今天是个好天气 logo 今天是个好天气
  • Home
  • Go
  • MySQL
  • Redis
  • LeetCode
  • Hello World
↩️README 数据结构 Redis是怎么运行的 持久化 缓存过期与内存淘汰 集群模式 缓存 分布式锁 事务机制 Hot Key / Big Key

Redis数据丢失怎么办

持久化介绍

Redis是跑在内存里的,当程序重启或者服务崩溃,数据就会丢失,如果业务场景希望重 启之后数据还在,就需要持久化,即把数据保存到可永久保存的存储设备中。

持久化方式:

  1. RDB(Redis Database),记录Redis某个时刻的全部数据,这种方式的本质就是数据快照,直接保存二进制数据到磁盘当中,后续通过加载RDB文件恢复数据。
  2. AOF(Append Only File),记录执行的每条命令,重启之后通过重放命令来恢复数据,AOF本质是记录操作日志,后续通过日志重放恢复数据。

二者的区别:

  • 体积方面:相同数据量下,RDB体积更小,因为RDB是记录的二进制紧凑型数据
  • 恢复速度:RDB是数据快照,可以直接加载,而AOF文件恢复,相当于重放情况,RDB显然会更快
  • 数据完整性:AOF记录了每条日志,RDB是间隔一段时间记录一次,用AOF恢复数据通常 会更为完整。

应用场景:

如果业务本身只是缓存数据而不是海量访问,不用开持久化。

如果对数据非常重视,可以同时开启RDB和AOF,优先使用AOF(AOF内容更全,数据恢复更完整)。

如果可以接受丢几分钟级别的数据,那么建议只开RDB。单独开AOF,Rdis官方不建议,因为如果决定要走数据备份,那么镜像保存始终是数据库领域非常行之有效的解决方案,所以在配置中RDB是默认打开的,而AOF不是。

RDB

Redis默认是开启RDB持久化的,在redis.windows.conf可以看到。

save 900 1
save 300 10
save 60 10000

表示每900s,有1条写数据操作

每300s,有10条写数据操作

每600s,有10000条写数据操作

这里的写操作指增加、删除及更新,就会激活RDB持久化(触发bgsave)。

什么时候进行持久化

  1. 主动执行命令save,会有响应的提示输出。就会在主线程生成RDB文件,由于和执行操作命令在同一个线程,所以如果写入RDB文件的时间太长,会阻塞主线程,这个命令慎用。

  2. 主动执行bgsava,区别save,会创建一个子进程生成RDB文件,避免主线程的阻塞。

  3. 达到持久化配置阈值,周期函数检查是否达到策略,达到就触发bgsave。

  4. 程序正常关闭时执行,以记录更全的数据。

具体做了什么

  1. Fork出一个子进程来专门做RDB持久化
  2. 子进程写数据到临时的RDB文件
  3. 写完之后,用新RDB文件替换旧的RDB文件

执行持久化过程中,Redis依然可以继续处理操作命令,数据是能被修改的,主要通过写时复制技术实现,相当于异步执行。

fork出的子进程后,子进程复制了页表,但是页表指向的物理内存还是同一块。

只有当修改内存数据时,物理内存才会被复制一份。此时Redis使用bgsave对当前内存当中的所有数据做快照,主线程修改的副本,这部分不会追加给子进程进行持久化。

这样做减少了创建子进程过程时的性能损耗,从而加快创建子进程的速度,因为创建过程会阻塞主线程。

AOF

默认情况下,AOF是关闭的,应该根据实际需要打开。

打开之后,Redis每条更改数据的操作都会记录到AOF文件中,当你重启,AOF会助你重建状态,相当于就是请求全部重放一次,所以AOF恢复起来会比较慢。

写入流程

执行请求时,每条日志都会写入到AOF当中,会一定程度上影响程序性能。因此Redis提供了3种刷盘策略,以便根据需要进行不同的选择。

  1. appendfsync always,每次请求都刷入AOF,用官方的话说,非常慢,非常安全
  2. appendfsync everysec,每秒刷一次盘,用官方的话来说就是足够快了,但是在崩溃场 景下你可能会丢失1秒的数据。
  3. appendfsync no,不主动刷盘,让操作系统自己刷,一般情况Linux会每30秒刷一次 盘,这种策略下,可以说对性能的影响最小,但是如果发生崩溃,可能会丢失相对比较 多的数据。

Redis建议方案2,在保证速度情况下,崩溃丢失1s的数据认为大多数场景是可以接受的。

在不存在超级热点缓存时,丢失30s不是问题时,可以使用方案3。

方案1使用场景较少,因为Redis本身是无法做到完全不丢数据,Redis定位就不是完全可靠的,没有必要损耗大量性能去追求立刻刷盘。

写入AOF细节

  1. 将数据写入AOF缓存(aof_buf)当中,本质是一个sds数据。

  2. aof_buf将对应数据刷入到磁盘缓冲区,对应四个时机,会调用flushAppendOnlyFIle函数,其使用Write函数将数据写入操作系统缓冲区:

    • 处理完事件处理后,等待下一次事件到来之前,也就是beforeSleep中

    • 周期函数serverCron

    • 服务器退出之前的准备工作时

    • 通过配置指令关闭AOF功能时

    注意,如果是appendfsync everysec策略,那么在上一次fsynci还没完成之前,并且时长 不超过两秒时,就本次flushAppendOnlyFile就会放弃,也就是说先不写入aof_buf的,等待下次调度。

  3. 刷盘,调用系统的flush函数。

AOF重写

Redis在AOF文件体积过大时,自动在后台Fork一个子进程,专门对AOF重写。

针对相同Key的操作,进行合并,比如对同一个Key的set,用后者覆盖前者。

在重写过程中,新的操作记录不仅记录在原有的AOF缓冲区,还会记录在AOF重写缓冲区,在新的AOF文件创建好时,一起追加到新文件当中,再用新的AOF替代旧的AOF。

重写时机:

  • 相比上次重写时候数据增加100%
  • 超过设定的值64MB时

二者都是配置决定的,最后实际上还是周期函数检查然后触发。

混合持久化

混合部署实际发生在AOF重写阶段,将当前状态保存为RDB二进制文件内容,写入AOF文件,再将重写缓冲区的内容追加到AOF文件中。

此时的AOF文件,是二进制数据+日志数据的混合体,所以叫做混合持久化。

解决了什么问题

发生在AOF流程当中,本质上还是AOF,只是重写时使用RDB进行优化。

是RDB和AOF的折中。

更好解决了AOF体积过大的问题,同时文件恢复数据更快。

怎么开启

对应配置文件的,aof-use-rdb-preamble。

在5.0之后默认是打开的,所以5.0之后只要AOF配置开启,默认就是混合持久化。

如何加载持久化数据

同时启用AOF和RDB时,Redis重新启动时,会使用AOF文件重建数据集。

通常来说AOF数据更完整,混合持久化属于AOF,有混合持久化时,优先使用混合持久化的数据。

通过判断文件开头是否有REDIS来判断。

  1. 持久化介绍
  2. RDB
    1. 什么时候进行持久化
    2. 具体做了什么
  3. AOF
    1. 写入流程
    2. 写入AOF细节
    3. AOF重写
  4. 混合持久化
    1. 解决了什么问题
    2. 怎么开启
    3. 如何加载持久化数据
Created by shixiaocaia | Powered by idoc
Think less and do more.