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
节点的replid
offset
偏移量,随着记录在repl_baklog
中的数据增多而逐渐增大,slave
完成同步时也会记录当前同步的offset
,如果slave
的offset
小于master
的offset
,则说明slave
数据落后于master
,需要更新- 基于
replid
判断主从是否一致,如果不一致则表明是第一次同步
全量同步的流程:
slave
节点请求增量同步master
节点判断replid
,不一致,则拒绝增量同步master
将完整内存数据生成RDB
,发送到slave
slave
清空本地数据,加载master
的RDB
master
将RDB
期间的命令记录在repl_backlog
,持续将log
中的命令发送给slave
slave
执行接收到的命令,保持与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
,让节点称为master
sentinel
给其他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!