Redis持久化
文章目录
- Redis持久化
- 一:持久化简介
- 1:Redis为什么要进行持久化
- 2:Redis持久化的方式
- 二:RDB持久化介绍
- 1:手动触发RDB
- 2:自动触发RDB
- 3:redis.conf中进行RDB的配置
- 4:RDB优缺点
- 二:AOF持久化介绍
- 1:写后日志
- 2:如何实现AOF
- 3:redis.conf中进行AOF的配置
一:持久化简介
1:Redis为什么要进行持久化
Redis是个基于内存的数据库。那服务一旦宕机,内存中的数据将全部丢失。
通常的解决方案是从后端数据库恢复这些数据,但后端数据库有性能瓶颈:
- 如果是大数据量的恢复,会对数据库带来巨大的压力
- 数据库的性能不如Redis。导致程序响应慢
2:Redis持久化的方式
1)AOF 日志(Append Only File,文件追加方式) :记录所有的操作命令,并以文本的形式追加到文件中。
2)RDB 快照(Redis DataBase) :将某一个时刻的内存数据,以二进制的方式写入磁盘。
3)混合持久化方式 :Redis 4.0 新增了混合持久化的方式,集成了 RDB 和 AOF 的优点。
二:RDB持久化介绍
RDB 就是 Redis DataBase 的缩写,中文名为快照/内存快照
RDB持久化是把当前进程数据生成快照保存到磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值。
1:手动触发RDB
手动触发分别对应save和bgsave命令
- save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用
- bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。
- 阻塞只发生在fork阶段,一般时间很短
具体的流程如下:
-
redis客户端执行bgsave命令或者自动触发bgsave命令;
-
主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;
-
如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;
-
子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;
-
同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)。
2:自动触发RDB
下面的四种情况会自动触发RDB持久化:
- redis.conf中配置
save m n
,即在m秒内有n次修改时,自动触发bgsave生成rdb文件; - 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点;
- 执行debug reload命令重新加载redis时也会触发bgsave操作;
- 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作
3:redis.conf中进行RDB的配置
内存快照在生产环境下多数情况都会设置其周期性执行条件
# 周期性执行条件的设置格式为
save <seconds> <changes>
# 默认的设置为:
save 900 1 # 如果900秒内有1条Key信息发生变化,则进行快照
save 300 10 # 如果300秒内有10条Key信息发生变化,则进行快照;
save 60 10000 # 如果60秒内有10000条Key信息发生变化,则进行快照。
# 以下设置方式为关闭RDB快照功能
save ""
# ============ 其他配置相关 =============
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
RDB 做快照的时候数据能修改吗 ?怎么修改?
save 是同步的会阻塞客户端命令,bgsave 的时候是可以修改的。
具体的修改方案主要是利用 bgsave 的子线程实现的,具体操作如下:
- 如果主线程执行读操作,则主线程和 bgsave 子进程互相不影响;
- 如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子进程会把该副本数据写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据。
4:RDB优缺点
优点
- RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;
- Redis加载RDB文件恢复数据要远远快于AOF方式;
缺点
- RDB方式实时性不够,无法做到秒级的持久化;
- 每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高;
- RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全;
- 版本兼容RDB文件问题;
二:AOF持久化介绍
AOF 采用的是写后日志的方式,Redis 先执行命令把数据写入内存,然后再记录日志到文件中。
AOF 日志记录的是操作命令,不是实际的数据,如果采用 AOF 方法做故障恢复时需要将全量日志都执行一遍。
1:写后日志
Redis是“写后”日志,Redis先执行命令,把数据写入内存,然后才记录日志
日志里记录的是Redis收到的每一条命令,这些命令是以文本形式保存
大多数的数据库采用的是写前日志,例如MySQL,通过写前日志和两阶段提交,实现数据和逻辑的一致性
优点 -> 高性能
- 避免额外的检查开销:Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。
- 不会阻塞当前的写操作
缺点 -> 丢失数据可能
- 写日志之前宕机了,会丢失数据
- 主线程写磁盘压力大,导致写盘慢,阻塞后续操作
2:如何实现AOF
AOF日志记录Redis的每个写命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync)
-
append -> 当AOF持久化功能打开了,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的 aof_buf 缓冲区
-
write & sync -> 关于何时将 aof_buf 缓冲区的内容写入AOF文件中,Redis提供了三种写回策略
性能和可靠性不可兼得
3:redis.conf中进行AOF的配置
默认情况下,Redis是没有开启AOF的,可以通过配置redis.conf文件来开启AOF持久化
# appendonly参数开启AOF持久化
appendonly no
# AOF持久化的文件名,默认是appendonly.aof
appendfilename "appendonly.aof"
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
dir ./
# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof出错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
- AOF在重写时,在fork进程时是会阻塞住主线程的
- 重写过程总结为:“一个拷贝,两处日志”。
- 在fork出子进程时的拷贝,以及在重写时,如果有新数据写入,主线程就会将命令记录到两个AOF日志内存缓冲区中
总结操作:
- 主线程fork出子进程重写AOF日志
- 子进程重写日志完成后,主线程追加AOF日志缓冲
- 替换日志文件