概述
Redis的持久化:
通俗讲持久化就是将内存中的数据写入非易失介质中,比如机械磁盘和SSD。
在服务器发生宕机时,作为内存数据库Redis里的所有数据将会丢失,因此Redis提供了持久化两大利器:RDB和AOF
RDB 将数据库快照以二进制的方式保存到磁盘中。
AOF 以协议文本方式,将所有对数据库进行过写入的命令和参数记录到 AOF 文件,从而记录数据库状态。
RDB:
查看RDB配置:
cat /abc/redis/conf/redis.conf
save 900 1
save 300 10
save 60 10000
dbfilename "dump.rdb"
dir "/data/dbs/redis/rdbstro"
前三行都是对触发RDB的一个条件, 如第一行表示每900秒钟有一条数据被修改则触发RDB,依次类推;只要一条满足就会进行RDB持久化;
第四行dbfilename指定了把内存里的数据库写入本地文件的名称,该文件是进行压缩后的二进制文件;
第五行dir指定了RDB二进制文件存放目录 ;
修改RDB配置:
在命令行里进行配置,服务器重启才会生效:
bin/redis-cli
127.0.0.1:6379> CONFIG GET save
1) "save"
2) "900 1 300 10 60 10000"
127.0.0.1:6379> CONFIG SET save "21600 1000"
OK
RDB的SAVE和BGSAVE:
RDB文件适合数据的容灾备份与恢复,通过RDB文件恢复数据库耗时较短,可以快速恢复数据。
RDB持久化只会周期性的保存数据,在未触发下一次存储时服务宕机,就会丢失增量数据。当数据量较大的情况下,fork子进程这个操作很消耗cpu,可能会发生长达秒级别的阻塞情况。
SAVE是阻塞式持久化,执行命令时Redis主进程把内存数据写入到RDB文件中直到创建完毕,期间Redis不能处理任何命令。
BGSAVE属于非阻塞式持久化,创建一个子进程把内存中数据写入RDB文件里同时主进程处理命令请求。
BGSAVE实现细节:
RDB方式的持久化是通过快照实现的,符合条件时Redis会自动将内存数据进行快照并存储在硬盘上,以BGSAVE为例,一次完整数据快照的过程:
- Redis使用fork函数创建子进程;
- 父进程继续接收并处理命令请求,子进程将内存数据写入临时文件;
- 子进程写入所有数据后会用临时文件替换旧RDB文件;
注意:
Redis 执行 fork 操作产生的子进程内存占用量表现为与父进程相同,理论上需要一倍的物理内存来完成相应的操作。但是 Linux 具有写时复制技术 (copy-on-write),父子进程会共享相同的物理内存页,当父进程处理写请求时会对需要修改的页复制出一份副本完成写操作,而子进程依然读取 fork 时整个父进程的内存快照。
Redis在进行快照过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是任何时候RDB文件都是完整的。
我们可以通过定时备份RDB文件来实现Redis数据库备份,RDB文件是经过压缩的,占用的空间会小于内存中的数据大小。
RDB触发条件:
- 客户端执行命令save和bgsave会生成快照;
- 根据配置文件save m n规则进行自动快照;
- 主从复制时,从库全量复制同步主库数据,此时主库会执行bgsave命令进行快照;
- 客户端执行数据库清空命令FLUSHALL时候,触发快照;
- 客户端执行shutdown关闭redis时,触发快照;
AOF详解
在使用AOF持久化方式时,Redis会将每一个收到的写命令都通过Write函数追加到文件中类似于MySQL的binlog。换言之AOF是通过保存对redis服务端的写命令来记录数据库状态的。
AOF文件有自己的存储协议格式:
cat appendonly.aof
*2
# 2个参数
$6
# 第一个参数长度为 6
SELECT
# 第一个参数
$1
# 第二参数长度为 1
8
# 第二参数
*3
# 3个参数
$3
# 第一个参数长度为 4
SET
# 第一个参数
$4
# 第二参数长度为 4
name
# 第二个参数
$4
# 第三个参数长度为 4
Jhon
# 第二参数长度为 4
AOF配置:
more ~/redis/conf/redis.conf
dir "/data/dbs/redis/abcd"
#AOF文件存放目录
appendonly yes
#开启AOF持久化,默认关闭
appendfilename "appendonly.aof"
#AOF文件名称(默认)
appendfsync no
#AOF持久化策略
auto-aof-rewrite-percentage 100
#触发AOF文件重写的条件:当前AOF文件大小和最后一次重写后的大小之间的比率。如默认100代表当前AOF文件是上次重写的两倍时候才重写。
auto-aof-rewrite-min-size 64mb
#触发AOF文件重写的条件:只有当AOF文件大小大于该值时候才可能重写,默认是64MB
当开启AOF后,服务端每执行一次写操作就会把该条命令追加到一个单独的AOF缓冲区的末尾,然后把AOF缓冲区的内容写入AOF文件里,由于磁盘缓冲区的存在写入AOF文件之后,并不代表数据已经落盘了,而何时进行文件同步则是根据配置的appendfsync来进行配置:
appendfsync选项:
always:服务器在每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘上的AOF文件里,保证了数据持久化的完整性,效率是最慢的但最安全的;
everysec:服务端每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,兼顾了效率和完整性,极端情况服务器宕机只会丢失一秒内对Redis数据库的写操作;
no:表示默认系统的缓存区写入磁盘的机制,不做程序强制,数据安全性和完整性差一些。
AOF重写:
AOF比RDB文件更大,并且在存储命令的过程中增长更快,为了压缩AOF的持久化文件,Redis提供了重写机制以此来实现控制AOF文件的增长。
举个例子:
比如执行了100次set hello world ,又执行了一次set hello china。那么最后只用保存set hello china即可,但AOF会全保存。另外,对于目前已经过期的键也不需要进行存储。
重写流程:
在进行AOF 重写期间,也会fork一个子进程去进行,而主进程继续接收命令。子进程根据当前的内存快照,对原AOF文件进行扫描,并把新的结果写入一个新的AOF文件(与RDB一样,保证任意时刻文件的完整性)。最后用新的AOF文件替换旧的AOF文件。
注意:这里fork子进程,以及替换AOF文件时,Redis是阻塞的。
重写时的数据一致性问题:
在重写时,主进程任然在接受新的命令,会把新的写命令追加到旧AOF文件中。所以在子进程重写完后,直接把旧的AOF替换成新的重写后的AOF,会造成重写期间新增写命令的丢失。
针对这种情况,Redis提供了 重写缓冲区(aof_rewrite_buf)。在重写期间,主进程接收到新的写命令后,不仅会添加到旧的AOF文件,还会添加到重写缓存区。在子进程完成了重写后,会先把重写缓存区的数据添加到新的AOF中,再去替换掉旧的AOF文件。
Redis的数据恢复:
Redis的数据恢复优先级:
如果只配置 AOF ,重启时加载 AOF 文件恢复数据;
如果同时配置了 RDB 和 AOF ,启动只加载 AOF 文件恢复数据;
如果只配置 RDB,启动将加载 dump.rdb 文件恢复数据。
新型的混合型持久化:
RDB和AOF各自的缺点:
RDB是每隔一段时间持久化一次, 故障时就会丢失宕机时刻与上一次持久化之间的数据,无法保证数据完整性。
AOF存储的是指令序列, 恢复重放时要花费很长时间并且文件更大。
Redis 4.0 提供了更好的混合持久化选项:
fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。
持久化策略的选择:
在实际使用中需要根据Redis作为主存还是缓存、数据完整性和缺失性的要求、CPU和内存情况等诸多因素来确定适合自己的持久化方案,一般来说稳妥的做法包括:
最安全的做法是RDB与AOF同时使用,即使AOF损坏无法修复,还可以用RDB来恢复数据,当然在持久化时对性能也会有影响。
Redis当简单缓存,没有缓存也不会造成缓存雪崩只使用RDB即可。
不推荐单独使用AOF,因为AOF对于数据的恢复载入比RDB慢,所以使用AOF的时候,最好还是有RDB作为备份。
采用新版本Redis 4.0的持久化新方案。
参考文章:
https://www.cnblogs.com/wdliu/p/9377278.html
最后
以上就是着急鸡为你收集整理的Redis三种持久化方式:RDB、AOF、Redis4.0后的混合模式的全部内容,希望文章能够帮你解决Redis三种持久化方式:RDB、AOF、Redis4.0后的混合模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复