Redis高级(1) - 持久化
Redis高级 —- 持久化(1)
RDB
RDB就是Redis数据快照,其将Redis的数据本身保存到硬盘
如果直接使用save
来执行RDB,会阻塞所有命令
建议使用bgsave
,会开启子进程来执行RDB,避免主进程收到阻塞
RDB在Redis内部的使用
redis.conf中配置了默认的RDB机制
1 | # 开启RDB |
RDB原理
bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。
fork采用的是copy-on-write技术:
- 当主进程执行读操作时,访问共享内存;
- 当主进程执行写操作时,则会拷贝一份数据,执行写操作。
AOF
即追加文件,Redis处理的每一个写命令都会记录在AOF,可看作命令日志文件
AOF默认关闭,需要修改redis.conf配置文件来开启AOF:
1 | # 是否开启AOF功能,默认是no |
AOF的命令记录的频率也可以通过redis.conf文件来配:
1 | # 表示每执行一次写命令,立即记录到AOF文件 |
三种策略对比:
RDB与AOF对比
AOF文件重写
如果之前写入了a,然后又写入了a,会执行文件重写,将用最新的值替代之前的值
Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:
1 | # AOF文件比上次文件 增长超过多少百分比则触发重写 |
集群
数据同步原理
主从第一次同步数据是全量同步,从节点会从主节点中拉取所有数据bgsave(RBD)
新写的数据会使用AOF进行同步,将在RDB的时间内收到的命令在从节点中再执行一次(增量数据同步)
数据同步情况的判断
- Replication Id: 简称replid,是数据集的标记; slave会继承master的replid
- offset: 偏移量,若从节点offset小于offset,则说明从节点数据落后于主节点
主节点的增量同步数据若过长时间没有存入从节点,会导致溢出的数据覆盖原有数据,这时从节点要获取主节点数据就需要获取全量数据了
这个问题无法避免,只能尽量去优化,减少其出现的概率
数据同步的优化
- 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
- Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
- 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
- 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力
哨兵
上面的最基础的集群中,若主节点宕机了,那么整个服务就会陷入混乱; 这时就引入了哨兵Sentinel机制
哨兵负责衔接外部的请求和Redis集群,能为Redis访问提供正确的结点
服务状态监控
Sentinel的服务状态监控基于心跳机制,分为主观下线和客观下线
- 主观下线: 某个Sentinel节点发现某实例未在规定时间内响应,则将其记为主管下线
- 客观下线: 若超过某个数量(最好是过半哨兵)的哨兵都认为某个节点主观下线了,就将这个实例记为客观下线
选举
当发现master出现问题,就需要哨兵们选举新的master
- 首先判断slave和master断开时间的长短,若超过指定值则会将该slave排除
- 再判断slave的优先级,越小越高,0不参加选举
- 再判断offset值,越大说明越新,优先级更高
故障转移
- 哨兵给slave发送命令让该节点成为master
- 哨兵再给其余slave发送slave of (新主节点地址),让这些slave成为新的master的从节点
- 最后哨兵将故障的master节点标记为slave,若其在之后恢复正常了,会成为新master的从节点
哨兵集群搭建
跟搭建redis集群差不多,不赘述了
这里在搭建的时候,redis声明ip跟着文档填忘了改成自己的了,抓了一个多小时虫子…
分片集群
主从+哨兵实现了高可用高并发,但是仍然没有解决两个问题
- 海量数据存储
- 高并发写
使用分片集群可以结局上述问题, 分片集群的特征如下
- 集群中有多个master, 保存不同数据
- 每个master都有多个slave结点
- master之间互相ping来检测状态
- 客户端可以访问任意节点,最终会通过redis集群内部的路由转发到正确的节点
散列插槽
Redis会把每一个节点映射到一个插槽上,数据的key不与节点绑定,而是与插槽绑定; Redis会根据key来计算插槽值,然后把对应的值放到相应的插槽中, 实际上就是一个hash
集训伸缩
Redis集群支持动态的增加或者减少实例数量