2 RDB(Redis database)- 全量写入
Redis Server在有多db 中存储的K.V可理解为Redis的一个状态。当发生写操作时,Redis就会从一个状态切换到另外一个状态。
基于全量的持久化就是在某个时刻,将Redis的所有数据持久化到硬盘中,形成一个快照。快照,顾名思义可以理解为拍照一样,把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可,不像 AOF,一条条的执行操作命令。
当Redis 重启时,通过加载最近一个快照数据,可以将 Redis 恢复至最近一次持久化状态上。
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。
2.1 触发方式
save
- 客户端显示触发
- 或客户端发送 shutdown 命令,系统会先执行 save 命令阻塞客户端,然后关闭服务器
save本身是
单线程串行
方式执行,因此当数据量大时,可能会发生Redis Server的长时间卡顿。
其备份期间其他命令全部阻塞,无法执行,因此备份时期
数据的状态始终一致
。
若存在老的RDB文件,则新的会替换老的,时间复杂度O(N)。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SMzMTZwUTO5UmZ3IzNzADOyAzY0kzMmFzYihjMhdTM58CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
设置 redis.conf
再使用脚本初始化 500w 数据,等待后发现已经落盘:
bgsave
bgsave 可由
- 客户端显式触发
- 配置定时任务触发
- 当有主从架构时,从服务器向主服务器发送 sync 命令来执行复制操作时,主服务器会执行 bgsave
bgsave命令在执行时,会fork一个子进程。子进程提交完成后,会立即给客户端返回响应,备份操作在后台异步执行,期间不会影响Redis的正常响应。
对于bgsave来说,当父进程Fork完子进程之后,异步任务会将当前的内存状态作为一个版本进行复制。在复制过程中产生的变更,不会反映在这次备份当中。
不用命令,而使用配置
在Redis的默认配置中,当满足下面任一条件,会自动触发 bgsave 的执行:
bgsave相对于save的优势是
异步执行
,不影响后续命令执行。但Fork子进程,涉及父进程的内存复制,会增加服务器内存开销。
当内存开销高到使用虚拟内存时,bgsave的Fork子进程会阻塞运行
,可能会造成秒级不可用。因此使用bgsave需要保证服务器空闲内存足够。
2.2 RDB执行流程
rdb.c文件执行流程:
2.3 RDB 最佳配置
关闭自动RDB:
dbfilename dump-${port}.rdb
dir /redisDataPath
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
需要注意的触发时机
- 主从复制时机的全量复制,master节点会执行bgsave
- debug reload
- shutdown
- flushDB 、 flushAll
2.4 RDB性质
- RDB是Redis内存到硬盘的快照,用于持久化
- save通常会阻塞Redis
- bgsave不会阻塞Redis,但会fork新进程
- save自动配置满足任一就会被执行
2.5 RDB 优点
-
紧凑压缩的二进制文件
RDB会生成多个数据文件,每个文件都代表了某时刻Redis中的所有数据,这种方式非常适合做冷备。可将这种完整数据文件发送到云服务器存储,比如ODPS分布式存储,以预定好的备份策略来定期备份Redis中的数据
-
fork子进程性能最大化
RDB对Redis对外提供的读写服务,影响非常小,可让Redis保持高性能,因为Redis主进程只要fork一个子进程,让子进程执行RDB
-
启动效率高
相对于AOF,直接基于RDB文件重启和恢复Redis进程,更加快速
2.6 RDB缺点
耗时
O(n)
写时复制(copy-on-write)
耗内存,copy-on-write策略。RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。
执行 fork 时,os会使用写时复制,即 fork 函数发生的一刻父子进程共享同一内存数据。当父进程要更改其中某片数据时(如执行一个写命令),os会将该片数据复制一份以保证子进程数据不受影响,所以新的 RDB 文件存储的是执行 fork 一刻的内存数据。
不可控
容易丢失数据。一般RDB每隔5分钟,或者更长时间生成一次,若过程中Redis宕机,就会丢失最近未持久化的数据
2.7 恢复流程
当Redis重新启动时,会从本地磁盘加载之前持久化的文件。当恢复完成之后,再受理后续的请求操作。
4 选型及最佳实践
混合持久化
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,通过配置项
aof-use-rdb-preamble
开启)。
如果把混合持久化打开,AOF 重写时就直接把 RDB 内容写到 AOF 文件开头:
- 好在可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多数据
- 但是,AOF 里的 RDB 部分就是压缩格式不再是 AOF 格式,可读性较差
RDB最佳策略
- 关闭
- 集中手动管理RDB操作
- 在从节点打开自动执行配置,但是不宜频繁执行RDB
AOF最佳策略
- 建议打开,但是如果只是纯作为缓存使用可不开
- AOF重写集中管理
- everysec
抉择RDB & AOF
不要仅使用RDB,因为那样会导致丢失很多数据
也不要仅使用AOF,因为那样有两个问题
你通过AOF做冷备,没有RDB做冷备,来的恢复速度更快
RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug
综合使用AOF和RDB
用AOF保证数据不丢失,作为数据恢复的第一选择
用RDB做不同程度的冷备,在AOF文件都丢失或损坏不可用时,还可使用RDB快速实现数据恢复
一些最佳实践
-
小分片
例如设置maxmemory参数设置每个redis只存储4个G的空间,这样各种操作都不会太慢
- 监控(硬盘、内存、负载、网络)
- 足够的内存
参考
- https://redis.io/topics/persistence
- 《Redis设计与实现》