前言
redis是内存数据库,不持久化数据就会丢失,两种持久化方式RDB与AOF
RDB
RDB是经过压缩的二进制文件,重点:SAVE命令和BGSAVE命令
SAVE和BGSAVE
- 两个命令都是执行rdbSave()函数,但是BGSAVE会fork一个子进程执行
- Redis服务器启动会自动加载rdb文件、或者AOF文件
- SAVE会阻塞所有客户端的命令
- BGSAVE会拒绝SAVE,同时延迟BGREWRITEAOF命令到BGSAVE完成以后
- BGREWRITEAOF会拒绝BGSAVE和SAVE,原因是性能考虑
save选项:持久化的条件
save 900 1
save 300 10
save 60 10000
满足任意一个条件,BGSAVE就会执行
服务器对象有一个saveparam对象数组用于记录时间和次数的条件,除此之外还有dirty计数器和lastsave属性,通过对比saveparam和dirty以及lastsave可以判断是否满足BGSAVE的使用,当然还要配合serverCron()定时任务
RDB文件结构
稍稍看一下就好,只需要知道二进制的形式保存键值对数据,然后不同的键类型和数据类型保存格式也不同,大体上是(元素个数 + 字符个数 + 字符 + 字符个数 + 字符)的形式。
总体
databases
合二为一
pairs
带有过期时间
对于不同的键值,redis有不同的方式保存
字符串对象
列表对象
集合对象
哈希对象
有序集合
intset编码的集合
会先将整数集合转化为字符串,读取的时候再根据REDIS_RDB_TYPE_SET_INTSET转化回来
ZIPLIST编码的列表、哈希、有序集合:
也会将压缩列表转化为字符串保存
AOF
aof全称append only file是另外一种持久化格式,与Redis二进制字符串存储键值对不同的是,aof直接用文本格式将执行过的命令保存下来。AOF持久化有三个步骤:append、write和sync
持久化策略
Redis服务器本身就是一个事件循环,循环的文件事件处理,循环的定时任务,我么可以通过配置appendfsync来选择AOF持久化的频率。
- Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
- Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
- No,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
AOF重写
因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的AOF文件很可能对Rdis服务器、甚至整个宿主计算机造成影响,并且AOF文件的体积越大,使用AOF文件来进行数据还原所需的时间就越多。
BGREWRITEAOF命令
首先AOF重写放在主线程中执行会造成长时间的阻塞,所以需要fork一个子进程来执行,这也就是BGREWRITEAOF的执行原理,步骤如下:
- 服务器正常执行写命令,该写入写入,该同步同步。
- 服务器同时fork一个子进程执行重写操作,且将写命令发送到AOF重写缓冲区保存重写过程中的新命令。(重写使用的是新的AOF文件)
- 重写完毕后,子线程将AOF重写缓存区的写命令发送到主线程,主线程写入新AOF文件
- AOF文件执行新旧替换
-
完成
讲一下为啥要不能写同一份AOF文件,因为如果重写失败,那数据不就丢失了,所以两份保险。