Redis的持久化方式
一、什么是持久化?
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
二、Redis为什么要持久化?
Redis是一个内存数据库,所有的数据将保存在内存中,这与传统的MySQL、Oracle、SqlServer等关系型数据库直接把数据保存到硬盘相比,Redis的读写效率非常高。但是保存在内存中也有一个很大的缺陷,一旦断电或者宕机,内存数据库中的内容将会全部丢失。为了弥补这一缺陷,Redis提供了把内存数据持久化到硬盘文件,以及通过备份文件来恢复数据的功能。
三、Redis官方提供了不同级别的持久化方式
1、RDB(Redis DataBase)
在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
它是Redis数据库中数据的内存快照,并且是一个二进制文件(默认名称为dump.rdb,可修改),存储了文件生成时Redis数据库中所有的数据内容。可用于Redis的数据备份、转移与恢复。
1) 配置文件参数及说明
在redis.conf配置文件中可以配置:
################################ SNAPSHOTTING ################################ # Redis触发自动备份的触发策略 # save <seconds> <changes> save 900 1 # 在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照 save 300 10 # 在300秒(5分钟)之后,如果至少有10个key发生变化,则dunp内存快照 save 60 10000 # 在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照 # 如果持久化出错,主进程是否停止写入 stop-writes-on-bgsave-error yes # 是否压缩 rdbcompression yes # 导入时是否检查 rdbchecksum yes # 文件名称 dbfilename dump.rdb # 文件保存路径 dir /www/server/redis/
2) RDB持久化工作原理
- Redis调用fork(),产生一个子进程。
- 子进程把数据写到一个临时的RDB文件。
- 当子进程写完新的RDB文件后,把旧的RDB文件替换掉。
3) RDB持久化触发方式
手动触发
save:会阻塞redis的服务器进程,直到RDB文件被创建完毕,线上环境应该禁止使用。
bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。
重启redis服务端和客户端,看数据是否真的持久化了
自动触发
1)根据 save <seconds> <changes> 配置规则自动触发
2)从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave
3)执行 debug reload 时
4)执行 shutdown时,如果没有开启aof,也会触发
说明:自动触发对应 bgsave 命令,Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
由于 save 基本不会被使用到,我们重点看看 bgsave 这个命令是如何完成RDB的持久化的。
这里需要注意的是 fork 操作会阻塞,导致Redis读写性能下降。我们可以控制单个Redis实例的最大内存,来尽可能降低Redis在fork时的事件消耗。以及上面提到的自动触发的频率减少fork次数,或者使用手动触发,根据自己的机制来完成持久化。
4) RDB持久化优缺点
优点
1)RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
2)基于上面所描述的特性,RDB很适合用于灾备。单文件很方便就能传输到远程的服务器上。
3)RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
4)比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
缺点
1)RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到 Redis 出现问题这段时间的数据就会丢失了。
2)RDB方式无法做到实时或秒级持久化。因为 RDB 使用 fork() 产生子进程进行数据的持久化,而fork操作是一个耗时操作,无法做到实时性。如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会达到1秒。
2、AOF(Append Only File)
快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。
1)配置文件参数以及说明
开启AOF功能需要配置:appendonly yes,默认不开启。
2)工作原理
AOF持久化会把被执行的写命令写到AOF文件的末尾,记录数据的变化。默认情况下,Redis是没有开启AOF持久化的,开启后,每执行一条更改Redis数据的命令,都会把该命令追加到AOF文件中,这是会降低Redis的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高AOF的性能
AOF的整个流程大体来看可以分为两步,第一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗),第二步是对 aof 文件的重写。
aof 重写是为了减少aof文件的大小,使得 AOF文件的体积不会超出保存数据集状态所需的实际大小。可以手动或者自动触发。fork的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。
实际上,AOF持久化并不会立即将命令写入到硬盘文件中,而是写入到硬盘缓存,在接下来的策略中,配置多久来从硬盘缓存写入到硬盘文件。所以在一定程度一定条件下,还是会有数据丢失,不过可以大大减少数据损失。
重写的流程图如下:
AOF持久化提供三种策略:
always: 每次操作都会立即写入aof文件中
everysec: 每秒持久化一次(默认配置)
no: 不主动进行同步操作,默认30s一次。写入AOF文件中的操作由操作系统决定,一般而言为了提高效率,操作系统会等待缓存区被填满,才会开始同步数据到磁盘。
3)触发方式
手动触发
bgrewriteaof
自动触发
根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。
4)AOF持久化优缺点
优点
1) 比RDB可靠
可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着最多丢失一秒钟的数据。
2)AOF日志文件是一个纯追加的文件
就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。
3)通过重写来减少aof文件的大小
当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
4)快速恢复数据
AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。
缺点:
- 在相同的数据集下,AOF文件的大小一般会比RDB文件大。
- 在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次(everysec)就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
- 在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。
3、同时开启RDB和AOF
在这种情况下,当redis重启的时候会优先载入 AOF 文件来恢复原始的数据。因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。
4、不使用持久化
数据的生命周期只存在于服务器的运行时间里
参考链接:
https://segmentfault.com/a/1190000002906345
http://redisdoc.com/topic/persistence.html
https://www.cnblogs.com/xuwenjin/p/9876432.html
https://juejin.cn/post/6844903655527677960