Redis是内存数据库,如果不进行持久化,一旦进程退出或宕机数据就会丢失
RDB
将数据写入.rdb(二进制文件)
save
优点:节约系统资源
缺点:直接调用 rdbSave,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求
bgsave
优点:fork出一个子进程,子进程负责调用rdbSave,并在保存完成之后向主进程发送信号,通知保存已完成。Redis服务器在bgsave执行期间仍然可以继续处理客户端的请求
缺点:由于会fork一个进程,因此更消耗内存
- 实现方式:
# 原理 1、Redis的save m n,是通过serverCron函数、dirty计数器、和lastsave时间戳来实现的。 2、serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次(redis.conf中默认:hz 10,表示1s内执行10次,也就是每100ms触发一次定时任务); 该函数对服务器的状态进行维护,其中一项工作就是检查save m n配置的条件是否满足,如果满足就执行bgsave。 3、dirty计数器是Redis服务器维持的一个状态,记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty重新置为0; 注意dirty记录的是服务器进行了多少次修改,而不是客户端执行了多少修改数据的命令。例如,如果Redis执行了set mykey helloworld,则dirty值会+1;如果执行了sadd myset v1 v2 v3,则dirty值会+3 4、lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。 5、save m n的原理如下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave。# 在redis.conf文件中配置 # 1、多条件设置,满足一条就会生效,触发bgsave save 1000 1 # 1000秒内至少1个key发生变化,则重写rdb文件 save 300 10 # 300秒内至少10个key发生变化... save 90 100 # 90秒内至少100个key发生变化... # 2、rdb的文件名,改为'dump-端口.rbd' dbfilename dump-${port}.rdb # 3、文件持久化目录,日志目录,改到分布式存储中或者放到较大的硬盘目录中。 dir /opt/data/ # 4、bgsave发生错误时停止写入 stop-writes-on-bgsave-error yes # 5、采用压缩方式,不然生成的rdb文件可能很大。压缩后主从复制拷贝文件小,速度也快。 rdbcompression yes # 6、在写入文件和读取文件时开启rdb文件检查 rdbchecksum yes - 其他触发机制
- 执行shutdown命令时,自动执行bgsave进行rdb持久化
- 在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行 bgsave 命令,并将rdb文件发送给从节点
AOF
将写操作追加到.aof文件(类似log文件)
策略
always:每条命令都会刷新到缓冲区,把缓冲区fsync到硬盘,对硬盘IO压力大。
everysec:每秒把缓冲区fsync到硬盘,如果出现故障,会丢失1s(默认配置是1秒)的数据,一般使用这种。
no:由操作系统来定什么时候fsync到硬盘中,缺点是不可控。
AOF重写
作用:减少硬盘占用量、加快恢复速度
实现方式:
# 原理 1、调用bgrewriteaof,fork一个子进程,子进程带有主进程的数据副本 2、之后的写操作命令都会被添加到旧aof文件(考虑性能此操作应禁止)以及aof_rewrite_buf_blocks重写缓冲中 3、在目前版本中,REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值为64, 当键中包含的值超过64个,设置键值对的命令将会被拆开 4、当子进程rewrite结束后,父进程收到子进程退出信号,把重写缓冲添加到rewrite后的文件中,旧文件关闭随即删除。 在整个rewrite过程中只有这个步骤对父进程造成阻塞,将影响降到了最低。 5、aofUpdateCurrentSize统计aof文件的大小,更新server.aof_rewrite_base_size,用于接下来判断aof增长率 6、bgrewriteaof的时候如果同时存在bgsave在备份,会推迟这次操作,待到bgsave结束后的下一次serverCron才会触发# 在redis.conf文件中配置 # 1、打开aof功能 appendonly yes # 2、‘当前aof文件’超过‘上次重写时aof文件’百分比时触发重写 auto-aof-rewrite-percentage 100 # 3、‘当前aof文件’超过设定值时触发重写,注意2和3须同时满足 auto-aof-rewrite-min-size 64mb # 4、重命名aof文件名,以端口号区分 appendfilename "appendonly-${port}.aof" # 5、使用everysec策略 appendfsync everysec # 6、在aof重写的时候,不做旧aof的append操作,这里出于性能考虑 no-appendfsync-on-rewrite yes # 7、redis在恢复时,忽略最后一条可能被截断的指令 aof-load-truncated yes
总结
RDB恢复速度快;但如果数据备份时宕机,会丢失两次持久之间的数据,数据量较大,而且备份时占用双倍内存
AOF文件越来越大,且恢复较慢;一般情况下设置每秒fsync,数据完整性与一致性较高,宕机只会丢失一秒的数据
建议RDB和AOF同时开启,但是恢复时Redis会优先使用从AOF来还原数据库,如果AOF关闭,则从RDB中恢复
Redis4新增了混合模式,当前数据以rdb写入,追加操作以aof写入。既不阻塞主进程,恢复速度又快,但不兼容之前的版本
# 在redis.conf文件中配置 aof-use-rdb-preamble yes
文档信息
- 本文作者:Weikang Yu
- 本文链接:https://AccelYu.github.io/2020/09/16/redis_two/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)