头图

Redis 持久化

redis 是内存数据库,如果不将内存中数据库保存到磁盘上,那么服务器一旦宕机,或者 redis 进程退出,不仅数据会被丢失,服务器中的数据库状态也会被丢失

因此 redis 提供了持久化的功能

redis 的持久化分为 RDB 和 AOF

RDB (Redis DatabBase)

在主从复制中,rdb文件都作为备用的,放在从机上面

在指定时间间隔内将内存中的数据集快照写入到磁盘中,这就是快照 snapshot ,恢复快照的时候,是把快照文件读入到内存中。

redis 通过 fork 的方式创建一个子进程来专门做持久化的动作,

  • 先将数据写入到一个临时文件中,待持久化过程结束,再用这个临时文件替换上一次的持久化好的文件

整个过程中,主进程是不进行任务 IO 操作的,这就保障了极高的性能

如果需要进行大规模的数据恢复,且对于数据的完整性要求不那么敏感和严格,选择 RDB 的持久化方式比 AOF 的持久化方式更优,更加高效。

RDB 虽然性能高,但是在 最后一次持久化后的数据可能会被丢失,redis 默认就是使用的 RDB 持久化方式,一般情况下也不需要修改

save 60 3

# The filename where to dump the DB
dbfilename dump.rdb

dir ./

我们设置 60s 内若 有操作 redis 3 次,那就做一次持久化

127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config get dir
1) "dir"
2) "/root"
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK

dump.db 文件是生成在 dir 目录下的,我们这里的 dir 目录是 /root

进行上述操作之后,我们发现 /root 生成了 dump.rdb 文件 ,咱们将该文件删除掉,再尝试一次

root@iZuf66y3tuzn4wp3h02t7pZ:~# rm dump.rdb -rf
root@iZuf66y3tuzn4wp3h02t7pZ:~# redis-cli
127.0.0.1:6379> set p1 1
OK
127.0.0.1:6379> set p2 1
OK
127.0.0.1:6379> set p3 3
OK
root@iZuf66y3tuzn4wp3h02t7pZ:~# ls
dump.rdb

果然也是正常生成的

持久化的触发机制

  • 按照 save 的规则满足的情况下,就会触发持久化,例如上述的 60s 操作 redis 3 次就会触发 1 次持久化
  • 执行 flushall 命令的时候,也会触发持久化,生成 dump.db 文件
  • 退出 redis 的时候, 也会触发持久化,生成 dump.db 文件

备份就会自动生成一个 dump.db 文件

如何恢复持久化文件

1、只需要将 dump.db 文件放到 redis 的启动目录即可,redis 启动的时候会将该文件读入到内存中,进行数据恢复

2、查看 redis 的启动目录可以这样做

127.0.0.1:6379> config get dir
1) "dir"
2) "/root"

这一块的配置,我们基本上不需要修改太多,默认的配置基本就够用了

RDB 的优势

  • 适合大规模的数据恢复
  • 对数据的完整性要求不高

RDB 的劣势

  • 需要在一定的时间间隔进行操作,如果 redis 意外宕机,最后一次写入的数据就会丢失
  • fork 子进程的时候需要占用一定的空间

AOF 持久化方式

AOF 是什么?

将我们的写命令全部记录下来,恢复的时候,将文件中的记录全部执行一遍

AOF 是 redis 的另外一种持久化方式,以日志的形式记录每一个写操作,将 redis 执行过的写操作全部记录下来,只允许追加文件,不允许改写文件

redis 启动的时候就会读取这个 aof 文件重建数据库,也就是说,redis 重启的时候,就会根据日志文件的内容将写指令按照写入顺序执行,完成数据恢复

aof 保存的是 appendonly.aof 文件

# Please check https://redis.io/topics/persistence for more information.

appendonly no

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

# appendfsync always
appendfsync everysec
# appendfsync no

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-min-size 64mb

当 aof 文件大于 64 mb 的时候,就会再创建一个子进程来写一个新的 aof 文件

关于 aof 的配置基本上其他的都是使用默认的配置即可,我们只需要把 aof 模式打开即可

appendonly yes

默认 appendonly 是不开启的,我们修改了配置之后,重启 redis-server 就会马上生效

重写规则说明

aof 默认是对文件无限追加,文件必然会越来越大

修改 redis.conf 为 aof 模式后,重启 redis-server 可以看到 appendonly.aof 文件

redis 客户端连接 server 进行操作 redis ,简单的设置几个值

root@iZuf66y3tuzn4wp3h02t7pZ:/# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set name xiaozhu
OK
127.0.0.1:6379> set age 19
OK
127.0.0.1:6379> set hobby play
OK
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379> shutdown
not connected>

查看 appendonly.aof 文件

