RDB
概述
保存某个时间点之前的二进制快照。
相关命令
SAVE/BGSAVE
- save阻塞主进程
- bgsave则是fork一个子进程,只会在fork时短暂阻塞,后面子进程生成RDB文件则不再阻塞)
下面是配置save point的示例:
// 配置save point
save 900 1 #900秒内有1个key发生了变化,则触发保存RDB文件
save 300 10 #300秒内有10个key发生了变化,则触发保存RDB文件
save 60 10000 #60秒内有10000个key发生了变化,则触发保存RDB文件
AOF
概述
所有命令行记录以redis命令请求协议的格式完全持久化存储为一个aof文件。
相关命令
BGREWRITEAOF - 手动触发执行一个AOF重写操作
AOF步骤
- 命令传播
redis将执行完的命令和参数、参数个数等信息发送给AOF程序
- 命令追加
当开启AOF后,服务器在每执行完一个写命令后会将被执行的写命令追加到服务器状态的aof缓冲区,即aof_buf的末尾。称为append操作。
- 文件写入、同步
当redis把数据写到aof缓冲区时,实际上还未真正落盘,在AOF保存条件被满足时,会触发执行fsync/fdatasync命令来进行强制刷盘,此时才真正将命令内容写入到磁盘中(持久化)。
AOF的几种模式
AOF_FSYNC_NO :不保存。
AOF_FSYNC_EVERYSEC :每一秒钟保存一次。
AOF_FSYNC_ALWAYS :每执行一个命令保存一次。
AOF重写机制简介
- 解决什么问题?
持久化能够有效地提高数据的安全性
- 带来的问题
随着运行时间的流逝, AOF 文件会变得越来越大。
- 命令如何重写?
比如服务器批量执行以下命令:
SADD user a
SADD user b c
SADD user d // result: [a b c d]
AOF重写后保存一条SADD a b c d命令即可。
- redis如何执行重写?
redis对于重写AOF的操作采用的是fork一个子进程的方式进行重写,但fork子进程进行重写可能带来一个问题:在子进程重写期间,主进程的接收的新命令有可能正是更改到现有数据。如何解决?
为解决这个问题,redis会在fork子进程后开启一个AOF重写缓存,在接收到新的写请求时也往缓存中追加,在子进程完成AOF重写并生成新的AOF文件后,主进程会将AOF重写缓存中的内容全部写到新的AOF文件,再将旧AOF文件进行替换,然后继续append。。
两者对比
- RDB 占用空间少,持久化能够快速地储存和恢复数据, 但是在服务器停机时却会丢失大量数据
- AOF 占用空间多,持久化能够有效地提高数据的安全性, 但是在储存和恢复数据方面却要耗费大量的时间
鱼与熊掌可以兼得:混合持久化(4.0后才有)
进行AOF重写时,会创建出一个同时包含RDB数据和AOF数据的AOF文件,而该文件的前半部分为RDB数据,记录了重写前时的数据库状态,而在重写后的数据则以执行redis命令以AOF格式append到文件尾部。
如何实现混合持久化?redis.conf配置如下:
appendonly yes
aof-use-rdb-preamble yes
混合后的生成的AOF文件示例:
$cat appendonly.aof
REDIS0008 redis-ver4.0.1
redis-bits@ctimeYused-memP
aof-preamblerepl-id(484f9d49a700c4b9b136f0fd40d2d6e5a8460438
repl-offsetfoobar?I Y*2
$6
SELECT
$1
0
*3
$3
set
$3
foo
$3
bar
可以看出前半部分是RDB格式全量数据,后半部分是redis命令请求协议格式的增量数据。
参考文献:
网友评论