首页 > 技术文章 > Redis的持久化机制

yhq1314 2018-11-22 14:55 原文

持久化机制

RDB:快照模式
AOF :日志模式

多数据库
– 一个redis服务器内部默认有16个数据,编号О0-15
– 默认操作是编号为0的数据库
– 可以在命令行用select选择数据库
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
OK
--多个数据库是隔离开的,不影响key
通过save命令实现持久化
-客户端发送save命令
-服务器端收到命ј并执行后,会阻塞客户端的请求
127.0.0.1:6379[1]> save
O
[root@hongquan1 ~]# cd /etc/redis/
-rw-r--r-- 1 root root 36 Apr 11 06:39 dump.rdb

通过bgsave命令
-可以在命令行触发
--命令行执行bgsave,立即触发执行
-可以通过服务器端条件触发
• save seconds ops即͹在seconds秒内发生ops次数数据变化 就会触发RDB持久化操作
• Save 900 1 代表在900秒内有一次数据变更操作就触发持久化
• 可以同时配置多条触发条件
127.0.0.1:6379[1]> bgsave
Background saving started
通过过bgsave命令
– 通过fork一个子进程进行保持操作,所以bgsave不会阻塞客户端请求
– 父进程负责处理客户端请求,父子程通过fork的copy on write技术进行数据同步
– 在bgsave执行期间,客户端发送的save和bgsave命令将会被拒绝
– BGREWITEAOF命令和bgsave命令不能同时执行,如果这时正在执行bgsave命令,则只有执行完成后才会接着执行BGREWITEAOF
原理
• Redis有一个周期性函数每隔100ms执行一次,此函数名叫serverCron,此函数的其中一个检测项就是save配置
• 服务器端维护两个属性:dirty,即上次保存数据库发生多少次操作ͺlastsave,即上次执行操作的时间
RDB配置项
– stop-writes-on-bgsave-error true当在bgsave执行出错时,阻止前面的请求,默认是true
– Rdbcompression yes是否对RDB文件进行压缩,默认是yes
– rdbchecksum yes是否对rdb文件进行校验,默认是yes
– dbfilename dump.rdb rdb文件名
– dir ./ RDB文件存储目录,必须是目录
# save ""

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./
[root@hongquan1 redis]# find / -name dump.rdb
/etc/redis/dump.rdb
/root/dump.rdb
/dump.rdb
/home/mysql/backup/binlogbk4/dump.rdb
/usr/local/redis/src/dump.rdb

RDB存储结构
redis5种数据类型,无论是key还是value,存储后的类型都为REDIS_RDB_TYPE_STRING

AOF持久化
– AOF即Append Only File,保持redis的执行命令来记录数据
– 重新加载时,通过重放这些命令来实࣫数据的恢复
– 文件里面的命令是纯文本格式,可以直接打开观察里面的内容
– 整个过程中只有一个文件,通过重写技术缩减此文件的大小
– 命令执行成功后才会写入AOF文件
AOF写入原理
– 1.客户端发送请求
– 2.服务器端处理请求,如果是写请求,则把请求转换为操作命令放入aof缓存队列
– 3.当redis的主进程主线程重新进入循(时即处理完一次事件请求,重新进入下一次事件)时,进行相关处理(其中一件з情就是检查aof_buf)
– 4.把aof_buf中的命令写入文件
– 5.根据同步配置策略把文件内容村入磁盘
• Alaways:立即进入磁盘
• Everysec:每秒进入一次 ,默认
• No,操作系统自己决定什么时候进入

