写点什么

redis 持久化怎么选?成年人从来不做选择...

用户头像
moon聊技术
关注
发布于: 2021 年 01 月 18 日
redis持久化怎么选?成年人从来不做选择...

前言


面试官:你知道 redis 是的怎么做持久化的吗?


我:我知道 redis 有两种方式,一种是 RDB,一种是 AOF。


面试官:那这两种方式具体是怎么做的,它们的区别是什么,生产环境中到底应该怎么选择??


我:嗯。。。。。。这个我不知道。


面试官:出门左拐,不送。


嗯。。。以上场景很真实,都说面试造火箭,入职拧螺丝,今天我们就让面试官再问到这个问题时,把他按在地上摩擦!


redis 的持久化有哪些?


我们简单的说明一下什么是 redis 的持久化:


用通俗的语言来说.redis 的持久化就是将内存中的数据,保存的磁盘当中,以便于数据恢复.


接下来我们进入正题,说说 redis 持久化的方式 redis 的持久化方式有两种:

  • RDB(Redis DataBase)

  • AOF(Append Only File)


RDB


RDB(redis database):


把某个时间点 redis 内存中的数据以二进制的形式存储的一个.rdb 为后缀的文件当中,也就是周期性的备份 redis 中的整个数据,这是 redis 默认的持久化方式,也就是我们说的快照(snapshot)


RDB 的两种工作方式


  • 自动提交


这是 redis 中默认的配置,它的意思就是

在900s内,有1个redis键有变化,就备份一次
在300s内,有10个redis键有变化,就备份一次
在600s内,有10000个redis键有变化,就备份一次
复制代码


这个参数是我们可以修改的,具体的数值可以根据我们的业务量进行匹配


  • 手动提交

:手动触发 Redis 进行 RDB 持久化的命令有两种:

- save

该命令会阻塞当前 Redis 服务器,执行 save 命令期间,Redis 不能处理其他命令,直到 RDB 过程完成为止。所以说当 save 命令执行期间,如果有其他命令执行,那么只能阻塞,极大的影响了 redis 的性能


- bgsave:执行 bgsave 命令的时候,redis 会自己 fork 出一条子进程,由这条子进程去执行,这样就不会影响到客户端对于 redis 的正常操作

有意思的是,我们都知道,进程与进程之间的内存不是共享的,那么子进程是如何获取到主进程的内存数据呢?


  • 真像是在主进程 fork 子进程的同时,会把自己内存中的数据同时复制一份给子进程,这样就相当于子进程可以读取到主进程的数据了,然后子进程就可以愉快的进行 io 操作了.(将内存中的数据写入磁盘中)


用心的小伙伴可能已经发现了,既然主进程要把自己的数据复制一份给子进程,那么就是说,会有双倍的内存占用.


简单点来讲,假如你的 redis 在未 fork 子进程时就占用了 5G 内存,那么你的服务器剩余可用内存至少要达到 5G 才可正常的进行 fork 操作.


有的小伙伴可能会问,那么这个复制内存的操作是立即执行的吗?


  • 其实并不是的,正常情况下 redis 的服务大部分都是读操作,在 fork 子进程的时候,子进程其实并没有直接复制一份主进程的数据,而是给他分配了一个虚拟的内存地址,指向了父进程的内存地址,直到父进程的内存数据发生改变的时候才会进行复制内存的操作


又有一个问题来了,如果在 fork 期间客户端又发起了新的操作,redis 会怎样做呢


  • 答案相信大家都猜到了,当然是等着了,毕竟 redis 是单线程的, fork 这个过程结束后, redis 的子进程就会进行持久化操作了,所以 redis 主进程理所应当的就创建了一份新的 rdb 文件,直到子进程完成持久化操作后,才会删除掉之前的 rdb 文件,以这份新的 rdb 文件代替


所以大家也发现了,fork 的时间长短其实是跟当时 redis 中的数据量有很大关系的,在其他条件恒定的情况下,随着数据量的增大,redis 的 fork 操作时间也会变长.


为了性能,基本上 Redis 内部所有的 RDB 操作都是采用 bgsave 命令,也就是自动提交。


RDB 的优缺点


RDB 的优点:

  • 1.它是将某一时间点 redis 内的所有数据保存下来,所以当我们做大型的数据恢复时,RDB 的恢复速度会很快


  • 2.由于 RDB 的 FROK 子进程这种机制,队友给客户端提供读写服务的影响会非常小


RDB 的缺点:

  • 1:有可能会产生长时间的数据丢失

