Redis的持久化方式

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的整个流程大体来看可以分为两步

     a.  第一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗)

     b.  第二步是对 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. 混合持久化

      重启 Redis 时,如果使用 RDB 来恢复内存状态,会丢失大量数据。而如果只使用 AOF 日志重放,那么效率又太过于低下。Redis 4.0 提供了混合持久化方案,将 RDB 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自 RDB 持久化开始到持久化结束这段时间发生的增量 AOF 日志,通常这部分日志很小。

      5、不使用持久化

     数据的生命周期只存在于服务器的运行时间里

     

     参考链接:

     https://segmentfault.com/a/1190000002906345

     http://redisdoc.com/topic/persistence.html

     https://www.cnblogs.com/xuwenjin/p/9876432.html

     https://juejin.cn/post/6844903655527677960

posted @ 2021-04-25 20:09  欢乐豆123  阅读(457)  评论(0编辑  收藏  举报