本文 首发于 🍀 永浩转载 请注明 来源

18、【对线面试官】Redis持久化

嗯,开始吧,今天要不来聊聊Redisl的持久化机制吧?

  1. 在上一次面试已经说过了Redis:是基于内存的

  2. 假设我们不做任何操作,只要Redis服务器重启(或者中途故障挂掉了),那内存的数据就会没掉

  3. 所以Redis:提供了持久化机制给我们用,分别是RDB和AOF

    1)RDB指的就是:根据我们自己配置的时间或者手动去执行BGSAVE或SAVE命令,Redisi就会去生成RDB文件

    2)这个RDB文件实际上就是一个经过压缩的二进制文件,Redis可以通过这个文件在启动的时候来还原我们的数据

    1)而AOF则是把Redis服务器接收到的所有写命令都记录到日志中

    2)Redis重跑一遍这个记录下的日志文件,就相当于还原了数据

那我就想问了,你上次不是说Redis是单线程吗?那比如你说的RDB,它会执行SAVE或BESAVE命令,生成文件。那不是非常耗时的吗,那如果只有一个线程处理,那其他的请求不就得等了?

  1. 嗯,没错,Redis是单线程的。
  2. 以RDB持久化的过程为例,假设我们在配置上是定时去执行RDB存储
  3. Redis有自己的一套事件处理机制,主要处理文件事件(命令请求和应答等等)和时间事件(RDB定时持久化、清理过期的Key等的)
  4. 所以,定时的RDB实际上就是一个时间事件
  5. 线程不停地轮询就绪的事件,发现RDB的事件可执行时,则调用BGSAVE命令
  6. 而BGSAVE命令实际上会fork出一个子进程来进行完成持久化(生成RDB文件)
  7. 在fork的过程中,父进程(主线程)肯定是阻塞的。
  8. 但fork完之后,是fork出来的子进程去完成持久化。处理请求的进程该干嘛的就干嘛
  9. 所以说啊,Redis:是单线程,理解是没错的,但没说人家不能fork进程来处理事情。
  10. 还有就是,其实Redis在较新的版本中,有些地方都使用了多线程来进行处理
  11. 比如说,一些删除的操作(UNLINK、FLUSHALL ASYNC等等)还有Redis6.x之后对网络数据的解析都用了多线程处理了。
  12. 只不过,核心的处理命令请求和响应还是单线程。

那AOF呢?AOF不是也要写文件吗?难道也是fork了个子进程去做的?

  1. emm,不是的。AOF是在命令执行完之后,把命令写在buffer缓冲区的(直接追加写)
  2. 那想要持久化,肯定得存盘嘛。Redis:提供了几种策略供我们选择什么时候把缓冲区的数据写到磁盘
  3. 我记得好像有:每秒一次/每条命令都执行从不存盘;一般我们会选每秒一次
  4. Redis会启一个线程去刷盘,也不是用主线程去干的

那如果把执行过的命令都存起来;等启动的时候是可以再把这些写命令再执行一遍,达到恢复数据的效果;这样会有什么样的问题吗?

  1. 嗯,问题就是,如果这些写入磁盘的「命令集合」不做任何处理,那该「命令集合」就会一直膨胀
  2. 其实就是该文件会变得非常大
  3. Redis当然也考虑了这一点,它会fork个子进程会对「原始」命令集合进行重写
  4. 说白了就是会压缩,压缩完了之后只要替换原始文件就好了

那我又想问了,既然它是fork一个进程来对AOF进行重写的;前面你也提到了再fork时,主进程是阻塞的,但fork后,主进程会继续接收命令;你是说重写完(压缩)会进行文件覆盖;那这样不会丢数据吗?毕竟主进程在fork之后是一直会接收命令的

  1. 其实做法很简单啊,在fork子进程之后,把新接收到命令再写到另一个缓冲区不就好了吗

那AOF和RDB用哪一个呢?

  1. 主要是看业务场景吧,我们这边是基于Redis使用了一套开源的key-value存储
  2. 使用Redis前,首先要去新增实例,在新增时会让你选择对应的使用场景
  3. 就是会让你通过不同的应用场景进行配置选择
  4. 比如说,业务上是允许重启时部分数据丢失的,那RDB就够用了
  5. RDB在启动的时候恢复数据会比AOF快很多
  6. 在Redis4.0以后也支持了AOF和RDB混合
  7. 至于AOF的话,官网是不建议仅仅只使用AOF的,如果对数据丢失容忍度是有要求的,建议是开启AOF+RDB一起用
  8. 总的来说,不同的场景使用不同的持久化策略吧
  9. 我们公司也是不建议把Redis当做存储去使用的(毕竟没有事务保证,也还是可能导致数据丢失)

顺便我想问下,假如Redisl的内存满了,但业务还在写数据,会怎么样?

  1. 嗯,这个问题我也遇到过
  2. 一般来说,我们会淘汰那些「不活跃」的数据,然后把新的数据写进去
  3. 更多情况下,还是做好对应的监控和容量的考量吧。等容量达到阈值的时候,及时发现和扩容

那要不来讲讲扩容和Redisl的架构吧?

下次吧

那要不来讲讲扩容和Redisl的架构吧?

  1. Redis的官网啊,看了这么多技术官网,我觉得Redis的官网弄得是真不错
  2. 《Redis设计与实现》这本书也挺不错的