这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天
三、RDB持久化
RDB=RedisDataBase
RDB是Redis持久化方式之一,这也是Redis优于memoryCache的一大特征
1、RDB文件的创建与载入
SAVE和BGSAVE两个命令可以将当前内存里的数据保存到磁盘上,进行持久化。
但是SAVE会阻塞线程,BGSAVE=background_save,是创建一个子进程来处理保存命令。
注意:AOF保存的频率比RDB高,所以当AOF和RDB同时需要还原数据的时候,优先使用AOF来进行。也就是说,只有AOF持久化关闭的时候才会使用RDB进行持久化。
BGREWRITEAOF
执行一个 AOF文件 重写操作。重写会创建一个当前 AOF 文件的体积优化版本。
即使 BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 BGREWRITEAOF 成功之前不会被修改。
重写操作只会在没有其他持久化工作在后台执行时被触发,也就是说:
- 如果 Redis 的子进程正在执行快照的保存工作,那么 AOF 重写的操作会被预定(scheduled),等到保存工作完成之后再执行 AOF 重写。在这种情况下, BGREWRITEAOF 的返回值仍然是 OK ,但还会加上一条额外的信息,说明 BGREWRITEAOF 要等到保存操作完成之后才能执行。在 Redis 2.6 或以上的版本,可以使用 INFO 命令查看 BGREWRITEAOF 是否被预定。
- 如果已经有别的 AOF 文件重写在执行,那么 BGREWRITEAOF 返回一个错误,并且这个新的 BGREWRITEAOF 请求也不会被预定到下次执行。
从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。
因为SAVE执行期间所有操作时阻塞的,所以不存在先后问题。
BGSAVE执行期间,如果有BGREWRITEAOF命令,则等待,如果在BGWRWTIEAOF执行期间,则BGSAVE命令会被拒绝。
2、自动间隔性保存
服务器可以自间隔调用BGSAVE来进行RDB持久化,可以配置多个条件
Save 时间 更新数据量
Save 900 1
Save 60 1000
以上的设计很人性化,既兼顾了性能,又可以在数据大量更改的时候能够及时持久化,防止内存雪崩引发宕机导致数据不一致
服务器会位置一个saveparams的数组,就是上面的参数,还会位置一个dirty计数器,一个lastsave属性。
dirty计数器:在上一次save完毕以后更新的数据量
lastsave属性:上一次成功执行save命令的时间戳
dirty和lastsave组合在一起就可以保证saveparams数组里的时间以及数据量参数能有效的运行。数据库每隔100ms进行一次检查,来保证数据的自动保存
3、RDB文件结构
| REDIS | db_version | SELECTDB | 0 | pairs | eof | check_num |
|---|
REDIS:固定字符,标志当前为RDB文件
db_version:RDB文件版本号
SELECT:固定字符,表示之后会读取一个数,这个数就是哪一个数据库
0:0号数据库
paris:数据真正储存的地方
Pairs就是各种数据结构
1、字符串
- REDIS_ENCODING_INT
| ENCODING | integer |
|---|
| REDIS_RDB_ENC_INT8 | 123 |
|---|
- REDIS_ENCODING_RAW
如果字符串长度小于等于20字节则不被压缩,否则压缩储存(压缩是要打开RDB压缩功能)
无压缩
| len | string |
|---|
压缩
| REDIS_RDB_ENC_LZF | compressed_len | origin_len | compressed_string |
|---|
REDIS_RDB_ENC_LZF:表示后面的字符串使用的是LZF压缩算法
compressed_len:压缩以后的长度
origin_len:压缩之前的长度
compressed_string:压缩以后的字符串
2、列表
| REDIS_ENCODING_LINKEDLIST | list_length | item1 | item2 | ... | itemn |
|---|
list_length:list的长度
item:本质还是一个字符串,储存方式与上面字符串的储存方式相同
3、集合
| REDIS_ENCODING_HT | set_size | elem1 | elem2 | ... | elemN |
|---|
set_size:集合内容的数量
elem1:依旧以字符串的形式保存
4、哈希表
| REDIS_ENCODING_HT | hash_size | key_value_pair1 | key_value_pair2 | ... | key_value_pair N |
|---|
hash_size:哈希表数量
key_value_pair:key和value都以String的方式储存
5、有序集合
| REDIS_ENCODING_SKIPLIST | sorted_set_size | element1 | element2 | ... | elementN |
|---|
sorted_set_size:有序集合的大小
Element
| member1 | score1 | member2 | score2 | member3 | score3 |
|---|
member1:有序集合的成员,字符串形式保存
member2:有序集合的分数,字符串形式保存
6、INTSET集合的编码(set)
之前的学习中,以上的五中数据结构都有两种(字符串三种)实现方式,那么如果set集合是使用整数集合来实现的,那么RDB会全部转为字符串,然后读取的时候会根据type的值来还原整数集合
7、ZIPLIST编码的列表,哈希表以及有序集合(list,hash,zset)
1、将压缩列表转换为字符串对象
2、将转换所得的字符串对象保存到RDB文件
读取的话,如果遇到压缩对象转换成的字符串对象,程序会根据type的值转换先转换为压缩对象,然后根据type的信息,把他们转为各自的数据结构