redis持久化

redis是一个内存数据库,为了保证数据的持久性,提供了两种方案

RDB方式(默认)

RDB方式是通过快照(snapshotting)完成的,当符合一定条件时会自动将内存中的数据进行快照并持久化到硬盘。

触发快照的时机

1.符合自定义配置的快照规则
2.执行save或者bgsave命令
3.执行flushall命令
4.执行主从复制操作(第一次)

原理

设置快照规则

save多少秒内 数据变了多少
save “”:不使用RDB存储
redis默认RDB配置:
save 900 1:表示15分钟(900秒)内至少1个键被更改则进行快照。
save 300 10:表示5分钟(300秒)内至少10个键被更改则进行快照。
save 60 10000:表示1分钟内至少10000个键被更改则进行快照。

注意事项

1.redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的。
2.我们可以通过定时备份RDB文件来实现数据库备份,RDB文件是经过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输。

优缺点

缺点

使用RDB方式持久化,一旦redis异常退出,就会丢失最后一次快照以后更改的所有数据。

优点

RDB可以最大化redis的性能,父进程在保存RDB文件时唯一要做的事情就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无需执行任何磁盘I/O操作。同时这也是一个缺点,如果数据集比较大的时候,fork可能比较耗时,造成服务器在一段时间内停止处理客户端的请求。

AOF方式

redis默认没有开启AOF(append only file),
开启AOF持久化后,每执行一条会更改redis中的数据的命令,redis就会将该命令写入磁盘中的aof文件,会降低redis性能,大部分情况这个影响是可以接受的,使用较快的硬盘可以提高AOF性能。

配置redis.conf

# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
dir ./
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof

RESP

redis客户端使用RESP(redis的序列化协议)协议与redis的服务器进行通信。虽然该协议是专门为redis设计的,但是该协议也可以用于其他客户端-服务器软件项目。
1.间隔符号,在Linux下是\r\n,在windows下是\n
2.简单字符串Simple Strings,以“+”加号开头
3.错误Errors,以“-”减号开头
4.整数型Integer,以“:”冒号开头
5.大字符串类型Bulk Strings,以“$”美元符号开头,长度限制512M
6.数组类型Arrays,以“*”星号开头

用SET命令说明RESP协议格式
127.0.0.1>SET mykey “Hello”
“OK”
实际发送请求数据:
*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$5\r\nHello\r\n

*3
$3
SET
$5
mykey
$5
Hello
实际收到响应的数据:
+OK\r\n

AOF文件存储的是redis命令

原理

redis将所有对数据库进行过写入的命令和参数记录到AOF文件,以此达到记录数据库状态的目的,为了方便起见,我们称呼这种记录过程为同步。
同步命令到AOF文件分三个阶段:
命令传播:redis将执行完的命令及其参数等信息发送到AOF程序中。
缓存追加:AOF程序根据接受到的命令数据,将命令转化为网络通讯协议的格式,然后将协议内容追加到服务器的AOF缓存中。
文件写入和保存:AOF缓存中的内容被写入到AOF文件末尾,如果设定的AOF保存条件被满足的话,fsync函数或者fdatasync函数会被调用,将写入的内容真正的保存到磁盘中。

命令传播

当一个redis客户端需要执行命令时,它通过网络连接,将协议文本发送给redis服务器。服务器在接到客户端请求后,它会根据协议文本的内容,选择适当的命令函数,并将各个参数从字符串文本转换为redis字符串对象(stringObject)。每当命令函数成功执行之后,命令参数都会被传播到AOF程序。

缓存追加

当命令被传播到AOF程序之后,程序会根据命令及命令参数,将字符串对象转换回原来的协议文本。协议文本生成之后,它会被追加到redis.h/redisServer结构的aof_buf结尾。redisServer结构维持着redis服务器的状态,aof_buf域则保存着所有等待写入到AOF文件的协议文本。

文件写入和保存

每当服务器常规任务函数被执行、或者事件处理器被执行时,aof.c/flushAppendOnlyFile函数都会被调用,这个函数做以下两个操作:
WRITE:根据条件,将aof_buf中的缓存写入到AOF文件。
SAVE:根据条件调用fsync或者fdatasync函数,将AOF文件保存到磁盘中。

AOF保存模式

redis目前支持三种AOF保存模式:
AOF_FSYNC_NO:不保存。
AOF_FSYNC_EVERYSEC:每一秒钟保存一次(默认)。
AOF_FSYNC_ALWAYS:每执行一个命令保存一次。(不推荐)