- 举个例子假设我们定时 5 分钟备份一次,在 10:00 的时候 redis 备份了数据,但是如果在 10:04 的时候服务挂了,那么我们就会丢失在 10:00 到 10:04 的整个数据


  • 2:可能会有长时间停顿

- 我们前面讲了,fork 子进程这个过程是和 redis 的数据量有很大关系的,如果数据量很大,那么很有可能会使 redis 暂停几秒


AOF


AOF(append only file): redis 每次执行一个命令时,都会把这个命令原本的语句记录到一个.aod 的文件当中,然后通过 fsync 策略,将命令执行后的数据持久化到磁盘中(不包括读命令)


AOF 重写


我们知道 AOF 是不断的将写命令追加到一个后缀叫 .aof 的文件当中的,那么问题来了,随着我们不断的写命令,aof 文件越来越大,那么 redis 会做什么操作呢? 我们举个简单的例子.

 set a  10
del a
set a 10
del a
复制代码

我们执行了以上四条命令,正常来说,就会在.aof 文件当中存在这四条命令的身影,但是我们发现,其实当我们执行完这四条命令,我们根本没有修改数据的内容,要知道,redis 的本质就是存储数据的,只要数据内容不发生改变,即使做再多的操作也是没有意义的.


redis 自然也考虑到了这一点,所以它会自己对.aof 文件进行优化,重建.aof 文件.


这个文件中包含了当前数据所需要的的最少的命令集 (如:a + 1,a + 1,a + 1 这三个命令会合成为 a + 3 这一个命令).


当然 redis 并不会让主进程进行这个操作,为了防止阻塞,在执行重写操作期间会设置一个 aof 重写缓冲区,仅仅用于在后台进程重写期间,将发生的数据库读写命令写入到重写缓冲区,之后当重写子进程完成重写后,向服务器主进程发送一个信号,此时服务器主进程将 aof 重写缓冲区中的命令追加到新的 aof 文件中去,用新的 aof 文件替换掉旧的 aof 文件。


命令同步到磁盘的三种方式:


  • 1:appendfsync no


- Redis 不会主动调用 fsync 去将 AOF 日志内容同步到磁盘,具体的操作依赖于操作系统,对大多数 Linux 操作系统,是每 30 秒进行一次 fsync,将缓冲区中的数据写到磁盘上。


  • 2:appendfsync everysec


- Redis 会默认每隔一秒进行一次 fsync 调用,也就是说一次将一秒内的所有命令同步到磁盘中


  • 3:appednfsync always


- 每次写操作都会调用一次 fsync


AOF 的优缺点


  • AOF 的优点:

- 1.AOF 可以更好的保护数据不丢失,一般 AOF 会以每隔 1 秒,通过后台的一个线程去执行一次 fsync 操作,如果 redis 进程挂掉,最多丢失 1 秒的数据


- 2.AOF 是将命令直接追加在文件末尾的,写入性能非常高


- 3.AOF 日志文件的命令通过非常可读的方式进行记录,这个非常适合做灾难性的误删除紧急恢复,如果某人不小心用 flushall 命令清空了所有数据,只要这个时候还没有执行 rewrite,那么就可以将日志文件中的 flushall 删除,进行恢复


  • AOF 的缺点:


- 1.对于同一份数据源来说,一般情况下 AOF 文件比 RDB 数据快照要大


- 2.由于.aof 每次命令都会写入,那么相对于 RDB 来说需要消耗的性能也就更多


- 3.数据恢复比较慢,不适合做冷备。


总结


redis 有两种持久化的方式,一种是 RDB,一种是 AOP


所谓 RDB 就是段时间的用快照的方式将 redis 中的所有数据存储下来,并且通过 fork 子进程的方式去持久化的,由于 redis 通常是用来读取数据的,所有中间有一层优化就是写时持久化(进程与进程之间内存不共享,再 redis 数据发生变动时再 fork 完成持久化)


而 AOF 就是存储一条条执行的 redis 命令(不包括查询命令),通过命令的方式完成持久化,并且中间还会有 AOF 重写的操作,主要就是为了节省空间。


所以生产环境中到底应该怎么选择


成年人的世界不做选择,我全都要!


你学会了吗?下期见~


发布于: 2021 年 01 月 18 日阅读数: 26
用户头像

moon聊技术

关注

玩玩技术,聊聊人生,看看生活,搞搞理想 2019.03.19 加入

我是moon 文章首发于我的微信公众号:哪儿来的moon,欢迎大家关注 ! 关注后回复666 有一线大厂面试题赠送,助你成为offer收割机!

评论

发布
暂无评论
redis持久化怎么选?成年人从来不做选择...