appendonly.aof 文件里面存放的就是我们操作 redis 的写命令的记录

这个时候,我们认为的在 appendonly.aof 文件中修改一些值

set
$2
k2
$2
v2
*3
$3
set
$2
k3
$2
ashdkklasdjkkv3        # 修改了这一行

启动 redis-server ,查看是否可以恢复数据

root@iZuf66y3tuzn4wp3h02t7pZ:/# redis-server /usr/local/redis/redis-6.2.5/redis.conf
root@iZuf66y3tuzn4wp3h02t7pZ:/# redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>
root@iZuf66y3tuzn4wp3h02t7pZ:/# ps axu |grep redis
root      1251  0.0  0.0  14436  1048 pts/0    S+   14:55   0:00 grep --color=auto redis
root@iZuf66y3tuzn4wp3h02t7pZ:/#

发现 redis-server 启动失败,是因为咱们的 appendonly.aof 文件被人为的修改过,此时咱们需要修复该文件,redis 有提供工具修改 aof 文件,redis-check-aof

使用指令:

redis-check-aof --fix appendonly.aof

# redis-check-aof --fix appendonly.aof
0x              ce: Expected \r\n, got: 6864
AOF analyzed: size=223, ok_up_to=181, ok_up_to_line=47, diff=42
This will shrink the AOF from 223 bytes, with 42 bytes, to 181 bytes
Continue? [y/N]: y
Successfully truncated AOF
root@iZuf66y3tuzn4wp3h02t7pZ:/# redis-server /usr/local/redis/redis-6.2.5/redis.conf
root@iZuf66y3tuzn4wp3h02t7pZ:/# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get k1
"v1"

修复 aof 文件后,咱们再次启动 redis-server 来回复磁盘数据,恢复成功,nice

aof 的优势和劣势

优势

  • 每一次操作 reids 都会被记录,文件的完整性好
  • 每秒同步一次,可能会丢失一秒的数据
  • 从不同步,这个效率是最高的

劣势

  • 相对于数据文件来说,aof 文件会远大于 rdb 文件,修复的速度也比 rdb 文件慢
  • aof 运行的效率比 rdb 慢,所以 redis 默认的配置是 rdb 持久化

小结

两种持久化方式简述

  • RDB 持久化的方式能够在指定的时间间隔内对数据进行快照存储
  • AOF 持久化的方式记录每次对服务器的写操作,当服务器重启或者宕机的时候,会重新执行这些记录里面的写操作命令来恢复数据,AOF 命令以 redis 协议追加保存每次写操作到文件末尾,redis 还能对 aof 文件进行后台重写,是的 AOF 文件的体积不至于过大
  • 如果需求是只做缓存,只期望服务器运行的时候数据存在,那么不用做持久化

两种持久化方式的开和不开

  • 可以同时开启两种持久化方式

    • 这种情况下,redis 重启会先载入 aof 文件来恢复数据,因为通常情况下 aof 文件保存的数据集比 rdb 的数据集要完整
    • rdb 数据集不是实时的,同时使用两种方式时,服务器重启有只会找 aof 文件,那么要不要只使用 aof 文件呢?

    redis 的作者建议是不要只使用 aof 文件,因为 rdb 更加适合用于备份数据库,因为 aof 在不断的变化,不好备份,快速重启的时候,rdb 不会有 aof 可能潜在的 bug,留着 rdb 做一个兜底的机制

性能上的建议

对于 rdb 持久化

  • 由于 rdb 文件只用于备份数据,建议只在 slave 上面持久化 rdb 文件,15 分钟持久化一次就够了,也就是这一条指令 save 900 1
  • 如果打开 aof 持久化,好处就是在极端情况下丢失数据也不会超过 2s 的数据,启动脚本就简单的加载自己的 aof 文件即可,这样做也是有代价的

    • 代价之一就是 这样做带来了持续的 IO 操作
    • 代价之二就是 AOF 重写的最后将重写过程产生新数据写入到新文件造成的阻塞是不可避免的,只要硬盘许可,应该要尽量的减少 aof 重写的频率

对于 aof 持久化

  • aof 重写的基础大小值是 64 mb,我们可以设置成 5g 以上,默认超过原大小 100% 大小重写,这个参数可以设置成一个合理的参数
  • 如果不打开 aof 模式,仅仅靠主从复制实现高可用也是可以的,能够省掉一大笔 IO 消耗,也减少了重写带来系统的性能波动,这样做仍然是有代价的

    • 代价之一就是 如果主备 redis 同时挂掉(例如断电),会丢失十几分钟的数据,启动脚本也要比较主备的 rdb 文件,载入较新的那个 rdb 文件

参考资料:

redis_doc

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~


阿兵云原生
192 声望37 粉丝