高可用-持久化
Redis 的 RDB 持久化机制
RDB
将当前数据生成快照,并保存于硬盘中。可以通过手动命令,也可以设置自动触发。
原理是,进行持久化时,扫描当前所有的 dict
键值对,写到硬盘文件里。
对于比较大的 value
,不会一次性写入,会分批写入。通过一个 max_processing_chunk
变量控制每批写入的大小。
持久化期间哈希表扩容了怎么办?
哈希表扩容前会检查是否正进行持久化。如果正在进行的话扩容条件会变得更严苛(负载因子从1变为5),一般是不会扩容的。
简述 Redis 的 save 命令
save
命令是 redis
手动触发 RDB
过程的命令。使用该命令后,服务器阻塞,直到 RDB
过程完成后终止。该过程占用内存较多。
简述 Redis 的 bgsave 命令
bgsave
命令不阻塞主进程(也不是全程不阻塞,详看下面过程),该命令 fork
一个子进程用于执行 RDB
过程。其具体过程为:
判断此时有没有子进程用于
RDB
,有的话直接返回。redis
进行fork
子进程过程,此时父进程处于阻塞状态。子进程创建
RDB
文件,完成后返回给父进程
fork
进程会导致子进程复制父进程的的内存,如果父进程内存占用过大,复制一遍可能导致OOM
。此情况下linux
提供了一个参数/proc/sys/vm/overcommit_memory
,默认为0,会复制。可以改为 1,该参数使用了linux
的copy-on-write (COW)
写时复制机制,表示允许子进程共享父进程的内存,从而减少内存占用。
简述 Redis 自动触发 RDB 机制
通过配置文件,设置一定时间后自动触发
RDB
如采用主从复制过程,主节点自动执行
bgsave
生成RDB
并发送给从节点默认执行
shutdown
时,在未开启AOF
后会自动执行bgsave
简述 Redis 的 AOF
AOF
通过日志,对数据的写入修改操作进行记录。这种持久化方式实时性更好。可以通过配置文件打开 AOF
。
简述 AOF 的持久化策略
AOF
写日志时并不是直接写到硬盘上,而是先到 AOF
缓冲区,再写入硬盘。写入硬盘的时机可以配置三种:
always
。每执行一次数据修改命令就将其命令写入到磁盘日志文件上。everysec
。每秒将命令写入到磁盘日志文件上(默认)。no
。不主动设置,由操作系统决定什么时候写入到磁盘日志文件上。
简述 AOF 的重写
随着客户端不断进行操作,AOF
对应的文件也越来越大。redis
提供了 bgrewriteaof
函数, 把 redis
进程内的数据转化为写命令同步到新 AOF
文件,减小文件体积。可以通过配置设置自动触发阈值。
虽然名叫重写,但实际实现是和 rdb
类似的,会全量扫描所有 db
下的所有 dict
。对于比较大的 value
,也是分成多个命令写入文件。新文件写完后,再对其重命名,替换旧的 AOF
文件。
对重写期间发生变更的 kv
,redis
会将其追加到 AOF
缓冲区中,如果缓冲区大小不够,会申请新的空间。在重写结束后,再将缓冲区中的数据写到新的 AOF
文件中。
RDB 与 AOF 优缺点比较
RDB
原理为扫描 redis
的所有数据,全量导出到文件,导出的物理日志,内部用了 LZF
压缩,因此体积小。并且加载 RDB
恢复速度也远高于 AOF
。但实时性差。
AOF
原理是记录每条命令,是逻辑日志,备份对系统的消耗比较低,写入快,实时性好。但是体积大、用于恢复 redis 数据速度慢。
如果 redis
服务器开启了 AOF
,redis
会优先使用 AOF
来还原。只有 AOF
关闭时,服务器才会使用 RDB
来还原数据库状态。
参考
Last updated