随笔 - 171  文章 - 0  评论 - 0  阅读 - 62142

RDB和AOF

Redis目前支持两种持久化的方式,RDB和AOF。
RDB文件是压缩后的二进制文件,AOF记录的是每一次写操作的命令。所以一般来说AOF文件比RDB占用内存大。

RDB

RDB(RedisDataBase)是基于快照(snapshoptting)实现的。redis在运行时会在满足一定条件的情况下将运行中的数据同步转储到一个二进制的文件并保存在磁盘中作为副本。

redis会在以下几种情况下进行RDB的持久化,生成快照文件:

满足配置规则进行自动快照时

redis允许用户在(固定时间间隔M)和(被修改的key的个数N)这两个关键维度上面进行自定义的配置。
在redis的配置文件中默认存在了三个自定义条件:

第一行代表着在每900秒的时间间隔内,存在1个或以上的key被修改过,便会进行异步快照存储;

第二行代表着在每300秒内的时间间隔内,存在10个或以上的key被修改过,便会进行异步快照存储,以此类推。

自定义触发条件可以同时存在N个。但是进行快照的持久化操作在增加了数据安全性的同时也会消耗额外的系统资源,因此不能过于频繁。用户可以根据自己的实际需求,在数据安全性和系统性能之间进行取舍。当配置设置为空字符串时,代表禁用该特性,永不进行自动快照。

执行手动备份命令时

有时在数据迁移,系统重启等情况下,我们希望能够手动的令redis立即进行快照备份。

redis提供了两个命令来满足这个需求:

SAVE命令:

在执行SAVE命令时,redis会执行同步阻塞式的快照操作,此时的redis会阻塞所有的其它请求。如果所要同步的数据量很大,会导致redis长时间的未响应,因此应该避免在生产环境中使用该命令。

BGSAVE命令:

在执行BGSAVE(BackGround SAVE)命令时,顾名思义,redis将会在后台进行快照存储。这个操作是异步的,并不会阻塞其它的操作。由于redis是单线程架构,因此异步的快照存储实际上是redis从主进程中fork了一个子进程,这时主进程继续对外提供服务,而子进程则在后台默默的执行快照存储操作,在生成新的备份文件后,会将之前过时的备份文件替换掉。

值得一提的是,由于redis在异步快照操作时使用了操作系统支持的"写时复制"策略,即fork时操作系统并不会立刻为子进程提供一片主进程同等大小的内存区域,而是fork完毕的瞬间,子进程和主进程共享同一片内存区域。当主进程的内存被写入新数据时,逐步分配新的内存区域给主进程用于存储新数据,这大大的提高了内存的利用效率。但是如果在子进程备份期间主进程写入数据过多,由于系统必须同时维护主进程的实时数据和备份子进程中需要备份的旧数据,可能会导致redis使用比较多的内存,因此最好能预见到这种糟糕的情况,事先允许redis申请足够多的内存空间,以避免内存溢出。

执行FLUSHALL命令时

执行FLUSHALL命令时,redis会将所有的数据都清除,此时如果开启了自动快照功能,则无论清除操作执行之后是否满足自定义条件,redis都默认会进行一次RDB快照,生成一个空的备份文件。如果未开启自动快照功能,则FLUSHALL不会触发快照操作。

主从模式复制时  

当redis在进行主从复制时,会默认进行一次RDB快照操作。

RDB总结:

上面简单的介绍了redis进行RDB持久化的几种方式,对于RDB还有很多细节例如rdbcompression(生成的备份文件是否需要压缩--->"压缩文件占据更小的磁盘空间但是在压缩和解压缩时需要耗费更多的CPU资源")、stop-writes-on-bgsave-error(BGSAVE时如果出错,是否允许继续写入新数据)等等。

对数据正确性要求很高的场合,用RDB进行持久化的方式是无法满足的。这便引出了我们接下来要介绍的redis的AOF持久化方式。

AOF

