Redis高级入门篇
Redis入门高级入门篇
单点Redis的问题
- 数据丢失问题 —-Redis数据持久化
- 并发能力问题 —-主从集群,读写分离
- 故障恢复问题 —-Redis哨兵,健康监测/自动恢复
- 存储能力问题 —-搭建分片集群,利用插槽机制动态扩容
持久化
1.RDB(Redis快照)
RDB把内存中的所有数据都记录到磁盘中
执行时机
RDB持久化在四种情况下会执行:
- 执行save命令
- 执行bgsave命令
- Redis停机时
- 触发RDB条件时
1)save命令
save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。
2)bgsave命令
这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。
其开始时会fork主进程得到子进程,子进程共享主进程内的内存数据,完成fork后读取内存数据并写入RDB文件
fork采用的是copy-on-write技术
当主进程执行读操作时,访问共享内存
当主进程执行写操作时,则会拷贝一份数据再执行写操作
3)停机时
Redis停机时会自动执行一次save命令,实现RDB持久化。
4)触发RDB条件
Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:
1 | # 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB |
RDB的其它配置也可以在redis.conf文件中设置:
1 | # 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱 |
RDB缺点
- 执行间隔长,两次RDB之间数据写入有丢失风险
- fork子进程,压缩,写出RDB文件都需要消耗资源
2.AOF(追加文件)
Redis处理的每一个写命令都会记录在AOF文件,所以看做是某种命令日志文件
AOF配置
AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:
1 | # 是否开启AOF功能,默认是no |
AOF的命令记录的频率也可以通过redis.conf文件来配:
1 | # 表示每执行一次写命令,立即记录到AOF文件 |
三种策略的对比:
AOF文件重写
因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
如图,AOF原本有三个命令,但是set num 123 和 set num 666
都是对num的操作,第二次会覆盖第一次的值,因此第一个命令记录下来没有意义。
所以重写命令后,AOF文件内容就是:mset name jack num 666
Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:
1 | # AOF文件比上次文件 增长超过多少百分比则触发重写 |
RDB与AOF对比
在实际应用中要结合优缺点混合使用
Redis主从
单节点redis的并发能力是有上限的,需要通过搭建主从集群实现读写分离
主从间数据同步原理
- 主从第一次同步是全量同步
master是如何判断是否是第一次同步呢?
Replication Id:其是数据集的id,每个master都有唯一的repliid,slave则会集成master结点的replid
offset:偏移量,随着repl_backlog中数据增多而增大
所以slave的数据同步必须要向master生命自己的reliid和offset以供master判断需要同步哪些数据
- slave重启后同步,执行增量同步
注意:repl_baklog大小有上限,写满后会覆盖最早的数据,如果slave断开时间过久,导致尚未被备份的数据被覆盖,则无法基于log做增量同步,只能再次进行全量同步
Redis主从集群的优化
- 在master中配置repl-diskless-sync yse启动无磁盘复制,避免全量同步时的磁盘io
- Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
- 适当提高repl_baklog的大小,发现从节点宕机时尽快实现故障恢复,尽量避免进行全量恢复
- 限制一个master上的slave数量,如果slave确实多,可以采用主-从-从链式(从节点A是相对于其从节点B的master结点)结构,减轻master压力
Redis哨兵
哨兵(sentinel)的作用
- 监控:Sentinel会不断检查master和slave是否按照预期工作
- 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master,当故障实例恢复后也是以新的master为主
- 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新的消息推送给Redis的客户端
服务状态监控
Sentinel基于心跳机制检测服务状态,每隔1s向集群的每个实例发送ping指令
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认定该实例主观下线
- 客观下线:若超过指定数量quorum的sentinel都认为该实例主观下线,则该实例客观下线(quorum值最好超过sentinel实例数量的一半)
如何选举新的master
选举依据
- 首先判断slave与master结点断开时间的长短,如果超过指定值,就会排除该slave结点
- 然后判断slave结点的slave-priority值,越小优先局越高,若为0则用不参加选举
- 若slave-priority值一样,则判断slave结点的offset值,越大说明数据越新,优先级越高
如何实现故障转移
- 选定一个slave作为新的master,执行slaveof no one
- 让所有节点执行slaveof 新master
- 修改故障节点配置,添加slaveof 新master
Redis分片集群
分片集群结构
主从和哨兵可以解决高可用,高并发读的问题,但是依然没有解决海量数据存储和高并发写的问题
使用分片集群可以解决上述问题,其特征如下
- 集群中有多个master,每个master保存不同数据
- 每个master都可以拥有多个slave结点
- master之间通过ping检测彼此健康状态