文章目录

  • 分布式缓存
    • Redis持久化
      • RDB持久化
      • AOF持久化
    • Redis主从
      • Redis数据同步原理
        • 全量同步
        • 增量同步
    • Redis哨兵
      • 哨兵的作用和原理
        • sentinel(哨兵)的三个作用是什么?
        • sentinel如何判断一个Redis实例是否健康?
        • master出现故障后,新的master选择过程是怎样的?
        • 故障转移的步骤有哪些?
      • 项目中配置RedisTemplate哨兵模式
    • Redis分片集群
      • Redis散列插槽
      • Redis集群伸缩
      • 项目中RedisTemplate配置访问分片集群
  • Redis多级缓存
    • JVM进程缓存
      • Caffeine
        • Caffeine实现本地进程缓存案例
  • Redis实战经验
    • Redis键值设计
      • 优雅的key结构
      • 解决BigKey
      • 选择恰当的数据类型
    • 批处理优化
      • pipeline
      • 集群下的批处理
    • 服务端优化
      • 持久化配置
      • 慢查询
      • 内存配置

分布式缓存

单节点Redis存在着:

  • 数据丢失问题:单节点宕机,数据就丢失了。
  • 并发能力和存储能力问题:单节点能够满足的并发量、能够存储的数据量有限。
  • 故障恢复问题:如果Redis宕机,服务不可用,需要一种自动的故障恢复手段。

Redis持久化

RDB持久化

RDB(Redis database backup file,Redis数据库备份文件)



bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据,完成fork后,读取内存数据并写入RDB文件。fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。


AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。



Redis主从

Redis数据同步原理

全量同步

主从节点间的第一次同步采用的是全量同步,全量同步的流程如下:

  • slave节点请求增量同步
  • master节点判断replid,如果发现id不一致拒绝增量同步,id不一致说明是第一次同步,master会返回master的数据版本信息,尝试建立全量同步。
  • slave收到后,保存版本信息。
  • master节点执行bgsave,生成RDB,生成RDB期间的所有命令会保存在repl-backlog中,随后向slave发送RDB文件。
  • slave收到RDB文件后,清空本地数据,加载master节点发来的RDB文件。
  • 后序master节点会发送repl-baklog文件,slave收到后执行其中的命令,保持与master的数据同步。

增量同步

主从第一次同步是全量同步,但如果slave重启后同步,则执行增量同步

Redis哨兵

哨兵的作用和原理




sentinel(哨兵)的三个作用是什么?

  • 监控
  • 故障转移
  • 通知

sentinel如何判断一个Redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没响应,认为是主观下线
  • 如果超过一半的sentinel都认为实例主观下线,则判断服务客观下线。

master出现故障后,新的master选择过程是怎样的?

故障转移的步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有的节点都执行slaveof 新的master
  • 修改故障节点配置,添加slaveof 新的master

项目中配置RedisTemplate哨兵模式

步骤:

Redis分片集群

主从和哨兵可以解决高可用、高并发持续的问题,但是依然有两个问题没有解决:

  • 海量数据存储问题
  • 高并发读写的问题


分片集群中有多个master,每个master都可以有多个slave节点,master间通过ping监测彼此健康状态,此时就不再需要哨兵机制了。

Redis散列插槽

Redis会把一个master的节点映射到 0 – 16383个插槽上,数据的key不是与节点绑定,而是与插槽绑定。

Redis如何判断某个key应该在哪个实例?

  • 将16384个插槽分配到不同的实例。
  • 根据key的有效部分计算哈希值,对16384取余。
  • 余数作为插槽,寻找插槽所在的实例即可。

如何将同一类数据固定的保存在同一个Redis实例?

  • 这一类数据使用相同的有效部分,例如key都以{typeid}为前缀。

Redis集群伸缩

集群伸缩的概念就是动态添加和移除节点

项目中RedisTemplate配置访问分片集群

Redis多级缓存

多级缓存就是充分利用请求处理的各个环节,分别添加缓存,减轻Tomcat压力,提升服务性能。

  • 浏览器、客户端缓存
  • Nginx本地缓存
  • Redis缓存
  • Tomcat进程缓存


JVM进程缓存

Caffeine


Caffeine实现本地进程缓存案例


第一步:
构建缓存配置类,创建2个缓存的Bean对象:

第二步:
在使用的地方,将缓存对象注入,编写缓存查询和缓存未命中业务逻辑。

Redis实战经验

Redis键值设计

优雅的key结构

解决BigKey



选择恰当的数据类型

将大型的哈希表,进行拆表,拆解为小型的哈希表:

批处理优化

通过批处理执行,减少网络传输耗时。

pipeline


集群下的批处理


spring的Redistemplate已经提供了并行slot的集群下的批处理实现。

服务端优化

持久化配置

Redis持久化虽然可以保证数据安全,但也会带来很多额外的开销,因此持久化请遵循下列建议:

  • 用来做缓存的Redis实例尽量不要开启持久化,因为做缓存的数据只是为了加快响应速度,重要性没那么高。但是对于用来做分布式锁的数据,必须开启持久化,保证数据安全。
  • 建议关闭RDB持久化功能,使用AOF持久化。RDB持久化虽然文件占用更小,恢复更快,但是RDB在fork进程,生成RDB文件过程中,可能导致数据丢失。
  • 利用脚本定期在slave节点做RDB,实现数据备份

慢查询

内存配置