AOF配置
– Aof和rdb可以同时配置------/usr/local/redis/src/redis-cli config set appendonly yes
– appendonly no //是否开启aof,默认是不开启
– appendfilename "appendonly.aof" //aof文件名
– appendfsync everysec //aof文件进入磁盘的策略
– no-appendfsync-on-rewrite no //当正在做rdb的save或者aof的重写时,不要强行做磁盘刷新,会严重影响性能
– auto-aof-rewrite-percentage 100 //百分比,当前aof文件超过最后一次rewirteեaof文件的多少(百分比)触发aof文件的rewrite操作,比如上一次rewrite后为50m,百分比配置为100,则当前aof文件达到
100m后会触发aof的rewrite操作
– auto-aof-rewrite-min-size 64mb //根据percentage触发rewrite的aof最小值,即:即使满足触发的百分比,如果aof文件也达不到64m,也不会触发
– aof-load-truncated yes //
• 当aof文件出࣫损坏时是否加载,此种损坏是由于操作系统的文件系统导致,不是redisߎ身导致
• Yes表示加载,redis会尽量加载最全的时间,并且在日志中提示出࣫问题了
• No表示不加载,会导致redis启动失败
Redis启动数据加载
-服务器判断是否开启了aof配置,如果开启则使用aof恢复数据,如果没有则采用rdb进行恢复
-服务器内部启动一个伪客户端,通过伪客户端来重放aof文件里面的命令实现恢复
[root@hongquan1 /]# find / -name appendonly.aof
/appendonly.aof
/usr/local/redis/src/appendonly.aof
[root@hongquan1 redis]# tail -n 100 63079.log

AOF重写
背景:大量的写操作会导致aof文件膨胀,主要是某些数据的中间状态状态比较多导致
并不是对࣫有aof文件进行读再再合并等操作,而是把当前redis的数据库重写做一次aof,比如
为了避免重写时导致客户端输入缓冲区溢出,当处理列表 哈希表 集合 有序集合时,如果长度超过64个,则分成多条语句来
执行,64个是通过常量redis.h/REDIS_AOF_REWRITE_PER_CMD配置
AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次

AOF重写原理
在重写过程中如何保证可以继续接收客户端命令,又能保证数据一致性
– 不阻塞客户端命令请求:通过子进程进行重写操作
– 保证数据一致性:增加aof重写缓冲区,即启动冲写子进程后,所有变更的数据操作都要写入冲写缓冲区
– 触发时机
• 客户端执行:bgrewriteaof
• 满足auto-aof-rewrite-percentage
127.0.0.1:6379[1]> bgrewriteaof
Background append only file rewriting started
--6379.log
23387:C 11 Apr 07:36:52.524 * AOF rewrite: 0 MB of memory used by copy-on-write
22828:M 11 Apr 07:36:52.603 * Background AOF rewrite terminated with success
22828:M 11 Apr 07:36:52.603 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
22828:M 11 Apr 07:36:52.603 * Background AOF rewrite finished successfully
[root@hongquan1 etc]# find / -name appendonly.aof
/appendonly.aof

写操作的流程
首先我们来看一下数据库在进行写操作时到底做了哪些事,主要有下面五个过程。

1客户端向服务端发送写操作(数据在客户端的内存中)
2数据库服务端接收到写请求的数据(数据在服务端的内存中)
3服务端调用write(2) 这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)
4操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)
5磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)
故障分析上面的5个流程看一下各种级别的故障。
当数据库系统故障时,这时候系统内核还是OK的,那么此时只要我们执行完了第3步,那么数据就是安全的,因为后续操作系统会来完成后面几步,保证数据最终会落到磁盘上。
当系统断电,这时候上面5项中提到的所有缓存都
写操作大致有上面5个流程,下面我们结合会失效,并且数据库和操作系统都会停止工作。所以只有当数据在完成第5步后,机器断电才能保证数据不丢失,
在上述四步中的数据都会丢失。
通过上面5步的了解,可能我们会希望搞清下面一些问题:

数据库多长时间调用一次write(2),将数据写到内核缓冲区
内核多长时间会将系统缓冲区中的数据写到磁盘控制器
磁盘控制器又在什么时候把缓存中的数据写到物理介质上
对于第一个问题,通常数据库层面会进行全面控制。而对第二个问题,操作系统有其默认的策略,但是我们也可以通过POSIX API提供的fsync系列
命令强制操作系统将数据从内核区写到磁盘控制器上。对于第三个问题,好像数据库已经无法触及,但实际上,大多数情况下磁盘缓存是被设置关
闭的。或者是只开启为读缓存,也就是写操作不会进行缓存,直接写到磁盘。建议的做法是仅仅当你的磁盘设备有备用电池时才开启写缓存。

推荐阅读