Redis持久化、复制
持久化
RDB
把当前进程数据生成快照保存到硬盘
触发机制
- 手动触发:
save:阻塞Redis,知道RDB完成,线上环境不建议使用
bgsave:Redis进程fork子进程,RDB由子进程完成,阻塞发生在fork阶段
- 自动触发:
- save m n配置,m秒内数据集存在n次修改时触发bgsave
- 从节点执行全量复制,主节点自动执行bgsave并将RDB文件发给从节点
- debug reload命令重新加载redis
- 默认执行shutdown时,如果没有开启AOF,则自动执行bgsave
执行流程
- 执行bgsave,父进程判断是否存在正在执行的子进程,存在则直接返回
- 父进程fork子进程,父进程阻塞,info stats可查看latest_fork_usec选项,获取最近fork耗时微秒
- fork结束,bgsave命令返回“Background saving started”,不阻塞父进程,继续响应其他命令
- 子进程创建RDB文件,根据父进程内存生成临时快照,完成后对原有文件原子替换。lastsave可获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项
- 进程发送信号给父进程表示完成,父进程更新统计信息,info Persistence下的rdb_*选项
RDB文件处理
RDB文件保存在dir配置铺路下,文件名为dbfilename
可通过如下命令动态执行
- config set dir {newDir}
- config set dbfilename {newFileName}
遇到坏盘或磁盘写满的情况,可以用上述命令在线修改文件路径到可用磁盘路径,然后bgsave进程磁盘切换
redis默认使用LZF算法压缩RDB文件,压缩后远小于内存,默认开启,通过config set rdbcompression{yes|no}动态修改,压缩会消耗CPU,但便于保存和发送,线上建议开启
RDB文件损坏,可使用redis-check-dump工具检测
RDB优缺点
- 优点:
- 紧凑压缩的二进制文件,代表某个时间点上的数据快照,适用于备份,全量复制
- RDB加载恢复远远快于AOF方式
- 缺点:
- 没法做到实时持久化/秒级持久化。bgsave每次运行都要fork子进程,属于重量级操作
- RDB使用特定二进制格式,老版本Redis可能无法兼容新的RDB格式
AOF
AOF:append only file
以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。
AOF主要解决了数据持久化的实时性
使用
配置
- appendonly yes 默认不开启
- appendfilename AOF文件名,默认appendonly.aof
工作流程
graph TB
a1(命令写入) -- append --> a2(AOF缓冲)
a2 -- sync --> a3(AOF文件)
a3 -- rewrite/load --> a3
a3 -- load --- a4(重启)
- 所有的写入命令追加到aof_buf缓冲区中
- AOF缓冲区根据对应的策略向硬盘做同步操作
- 随着AOF越来越大,需要定期对AOF文件重写达到压缩目的
- redis重启时,加载AOF文件进行数据恢复
命令写入
AOF命令直接写入文本协议格式
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
- 使用文本协议格式
- 文本协议兼容性好
- 开启AOF后,所有写入命令都包含追加操作,直接用协议格式,避免二次处理开销
- 可读性好,便于直接修改
- 命令追加到aof_buf中
- 减轻硬盘负载
- redis可以提供多种缓冲区同步硬盘的策略,平衡性能和安全
文件同步
AOF缓冲区同步文件策略,由appendfsync控制,不同的值对应命令写入aof_buf后不同的处理方式:
| 值 | 说明 |
|---|---|
| always | 调用系统fsync同步到AOF文件,fsync完成后线程返回 |
| everysec | 调用系统write,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次 |
| no | 调用系统write,不对AOF文件做fsync同步,同步硬盘由OS负责,通常同步周期最长30秒 |
write出发延迟写(delayed write)机制
fsync针对单个文件做强制硬盘同步,阻塞直到写入硬盘完成后返回
everysec是建议的同步策略也是默认配置,兼顾性能和数据安全。理论上只有在系统突然宕机的情况下丢失1秒的数据。
重写机制
AOF引入重写来压缩文件体积。
AOF文件重写,是把Redis进程内额数据转化为写命令同步到新AOF文件的过程
重写后变小原因如下:
- 进程内已超时的数据不再写入文件
- 旧的AOF文件含有无效命令,重写使用进程内数据直接生产,新的AOF文件只保留最终数据的写入命令
- 多条写命令可以合并为一个
AOF重写触发:
- 手动触发:
bgrewriteaof - 自动触发: 根据配置确定
- auto-aof-rewrite-min-size:运行AOF重写时文件最小体积,默认64MB
- auto-aof-rewrite-percentage:当前AOF文件空间(aof_curremt_size)和上一次重写后AOF文件空间(aof_base_size)的比值
AOF详细流程:
重启加载
- AOF开启且存在AOF文件,优先加载AOF
- AOF关闭或者AOF文件不存在,加载RDB文件
- 加载AOF/RDB成功后,Redis启动
- AOF/RDB文件存在错误时,Redis启动失败
文件校验
加载损坏的AOF文件拒绝启动
错误的AOF文件,先备份,然后redis-check-aof –fix进行修复,修复后diff-u对比差异,找出丢失数据,有些可以人工补全。
机器突然掉电可能导致AOF尾部文件命令写入不全。Redis提供aof-load-truncated配置兼容之,默认开启
复制
配置
建立复制
参与复制的Redis划分为master节点和slave节点。默认都是master节点,每个salve只能有一个master。
复制的数据流只能从master复制到slave
配置方式:
- 配置文件中加入slaveof {masterHost} {masterPort}随Redis启动生效
- redis-server启动加入命令行 –slaveof {masterHost} {masterPort}
- 直接使用命令 slaveof {masterHost} {masterPort}
slaveof配置都是在从节点发起
主从节点复制成功建立后,使用info replication 查看复制相关状态
复制断开
命令:slave节点执行 slaveof no one
- 断开与master节点复制关系
- slave节点晋升为master节点
切换master节点:slaveof {newMasterIp} {newMasterPort}
切换master节点会清空之前所有的数据
安全性
master节点设置requirepass参数进行密码验证,这是客户端必须使用auth命令校验。
slave与master的复制连接通过一个特殊标识的客户端完成,需要配置slave节点的masterauth参数与master密码一致。
只读
默认slave使用slave-read-only=yes配置为只读模式。
修改slave节点会造成主从数据不一致。线上建议不要修改slave的只读模式
传输延迟
repl-disable-tcp-nodelay参数用于控制是否关闭TCP_NODELAY,默认关闭
关闭时,master数据无论大小都及时发给slave,这样主从延迟变小,但增加了带宽消耗,适用主从网络良好
开启时,master合并较小的TCP包节省带宽,发送间隔取决于Linux内核,一般默认40ms。
拓扑
Redis复制拓扑结果支持单层或多层复制关系。
一主一从
用于master宕机时slave提供故障转移支持。
如果只在slave节点开启AOF,需要注意主节点脱机避免自动重启,因为master没开启持久化重启后数据位空。
可以在slave执行slaveof no one断开复制,然后重启master
一主多从
也称星形拓扑
使得应用端利用多个slave节点实现读写分离。对于读占比大的场景,把读发送到slave分担master压力
树状主从
slave可以做为其他slave的master继续向下层复制
树状主从可以降低主节点压力
原理
复制过程
在slave执行slaveof命令后,复制过程便开始运作
保存master信息
master的ip和port被保存下来,但是master的连接状态是下线状态
master_link_status:down
主从建立网络连接
slave内部的定时任务发现存在新的master节点,则尝试建立网络连接
如果无法建立连接,则定时任务无限重试直到连接成功或者取消复制
失败可以在slave执行info replication查看master_link_down_since_seconds指标
发送ping命令
连接建立后slave发送ping请求首次通信
ping用于检测主从sockect是否可用以及master当前是否可接受处理命令
如果slave没收到master的pong回复或超时,则断开复制下次定时任务发起重连
权限验证
如果master设置了requirepass参数,slave必须配置masterauth参数保存密码相同
验证失败则复制终止,slave重新发起复制流程。
同步数据集
连接正常后,对于首次建立复制的场景,master把持有的数据全部发送给slave(耗时)
redis 2.8以后采用
psync进行数据同步命令持续复制
完成复制的建立流程后,接下来master持续把命令发送给slave,保证主从数据一致
数据同步
同部分全量复制和部分复制
全量复制:一般用于初次复制
部分复制:用于处理复制中因网络闪断等原因造成的数据丢失场景,当slave再次连上master后,如果条件允许,master会补发丢失数据给slave
psync命令运行需要以下组件支持:
- 主从节点各自复制偏移量
- master复制积压缓冲区
- master运行id
复制偏移量
参与复制的主从节点维护自身复制偏移量
info replication中的master_repl_offset指标中
slave每秒钟上报自身复制偏移量给master,master也会保存slave的复制偏移量
slave收到master发送的命令后,累计记录自身偏移量于info replication中的slave_repl_offset指标中
通过对比主从复制偏移量,判断主从数据是否一致
复制积压缓冲区
保存在主节点上的一个固定长度的队列,默认1MB
主节点运行ID
每个Redis节点启动后会动态分配一个40bit的16禁止字符串作为运行ID,唯一识别Redis节点。
运行ID变化后,从节点将做全量复制
info server命令查看当前节点运行ID
redis关闭再启动后,运行ID随之改变
debug reload可以重新加载RDB保持运行ID不变,避免不必要的全量复制。但是该命令会阻塞当前Redis节点主线程。谨慎使用。
psync命令
slave节点使用psync完成部分复制和全量复制。
psync {runId} {offset}
runId表示要复制的master的运行id
offset表示当前slave已复制数据的偏移量
全量复制
部分复制
心跳
异步复制
开发运维中的问题
- 读写分离
- 主从配置不一致
- 规避全量复制
- 规避复制风暴
1196

被折叠的 条评论
为什么被折叠?