AOF_FSYNC_NO

在这种模式下,每次调用flushAppendOnlyFile函数,WRITE都会被执行,SAVE略过
在这种模式下,SAVE只会在以下任意一种情况中被执行:
redis被关闭、AOF功能被关闭、系统的写缓存被刷新(可能是缓存已经被写满、或者定期保存操作被执行)这三种情况下的SAVE操作都会引起redis主进程阻塞。

此模式的保存操作只会在AOF关闭或redis关闭时执行,或者由操作系统触发,一般情况下只需要为写入阻塞,因此它的写入性能要比后面两种要高,但是这种性能的提高是以降低安全性为代价,如果运行的中途发生宕机,那么丢失数据的数量由操作系统的缓存冲洗策略决定。

AOF_FSYNC_EVERYSEC

在这种模式下,SAVE原则上每隔一秒执行一次,因为SAVE操作是由后台子线程调用的,所以它不会引起主进程阻塞。

性能优于AOF_FSYNC_ALWAYS,并且在通常情况下,这种模式最多丢失不多于2秒的数据,所以它的安全性要高于AOF_FSYNC_EVERYSEC,兼顾性能和安全

AOF_FSYNC_ALWAYS

在这种模式下,每次执行完一个命令之后,WRITE和SAVE都会被执行。
因为SAVE是由主进程执行的,所以在SAVE执行期间,主进程会被阻塞,不能接受命令请求。

此模式安全性最高,但性能最差,因为服务器必须阻塞直到命令写入并保持到磁盘之后,才能继续处理请求。
在这里插入图片描述

比较在这里插入图片描述

AOF重写原理(优化AOF文件)

当AOF文件过大时,redis会自动地在后台(fork子进程)对AOF重写,重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合,AOF重写并不需要对原有的AOF文件进行任何写入和读取,它针对的是数据库中键的当前值。
举例:
set s1 11
set s1 22 ------- > set s1 33
set s1 33
没有优化的:
set s1 11
set s1 22
set s1 33
优化后:
set s1 33

lpush list1 1 2 3
lpush list1 4 5 6 -------- > list1 1 2 3 4 5 6
优化后
lpush list1 1 2 3 4 5 6
redis不希望AOF重写造成服务器无法处理请求,所以将AOF重写程序放入到子进程里执行,这样处理的好处是:
1.子进程进行重写AOF期间,主进程可以继续处理命令请求。
2.子进程带有主进程的数据副本,使用子进程而不是子线程,可以在避免锁的情况下,保证数据的安全性。

使用子进程有一个问题需要解决:因为子进程在进行AOF重写期间,主进程还需要继续处理命令,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。
为了解决这个问题,redis还增加了一个AOF重写缓存,这个缓存在fork出子进程后开始启用,reids主进程在接到新的写命令之后,除了会将这个写命令的协议内容追加到现有的AOF文件之外,还会追加到这个缓存中。
在这里插入图片描述
redis在创建新AOF文件的过程中,会继续将命令追加到现有的AOF文件里面,即使重写过程发生停机,现有的AOF文件也不会丢失。一旦新AOF文件创建完毕,redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。
当子进程在执行AOF重写时,主进程需要执行以下三个工作:
1.处理命令请求,2.将写命令追加到现有AOF文件中,3.将写命令追加到AOF重写缓存中。就可以保证:
现有的AOF功能会继续执行,即使在AOF重写期间发生停机,也不会有任何数据丢失。所有对数据库进行修改的命令都会被记录到AOF重写缓存中,当子进程完成AOF重写之后,它会向父进程发送一个完成信号,父进程在接到完成信号之后,会调用一个信号处理函数,并完成以下工作:
将AOF重写缓存中的内容全部写入到新AOF文件中。对新的AOF文件进行改名,覆盖原有的AOF文件。
在整个AOF后台重写过程中,只有最后的写入缓存和改名操作会造成主进程阻塞,在其他时候,AOF后台重写都不会对主进程造成阻塞。
以上就是 AOF 后台重写, 也即是 BGREWRITEAOF 命令(AOF重写)的工作原理。
在这里插入图片描述
优化触发条件:

# 表示当前aof文件大小超过上一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,以
启动时aof文件大小为准
auto-aof-rewrite-percentage 100
# 限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
auto-aof-rewrite-min-size 64mb
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页