Redis持久化2大机制:AOF和RDB。
持久化
Redis是内存数据库,为了防止重启/宕机后数据丢失,因此需要持久化。
AOF
从以下几个方面熟悉AOF。
- 什么是AOF
- AOF写了什么
- AOF什么时候写
- AOF有什么缺陷以及如何解决的
什么是AOF
Redis在执行命令后,会记录日志存在磁盘中。
AOF写了什么
AOF记录的是命令。以set testkey testvalue为例。
- 命令三个部分
- $数字[命令或者键或者值分别几个字节]
- 分别是命令、键或值
*3
$3
set
$7
testkey
$9
testvalue
AOF什么时候写
AOF为写后日志。
为什么采用写后日志
对Redis,写后日志有2点好处。
- 先写入日志可能会有语法错误,为了避免额外的语法检查开销,因此写后日志可以避免错误命令。
- 避免阻塞写操作。
AOF写回策略
但AOF写回磁盘的时间很关键。如果没有及时记录日志,那么刚执行完命令就会有丢失风险。记录日志也可能会对下次操作带来阻塞风险。因此关注AOF的写回策略。
-
Always
同步写回 每个写命令都要落盘,性能影响大
-
Everysec
每秒写回 日志先写到内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘
-
No
操作系统控制的写回 先写到内存缓冲区,操作系统决定何时将缓冲区内容写回磁盘
写回策略体现了系统设计的trade-off取舍原则,这里在性能和可靠性之间取舍。
AOF有什么缺陷以及如何解决的
缺陷:文件存储,性能问题
AOF以文件形式记录所有写命令,因此可能会产生性能问题,在3个方面。
-
文件本身太大
-
写入效率会变低
-
重写缓慢
解决:AOF重写机制
因此这里引入了AOF重写机制。AOF重写机制的过程可以概括成一个拷贝,两处日志。
-
什么是AOF重写机制
如果一个键值被多条写命令反复修改时,会根据这个键值获取当前最新状态。
-
AOF重写过程
重写时候,主线程fork后台bgrewriteaof子进程执行了内存拷贝用于重写。如果这时有些操作,第一处日志就是正常的AOF日志,Redis会把操作写入AOF缓冲。第二处日志是AOF重写日志,这个操作也会被写入AOF操作缓冲,保证新写入数据不会丢失。
思考
-
AOF重写过程有哪些阻塞点
1.1 fork子进程
fork子进程需要拷贝内存页表,这个拷贝过程需要消耗大量CPU资源,拷贝完成之前整个进程是会阻塞的。除了必要的数据结构,fork不会一次性拷贝所有内存数据给子进程,采用的COW(Copy On Write)写时复制。
[内存页表]虚拟内存和物理内存的映射索引表。
1.2 AOF重写中父进程有写入场景
如果AOF重写,这时父进程操作一个已经存在的key,那么这个时候父进程会真正拷贝这个key对应的内存数据,因为内存分配是以页为单位分配的默认4k,如果父进程此时操作的是一个bigkey,重新申请大块内存耗时变长就会阻塞。
注:如果操作系统开启了内存大页机制(Huge Page,页面大小2M)那么父进程申请内存时阻塞的概率将会大大提高。所以可以关闭Huge Page。
fork生成RDB或AOF重写完成后,都可以在Redis log中看到父进程重新申请了多大的内存。
-
AOF重写为什么不复用AOF本身日志
2.1 为了避免重写失败导致AOF本身文件被污染
2.2 父子进程写同一个文件必然会产生竞争问题,如果要控制竞争会影响父进程性能。