当需要使用redis存储一些非临时性的,重要的数据时,推荐使用redis的AOF持久化方式。AOF(AppendOnlyFile)和RDB不同,RDB关注实时数据,通过备份实时的数据快照来达到数据的持久化,而AOF则是关注所执行的更新命令(造成数据变化的命令,查询排序之类的不算),通过实时的保存redis执行的每一条更新命令,生成细粒度的更新命令日志来达到数据持久化的目的。由于每一次更新命令都会被记录下来并且保存在硬盘上,这会导致redis的性能降低,使用高性能的硬盘可以尽可能的降低负面影响,使之达到能够被接受的程度。 

重写AOF文件

由于对同一个记录的数据更新操作会覆盖之前的数据,这导致了在原始的AOF文件中可能会出现大量的冗余记录,redis提供了重写aof文件的功能,通过剔除掉冗余的记录,可以降低文件占用的磁盘空间。

redis提供了两种重写(rewrite)aof文件的方式:

手动执行 BGREWRITEAOF命令:

执行BGREWRITEAOF时,和BGSAVE一样,redis不希望重写aof文件时阻塞服务,会在后台fork新的进程异步的进行AOF文件的重写。

自动触发:   

除了手动触发,redis还提供了自动重写aof文件的功能,配置两个关键参数auto-aof-rewrite-percentage和auto-aof-rewrite-min-size,redis会执行周期性的函数一直监听aof文件的变化,当达到配置好的触发条件时,便会自动的进行aof文件的重写。

redis的配置文件中默认的参数如图所示,第一行代表当AOF文件超过了上一次重写文件的100%时,第二行代表当前aof文件大小是否超过了64M,当redis服务器监听并发现aof文件如果同时满足了上述两个条件,而且此时没有正在进行中的其它持久化操作(rdb和手动rewrite),便会执行自动的rewrite重写操作。

同步硬盘数据

现代的操作系统为了弥补磁盘和内存之间存取速度的差距,都采用了磁盘缓存技术,缓存数据命中时操作系统优先操作磁盘缓存,操作系统会定期的将磁盘缓存中的数据刷新写入磁盘。这意味着应用程序(例如redis)调用文件写入磁盘的接口后,默认情况下并不会实时的写入磁盘,而必须等待操作系统周期性的同步操作(一般是30s),而在此期间一旦出现系统故障,最新的aof文件变更记录没有被保存下来,数据还是会出现丢失。因此redis提供了一个配置参数appendfsync来帮助用户解决这个问题。 

appendfsync有三种可选参数:

  1.appendfsync always

  代表着每一次的aof文件变更都会强制操作系统实时的写入硬盘,这是最安全的方式,由于这带来了频繁的IO,因此也是性能最差的。

  2.appendfsync everysec 

  这是redis在配置中默认启用的选项,代表着每秒钟强制操作系统进行一次aof文件的硬盘同步,一秒一次的IO比起appendfsync always 每次更新操作都进行IO的方式,在系统繁忙时,性能上有着显著提高。但带来的问题是:如果这一秒内出现系统故障,同步时间间隔之内的更新操作还是会丢失。

  3.appendfsync no

  redis不主动的进行硬盘同步操作,而是完全交给操作系统来同步,这是运行效率最高的方式。但是由于操作系统的硬盘同步时间间隔相对比较长,因此这是最不安全的方式。

如果用户没有主动为 appendfsync 选项设置值, 那么 appendfsync 选项的默认值为 everysec。

为什么主从库间的复制不使用 AOF?

RDB文件内容是经过压缩的二进制数据(不同数据类型数据做了针对性优化),文件很小。而AOF文件记录的是每一次写操作的命令,写操作越多文件会变得很大,其中还包括很多对同一个key的多次冗余操作。在主从全量数据同步时,传输RDB文件可以尽量降低对主库机器网络带宽的消耗,从库在加载RDB文件时,一是文件小,读取整个文件的速度会很快,二是因为RDB文件存储的都是二进制数据,从库直接按照RDB协议解析还原数据即可,速度会非常快,而AOF需要依次重放每个写命令,这个过程会经历冗长的处理逻辑,恢复速度相比RDB会慢得多,所以使用RDB进行主从全量同步的成本最低。

生产环境的配置?

每天业务低峰期定时RDB备份,AOF刷盘策略:appendfsync=everysec

posted on   zhengbiyu  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示