抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

持久化简介

redis是内存数据库,它的数据都存放在内存(RAM)中,这意味着如果断电数据将会全部丢失。因此需要把数据写入硬盘(ROM)中,来保证数据可用性。这种机制就是redis的持久化机制,它会将内存中的数据库状态保存到硬盘中。

redis支持两种的持久化方式:

  1. RDB快照,在指定的时间间隔对数据进行快照存储。
  2. AOF,记录服务器每次的写操作,将操作记录追加到硬盘中存储。

持久化过程

pasted-47

  1. 客户端向数据库 发送写命令(数据在客户端的内存中)
  2. 数据库接收到客户端的写请求(数据在服务器的内存中)
  3. 数据库调用系统API将数据写入磁盘(数据在内核缓冲区中)
  4. 操作系统将写缓冲区传输到磁盘控控制器(数据在磁盘缓存中)
  5. 操作系统的磁盘控制器将数据写入实际的物理媒介(数据在磁盘中)

对于软件来说执行完第3步就认为数据已经成功持久化了,但是如果发生断电宕机等情况数据一样丢失,所以执行完第5步才是客观上真正持久化了。Linux系统中写操作会被写入缓存区中(为了提高IO速度),默认情况下是30秒在真正写入进硬盘中。如果宕机redis30秒内的数据就全没了,所以一般在生产环境的服务器中,redis通常是每隔1s左右执行一次fsync操作。

持久化方式

RDB快照方式

RDB快照当满足特定条件后例如当m秒内发生n次,执行bgsave命令生成数据集的时间点快照,或者手动输入bgsave命令生成快照。

BGSAVE 命令执行之后立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

pasted-48

1
2
3
4
# redis默认文件配置
save 900 1
save 300 10
save 60 10000

AOF方式

AOF(Append Only File - 仅追加文件)它的工作方式非常简单:每次执行修改内存中数据集的写操作时,都会记录该操作。假设AOF日志记录了自 redis实例创建以来所有的修改性指令序列,那么就可以通过对一个空的 redis 实例顺序执行所有的指令,也就是重放,来恢复redis当前实例的内存数据结构的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#AOF测试例子
127.0.0.1:6379> set str Hello
OK
127.0.0.1:6379> append str " World!"
(integer) 12
127.0.0.1:6379> del str
(integer) 1
127.0.0.1:6379> del no_existing_str
(integer) 0


#AOF文件
*2
$6
SELECT
$1
0
*3
$3
set
$3
str
$5
Hello
*3
$6
append
$3
str
$7
World!
*2
$3
del
$3

可以看到最后一个del指令不见了,因为它没有对redis数据进行修改。

AOF文件重写

redis在长期运行的情况下,AOF文件会越来越大,所以需要进行重写,将内存中的数据重新以命令的方式写入aof文件。在重写的过程中,由于redis还会有新的写入,为了避免数据丢失,会开辟一块内存用于存放重写期间产生的写入操作,等到重写完毕后会将这块内存中的操作再追加到aof文件中。

为啥要重写

例如一个计数器你不断递增几千次,AOF文件里就会存储几千次的递增操作。但是我们其实只需要递增最后的结果值。像哪些被频繁调用的key,可能会产生很多条数据,会使得AOF文件膨胀。

如何解决

redis提供了bgrewriteaof指令用于对AOF日志进行瘦身。其原理就是开辟一个子进程 对内存进行遍历转换成一系列redis的操作指令,序列化到一个新的AOF日志文件中。序列化完毕后再将操作期间发生的增量AOF日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF日志文件了,瘦身工作就完成了。

redis4.0混合持久化

重启redis时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在redis实例很大的情况下,启动需要花费很长的时间。
redis4.0为了解决这个问题,带来了一个新的持久化选项——混合持久化。将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束 的这段时间发生的增量AOF日志,通常这部分AOF日志很小:
于是在redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此大幅得到提升。