redis核心篇(二)-数据持久化

317 阅读6分钟

1.前言

通常对于讨论到redis为何如此之快,第一反应可能就是:Redis是内存数据库,它将自己的数据库都储存在内存里面;既然数据都是在内存中,如果服务进程退出,数据应该无了;但是很多时候,我们重启进程,数据依旧还在,而且很多时候,redis有10多G的数据,在进程退出的时候,也能迅速将这10多G的数据恢复,这些听起来跟内存的存储特性又互相违背;为了达到这些效果,Redis提供了数据持久化功能,这个功能可以将Redis在内存中的数据库状态保存到磁盘里面,可以做到宕机快速恢复。

2.RDB内存快照

内存快照,指的就是Redis内存中的数据在某一刻全量数据。

rdb 触发机制:

  • 手动执行,通过执行相关命令:

    • save:当SAVE命令执行时,Redis服务器会被阻塞,所以当SAVE命令正在执行时,客户端发送的所有命令请求都会被拒绝
    • bgsave:BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件
  • 服务器配置选项定期执行,将某个时间点上的数据库状态保存到一个快照文件中。

举个例子,如果我们向服务器提供以下配置:

save 900 1
save 300 10
save 70  10000

那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行:

  • 服务器在900秒之内,对数据库进行了至少1次修改。
  • 服务器在300秒之内,对数据库进行了至少10次修改。
  • 服务器在60秒之内,对数据库进行了至少10000次修改。

2.2.1 原理

image.png

通过手动执行命令或者redis内部的时间事件,都能够将某一时候的全量数据进行保存下来;但不知道有没有小伙伴想过,全量数据保存,当数据量达到10多G的时候,也不可能瞬时完成,在备份的这段时间里,数据在不断的变化着,同时,数据写入磁盘也没那么快,那该怎么保证这备份的数据就是T1,T2,T3时候的数据呢?当然,redis也不可能将内存的数据复制一份。同时让内存保留两份一模一样的数据,那这样,redis的内存使用率就只有50%不到,这对于使用者也是万万不能接受的

2.2.2 COW

image.png

cow,写时复制(Copy On Write),Redis在执行BgSave命令的时候,会fork一个子进程,快照的持久化将交由子进程完成;子进程会保留一份父进程的全量数据索引指针,并不在创建子进程的时候,对数据也进行全量复制一份;当数据发生变化,如修改的时候,父进程会将原先数据复制一份到新的内存,然后再修改数据内容,改变指针指向,如图上的d。所以对于此处,可以理解为,就是在玩指针

linux父子进程关系:

  • 父进程的数据变化,子进程无法看到。
  • 子进程的数据修改,无法影响到父进程,父进程的修改,也无法影响到子进程。

2.2.3 rdb优缺点

弊端:

  • 不支持拉链,只有一个dump.rdb文件。
  • 丢失数据相对多一些,时间点的窗口数据容易丢失。
  • 生成RDB文件频率不好把握,频率过低,宕机丢失的数据就会比较多;频率过高,对磁盘读写压力过大。

优点:

  • 恢复速度快

2.3 AOF(append only file)

Redis除了提供RDB的持久化功能之外,还提供了AOF(Append Only File)的持久化功能,与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF是通过保存Redis服务器所执行的写命令来记录数据库状态的。

image.png 当客户端发送写命令的时候,redis会将该命令以协议格式的内容写入到aof缓冲区;然后在Redis服务器每次结束一个事件循环之前,会读取appendfsync配置,根据配置考虑是否需要将aof缓冲区中的内容写入和保存到AOF文件里面。

  • appendfsync:
    • always:将AOF的缓冲区同步到AOF文件中
    • eveerysec:将AOF的缓冲区同步到AOF文件中。如果上一次同步时间超过一秒钟,则再次对AOF文件进行同步,并且这个同步操作,是有一个线程专门负责的
    • no:将AOF缓冲区的内容写入到aof文件中,但不对文件进行同步,何时同步,则交由操作系统决定。

注:此处的同步,是磁盘文件缓存去同步到磁盘。通常而言,我们写入文件,会发生两个步骤,写入文件缓冲区,缓冲区满了,再写入到磁盘。

对于这个配置的,其实大多数开源项目都是同一个思想,在性能和可靠之间做权限,例如kafka的数据同步,拿redis来讲,想要获得高性能,就选择No策略;如果想要得到高可靠性保证,就选择 Always策略;如果允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择 Everysec 策略。

2.3.2 优缺点

缺点:

  • AOF文件容易造成无限大,当redis服务进程长时间运行之后,aof文件过大,不仅会对追加造成影响,同时也会对数据恢复的速率造成极大影响。 优点:
  • 丢失数据少

2.3.3 AOF重写(aof_rewrite)

AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的AOF文件很可能对Redis服务器、甚至整个宿主计算机造成影响,并且AOF文件的体积越大,使用AOF文件来进行数据还原所需的时间就越多,当还原时间长达半个小时,甚至一分钟,那备份可能就变得毫无意义

2.3.3.1 aof_rewrite原理

image.png

AOF文件重写,可通过执行BGREWRITEAOF命令;执行该命令之后,redis服务会fork一个子进程,该子进程将此时的数据快照写入到AOF文件中(前面rdb原理已经说到,子进程看不到父进程的数据修改),同时Redis服务器会维护一个AOF重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个AOF文件所保存的数据库状态一致。最后,服务器用新的AOF文件替换旧的AOF文件,以此来完成AOF文件重写操作