zoukankan      html  css  js  c++  java
  • 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重写的操作,主要就是为了节省空间。

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

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

    你学会了吗?下期见~

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/moon-java/p/14289486.html
Copyright © 2011-2022 走看看