redis的持久化机制

Redis中数据存储及读写操作都是在内存中进行。Redis宕机或者重启后,内存中的数据就会被清除,这是很不安全的。为了解决这个问题,Redis提供了持久化机制,一旦Redis宕机,重启后,数据也能马上恢复,Redis的持久化这时候就显得特别重要,所以Redis提供了两种持久化存储:RDB和AOF。

持久化:简单来讲就是将数据放到断电后数据不会丢失的设备中,也就是硬盘上

1、RDB

RDB 是以二进制文件,在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复的目的,简单理解就是每隔一段时间记录数据快照。

RDB的触发方式

  1. 通过配置参数设置,如在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave(自动触发)
  2. 通过在客户端执行命令bgsave手动触发,命令执行后,立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出(手动触发)

fork(多进程)

Redis 在持久化时会调用 glibc 的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段。这时你可以将父子进程想像成一个连体婴儿,共享身体。fork操作主要发生在写RDB文件和AOF rewrite的过程中,Redis通过fork出一个子进程来完成上面的工作,通过利用fork操作的COW(copy on write)功能,使得系统能够仅仅复制内存页面引用来实现数据快照的功能

优点

  • 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这样非常方便进行备份。比如你可能打算没1天归档一些数据。
  • 方便备份,我们可以很容易的将一个一个RDB文件移动到其他的存储介质上
  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
  • RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。

缺点

  • 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。所以这种方式更适合数据要求不严谨的时候。
  • 每次保存 RDB 的时候,Redis 都要 fork 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork可能会非常耗时

2、AOF

AOF是以格式化指令的方式追加到操作日志文件的尾部,换句话说,你执行过的指令都被记录在一个文件上,如果想要恢复数据,将执行过的指令再执行一遍即可

AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令

AOF的触发方式

  1. 通过配置自动触发,和RDB一样,配置在redis.conf文件里:

    如auto-aof-rewrite-min-size 64mb,auto-aof-rewrite-percentage 100这两个配置,意思是当AOF的文件大于64MB,并且比上一个文件增加了100%时,则会触发重写。

    • appendonly:是否打开AOF持久化功能,appendonly默认是 no, 改成appendonly yes。
    • appendfilename:AOF文件名称
    • appendfsync:同步频率
    • auto-aof-rewrite-min-size:如果文件大小小于此值不会触发AOF,默认64MB
    • auto-aof-rewrite-percentage:Redis记录最近的一次AOF操作的文件大小,如果当前AOF文件大小增长超过这个百分比则触发一次重写,默认100
  2. 使用bgrewriteaof命令手动触发:通过客户端输入指令,bgrewriteaof手动触发,通过创建子进程完成重写操作。Redis主进程fork子进程来执行AOF重写,这个子进程创建新的AOF文件来存储重写结果,防止影响旧文件,

重写(rewrite)

每一条命令都生成一条日志,那么AOF文件会变得越来越大,所以Redis提供了这个功能。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件

为什么要重写

redis中的数据其实有限的,很多数据可能会自动过期,可能会被用户删除,可能会被redis用缓存清除的算法清理掉。redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中,所以可能很多之前的已经被清理掉的数据, 随着写操作的不断增加, 对应的写日志还停留在AOF中,AOF日志文件就一个,AOF文件会越来越大

例如你递增一个计数器100次,那么最终结果就是数据集里的计数器的值为最终的递增结果,但是AOF文件里却会把这100次操作完整的记录下来。而事实上要恢复这个记录,只需要1个命令就行了,也就是说AOF文件里那100条命令其实可以精简为1条。所以Redis支持这样一个功能:在不中断服务的情况下在后台重建AOF文件

优点

  • 数据更加安全。如果系统对数据安全要求较高,可以选择AOF。
  • 使用 AOF 持久化会让 Redis 变得非常耐久:你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析也很轻松。 导出AOF 文件也非常简单

缺点

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此

fsync

这个函数可以将指定文件的内容强制从内核缓存刷到磁盘。只要 Redis 进程实时调用 fsync 函数就可以保证 aof 日志不丢失。但是 fsync 是一个磁盘 IO 操作,它很慢!如果 Redis 执行一条指令就要 fsync 一次,那么 Redis 高性能的地位就不保了

通过配置文件告诉redis我们想要 通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)

appendonly yes            //启用aof持久化方式
# appendfsync always      //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec      //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no          //完全依赖os,性能最好,持久化没保证
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页