Redis笔记_2
数据持久化
RDB
Redis Database Backup file(Redis数据备份文件),也叫做Redis数据快照。把内存中的所有数据都记录到磁盘中,故障重启后,从磁盘读取快照文件,恢复数据。RDB文件称为快照文件,默认保存当前运行目录
1 | redis-cli |
redis.conf配置RDB机制
1 | save 900 1 # 表示如果900s内至少有1个key被修改,则执行bgsave |
RDB的bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件- 但是
fork的过程是阻塞的,主进程此时不能处理别的请求。所以要加快fork过程
- 主进程操作虚拟内存,虚拟内存根据页表的映射关系到物理内存中真正的数据
fork仅仅是把页表做拷贝,即对映射关系做拷贝,因此子进程可以读取相同的数据,写入行的RDB文件- 为了避免在子进程读的时候主进程写,
fork采用的是copy-on-write技术- 主要是将物理内存标记成
read-only - 主进程读,则访问共享内存
- 主进程写,则拷贝一份数据,对副本执行写操作,写完后页表映射关系修改到副本
- 极端情况下就是所有数据都要拷贝一份,内存翻倍。所以一般情况下
Redis需要预留内存
- 主要是将物理内存标记成
-
RDB方式bgsave的基本流程fork主进程得到一个子进程,共享内存空间- 子进程读取内存数据并写入新的
RDB文件 - 用新的
RDB文件替换旧的RDB文件
-
RDB缺点RDB执行间隔时间长,两次RDB之间写入数据有丢失风险fork子进程、压缩、写出RDB文件比较耗时
AOF
Apppend Only File(追加文件),每一个写命令都会记录在AOF中,可以看作是命令日志文件- 默认关闭
1 | appendonly yes # 是否开启AOF功能,默认为no |
| 配置项 | 刷盘时机 | 优点 | 缺点 |
|---|---|---|---|
| always | 同步刷盘 | 可靠性高,几乎不丢数据 | 性能影响大 |
| everysec | 每秒刷盘 | 性能适中 | 最多丢失1s数据 |
| no | 操作系统控制 | 性能最好 | 可靠性较差,可能丢失大量数据 |
- 因为同时记录了命令和数据,所以
AOF会比RDB文件大很多,并且会记录同一个key的多次写操作,但是只有最后一次的写才有意义,因此可以执行bgrewriteaof命令,让AOF执行重写,用最少的命令达到原来操作相同的结果 - 可以在
redis.conf中配置AOF重写机制
1 | auto-aof-rewrite-percentage 100 # AOF文件比上次文件增占了多少百分比则触发重写 |
RDB VS AOF
| RDB | AOF | |
|---|---|---|
| 持久化方式 | 定时对整个内存快照 | 记录每次执行命令 |
| 数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
| 文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积大 |
| 宕机恢复速度 | 很快 | 慢 |
| 数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
| 系统资源占用 | 高,大量CPU和内存消耗 | 低,主要是磁盘IO资源,但是AOF重写会占用大量的CPU和内存资源 |
| 使用场景 | 可以容忍数分钟的数据丢失,更快启动速度 | 对数据安全性要求较高时常见 |
Redis主从集群
- 单节点
Redis并发能力有上限,进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离 - 启动三个
Redis服务,需要配置三台主从关系- 临时配置:
replicaof <masterip> <masterport> - 永久配置: 在
redis.conf中添加一行:replicaof <masterip> <masterport>
- 临时配置:
数据同步原理
- 主从第一次同步是全量同步,
slave重启后同步,则执行增量同步 - 如何判断是否第一次同步:
replication ID: 简称replid是数据集的标记,ID一致则说明是同一个数据集,每个master都有唯一的replid,slave则会继承master节点的replidoffset偏移量,随着记录在repl_baklog中的数据增多而逐渐增大,slave完成同步时也会记录当前同步的offset,如果slave的offset小于master的offset,则说明slave数据落后于master,需要更新- 基于
replid判断主从是否一致,如果不一致则表明是第一次同步
全量同步的流程:
slave节点请求增量同步master节点判断replid,不一致,则拒绝增量同步master将完整内存数据生成RDB,发送到slaveslave清空本地数据,加载master的RDBmaster将RDB期间的命令记录在repl_backlog,持续将log中的命令发送给slaveslave执行接收到的命令,保持与master之间的同步
repl_baklog大小有上限,写满后会覆盖最早的数据,如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次进行全量同步
优化主从集群:
- 在
master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO(一般是用于磁盘比较慢,但是网络较快的场景) Redis单节点上的内存占用不要太大,减少RDB导致的过多的磁盘IO- 减少全量同步的次数: 提高
repl_baklog的大小,发现slave宕机则尽快实现故障恢复,避免全量同步 - 限制一个
master上的slave数量,如果很多slave则使用主从从的链式结构,减少master压力
增量同步 VS 全量同步
- 全量同步:
master将完整内存数据生成RDB,发送到slave,后续命令记录在repl_baklog中,逐个发送给slave - 增量同步:
slave提交自己的offset到master,获取repl_baklog中从offset之后的命令给slave
哨兵Sentinel
作用
- 监控:
Sentinel不断检查master和slave是否按照预期工作 - 自动故障恢复: 如果
master故障,则Sentinel将slave提升为master,故障实例恢复后也会以新的master为主 - 通知:
Sentinel充当Redis客户端的服务发现来源,集群发生故障转移时,将最新的信息推送给Redis客户端
判断Redis是否健康
基于心跳机制监测服务状态,每隔1s向集群的每个实例发送PING命令:
- 主观下线
sdown: 某个sentinel发现节点实例没有在规定时间内响应,则认为其主观下线 - 客观下线
odown: 超过指定数量quorum的sentinel都认为该实例主观下线,则其客观下线,quorum最好超过sentinel的一半
主从切换选择依据
- 判断
slave节点与master节点断开时间长短,超过指定值down-after-milliseconds * 10会排除该slave节点 - 判断
slave节点的slave-prority越小优先级越高,如果为0则永不选举 - 如果
slave-prority则判断slave的offset值,越大越新,优先级越高 - 最后判断
slave节点的运行ID大小,越小优先级越高
故障转移
sentinel给slave1发送slaveof no one,让节点称为mastersentinel给其他slave发送slaveof ip port命令,让这些slave称为新的master从节点,开始从新的master上同步数据sentinel将故障节点标记为slave,故障节点恢复后悔自动成为新的master的slave
Redis分片集群
主从集群的问题:
- 海量数据存储
- 高并发写
分片集群特征
- 集群中有多个
master,每个master保存不同数据(并发写) - 每个
master可以有多个slave(并发读) master通过PING监测彼此健康状态- 客户端请求可以访问集群的任意节点,最终都会被转发到正确的节点
Redis会把每一个master映射到0~16383共16384个hash slot上,查看集群信息就可以看到
数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况
key中包含"{}“,且”{}“中至少包含一个字符,”{}"中的部分是有效部分key中国不包含"{}",整个key都是有效部分
利用CRC16算法得到一个哈希值,然后对16384取余,得到的结果就是slot值
如何将同一类数据固定的保存在同一个Redis实例中:- 这一类数据使用相同的有效部分,比如
key都以{typeID}为前缀
故障转移
集群中一个master宕机会发生什么?
- 实例与其他实例失去链接
- 疑似宕机
- 确定下线,自动提升一个
slave成为新的master
数据迁移
- 利用
cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave及诶单,实现无感知的数据迁移,具体流程为:
- 手动的
failover支持三种不同的模式:- 默认的流程,例如1~6
force省略了对offset的一致性校验takeover直接执行第五步,忽略数据一致性,忽略master状态和其他master意见
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sangs Blog!




