CentOS 7.6 redis5.0的持久化工作原理及配置

一、概述

Redis 是一种高级 key-value 数据库。它跟 Memcached 类似,不过数据可以持久化, 而且支持的数据类型很丰富,有字符串、列表、集合和有序集合。支持在服务器端计算集合 (difference)等,还支持多种排序功能。所以 Redis 也可以被看成是一个数据结构服务器。 Redis 的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个 append only file(aof)里面(这称 为“全持久化模式”)。 由于 Redis 的数据都存放在内存中,如果没有配置持久化,Redis 重启后数据就全丢失了。所以,需要开启 Redis 的持久化功能,将数据保存到磁盘上,当 Redis 重启后,可以从磁盘中恢复数据。

二、持久化方式

Redis 提供两种方式进行持久化,一种是 RDB 持久化(原理是将 Reids 在内存中的数据库记录定时 dump 到磁盘上的 RDB 持久化),另外一种是AOF(append only file)持久化(原理是将 Reids 的操作日志以追加的方式写入文件)

1、RDB 持久化

RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是 fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储

在这里插入图片描述

2、AOF 持久化

AOF 持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
在这里插入图片描述

三、RDB与AOF对比

1、RDB优缺点

RDB优点:

  • 一旦采用该方式,那么整个 Redis 数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,计划每个小时归档一次最近 24
    小时的数据,同时还要每天归档一 次最近 30 天的数据。通过这样的备份策略,一旦系统出现灾难性故障,可以非常容易地进行恢复。
  • 对于灾难恢复而言,RDB 是非常不错的选择。可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
  • 性能最大化,对于 Redis 的服务进程而言,在开始持久化时,它唯一需要做的只是 fork
    出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行 IO 操作了。
  • 相比于 AOF 机制,如果数据集很大,RDB 的启动效率会更高

RDB缺点:

  • 如果想保证数据的高可用性,即最大限度的避免数据丢失,那么 RDB
    将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
  • 由于 RDB 是通过 fork 子进程来协助完成数据持久化工作的,因此当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是 1秒钟。

2、AOF优缺点

AOF优点:

  • AOF 机制可以带来更高的数据安全性,即数据持久性。Redis 中提供了 3
    种同步策略,即每秒同步、每次修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,弊端是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每次修改同步,可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中,这种方式在效率上是最低的。
  • 由于该机制对日志文件的写入操作采用的是 append 模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半 数据就出现了系统崩溃问题,那么在 Redis
    下一次启动之前,可以通过 redis-check-aof 工具来解决数据一致性的问题。
  • 如果日志过大,Redis 可以自动启用 rewrite 机制。即 Redis 以 append
    模式不断地将修改数据写入到老的磁盘文件中,同时 Redis 还会创建一个新的文件用于记录此期间 有哪些修改命令被执行。因此在进行rewrite 切换时可以更好的保证数据安全性。
  • AOF 包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,也可以通过该文件完成数据的重建。

AOF缺点:

  • 对于相同数量的数据集而言,AOF 文件通常要大于 RDB 文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
  • 根据同步策略的不同,AOF 在运行效率上往往会慢于 RDB。每秒同步策略的效率是比较高的,同步禁用策略的效率和 RDB 一样高效

四、Redis 持久化配置

1、RDB配置

(1)前台命令方式(save)

save指令:手动保存操作,执行一次就产生rdb文件

首先连接到数据库,里面暂时没有数据,新建一个key

[root@redis ~]# redis-cli
127.0.0.1:6379> 
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> keys *
1) "name"

在数据目录里没有产生任何文件

[root@redis 6379]# ll
总用量 0

这时退出连接,停止redis服务,在数据目录中多了一个.rdb文件,打开是乱码,这个就是默认的rdb文件,因为默认开启了rdb功能,只有关闭服务的时候会产生,相当于是对上次连接数据库进行的操作拍了快照保存下来

[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 112 9  12 08:33 dump.rdb

[root@redis 6379]# cat dump.rdb 
REDIS0009	redis-ver5.0.7
redis-bits￀㨭eT\used-memxª
preamble~㭡mzhangsanÿ¨錻l[root@redis 6379]# 

现在删除这个rdb文件,重启服务,重新连接数据库

[root@redis 6379]# rm -rf dump.rdb 
[root@redis 6379]# ll
总用量 0

数据库有一个key,我们输入save之后再查看数据目录,立即多了一个rdb文件

[root@redis ~]# redis-cli
127.0.0.1:6379> 
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> save
OK

[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 112 9  12 08:42 dump.rdb

这时我们再set一个key并save,观察rdb文件的大小,变大了,查看文件内容,虽然看不懂,但是有看到age的字样,说明刚才那条操作被保存了

127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> save
OK

[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 112 9  12 08:42 dump.rdb
[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 119 9  12 08:45 dump.rdb

[root@redis 6379]# vim dump.rdb 

REDIS0009ú     redis-ver^E5.0.7ú
redis-bitsÀ@ú^EctimeÂ;^Z\^Hused-mem¨^E^M^@ú^Laof-preambleÀ^@þ^@û^B^@^@^CageÀ^^^@^Dname^Hzhangsanÿù䳡ú5^A

配置文件中rdb相关参数,默认都是设置好的

242 rdbcompression yes     <----是否压缩
251 rdbchecksum yes        <----是否校验,检查保存的数据是否收到损坏,会消耗一定性能
254 dbfilename dump.rdb    <----默认的rdb文件名,可以自定义但是必须.rdb结尾

但生产环境不建议用save指令,会拉性能,因为一旦save的时间过长,会阻塞redis服务器,因为它是单线程工作的,一个指令完成才执行下个指令,所以为了解决这个问题,出现了在后台save的方式

(2)后台命令方式(bgsave)

现在定义一个key,然后执行bgsave,显示在后台运行了,不占用前台资源,你可以做其他的操作

127.0.0.1:6379> set address nanjing
OK
127.0.0.1:6379> bgsave
Background saving started
[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 136 9  12 09:03 dump.rdb

[root@redis 6379]# vim dump.rdb 

REDIS0009ú     redis-ver^E5.0.7ú
redis-bitsÀ@ú^EctimeÂO^^\^Hused-memÂø^E^M^@ú^Laof-preambleÀ^@þ^@û^C^@^@^Gaddress^Gnanjing^@^Dname^Hzhangsan^@^CageÀ^^ÿÃ<82>çF)ê.s

bgsave不是立即执行,它是针对save阻塞问题做的优化

236 stop-writes-on-bgsave-error yes    <-----后台存储过程中如果出现错误现象是否停止保存操作

(3)自动执行(配置文件)

Redis 会将数据集的快照 dump 到 dump.rdb 文件中。此外,也可以通过配置文件来修改 Redis 服务器 dump 快照的频率,这种方式本质还是用的bgsave指令操作的

格式:
save second changes 在多长时间以内,只要是这么多的key发生变化了它就执行save指令
 219 save 900 1    900 (15 分钟)之后,如果至少有 1  key 发生变化,则 dump 内存快照
 220 save 300 10   300 (5 分钟)之后,如果至少有 10  key 发生变化,则 dump
内存快照。
 221 save 60 10000    60 (1 分钟)之后,如果至少有 10000  key 发生变化,则 dump 内存快照

为了观察实验现象,设置10s内2个操作就保存一次

219 #save 900 1
 220 #save 300 10
 221 #save 60 10000
 222 save 10 2

连接到数据库,10s内设置两个key

[root@redis ~]# redis-cli
127.0.0.1:6379> set name chenyan
OK
127.0.0.1:6379> set age 40
OK

因为一开始将dump.rdb删掉了,所以目录是空的,2个操作之后就出现dump.rdb了

[root@redis 6379]# ll
总用量 0
[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 135 9  12 14:17 dump.rdb

再get一下两个的值

127.0.0.1:6379> get name
"chenyan"
127.0.0.1:6379> get age
"40"

可以看到因为get没有对数据进行实质的操作,数据没有任何改变,所以rdb文件是不存储的,所以文件大小没有变化

[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 135 9  12 14:17 dump.rdb
  • 具体save的频率最终还是要根据业务需要设置
  • get指令是不会变化的,因为key没有改变
  • set同一个key值,也不会改变,因为数据没有发生变化

2、AOF配置(默认关闭)

在 Redis 的配置文件中存在三种同步方式,它们分别是

  • appendfsync always:每次有数据修改发生时都会写入 AOF 文件
  • appendfsynceverysec:每秒钟同步一次,该策略为 AOF 的缺省策略
  • appendfsync no:系统控制

本例我们设置第一种方式aof
首先需要在配置文件里开启aof,如下所示,然后重启服务

 700 appendonly yes    <---开启aof持久化
 704 appendfilename "appendonly.aof"
 729 appendfsync always
 730 #appendfsync everysec
 731 # appendfsync no

[root@redis ~]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...

这时我们发现在数据目录里已经有了一个aof文件,但此时文件大小为0,在数据库中set一个key,aof文件就记录数据了

[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root   0 9  12 14:33 appendonly.aof
-rw-r--r-- 1 root root 135 9  12 14:33 dump.rdb

127.0.0.1:6379> set id 1
OK

[root@redis 6379]# ll
总用量 8
-rw-r--r-- 1 root root  51 9  12 14:33 appendonly.aof
-rw-r--r-- 1 root root 135 9  12 14:33 dump.rdb

再次set一个key,观察aof的文件大小,又变大了,因为又执行了一次操作

127.0.0.1:6379> set hobby game
OK

[root@redis 6379]# ll
总用量 8
-rw-r--r-- 1 root root  85 9  12 14:34 appendonly.aof
-rw-r--r-- 1 root root 135 9  12 14:33 dump.rdb

我们来get一下key,发现aof文件大小是没有改变的,因为数据没有改变

127.0.0.1:6379> get id
"1"
[root@redis 6379]# ll
总用量 8
-rw-r--r-- 1 root root  85 9  12 14:34 appendonly.aof
-rw-r--r-- 1 root root 135 9  12 14:33 dump.rdb

1、重写功能

Redis 会不断地将被执行的命令记录到 AOF 文件里面,所以随着 Redis 不断运行,AOF 文件的体积也会不断增长。在极端情况下,体积不断增大的 AOF 文件甚至可能会用完硬盘 的所有可用空间。Redis 在重启之后需要通过重新执行 AOF 文件记录的所有写命令来还原数据集,所以如果 AOF 文件的体积非常大,那么还原操作执行的时间就可能会非常长。

(1)手动重写bgrewriteaof

为了解决 AOF 文件体积不断增大的问题,用户可以向 Redis 发送 BGREWRITEAOF 命令。BGREWRITEAOF 命令会通过移除 AOF 文件中的冗余命令来重写(rewrite)AOF 文件,使 AOF 文件的体积尽可能地变小。

为了测试,删除原来的aof文件然后重启服务

[root@redis 6379]# rm -rf appendonly.aof 
[root@redis 6379]# ll
总用量 4
-rw-r--r-- 1 root root 135 9  12 14:33 dump.rdb
[root@redis ~]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...

登入数据库执行以下操作,查看aof文件的大小

127.0.0.1:6379> set name shengjie
OK
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> set name wangwu
OK

[root@redis 6379]# ll
总用量 8
-rw-r--r-- 1 root root 165 9  12 14:43 appendonly.aof
-rw-r--r-- 1 root root 122 9  12 14:43 dump.rdb

然后执行重写命令,再次观察aof文件的大小

127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

[root@redis 6379]# ll
总用量 8
-rw-r--r-- 1 root root 110 9  12 14:44 appendonly.aof
-rw-r--r-- 1 root root 122 9  12 14:43 dump.rdb

文件变小了,查看aof文件的内容,发现只有最后一条name的记录,因为前面修改的记录没有意义

[root@redis 6379]# vim appendonly.aof 

REDIS0009ú     redis-ver^E5.0.7ú
redis-bitsÀ@ú^EctimeÂQn\^Hused-memÂð^E^M^@ú^Laof-preambleÀ^^@û^A^@^@^Dname^FwangwuÿÕ@ýCj<87>

BGREWRITEAOF 的工作原理和 BGSAVE 创建快照的工作原理非常相似:Redis 会创 建一个子进程,然后由子进程负责对 AOF 文件进行重写。因为 AOF 文件重写也需要用到 子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在 AOF 持久 化中也同样存在。

(2)自动重写

与快照持久化通过设置 save 选项来自动执行 BGSAVE 一样,AOF 持久化也可以通过设置 auto-aof-rewrite-percentage 选 项 和 auto-aof-rewrite-min-size 选项来自动执行 BGREWRITEAOF

 771 auto-aof-rewrite-percentage 100
 772 auto-aof-rewrite-min-size 64mb

举个例子,假设用户对 Redis 设置了配置选项 auto-aof-rewrite-percentage 100 和 auto-aof-rewrite-min-size 64mb,并且启动了 AOF 持久化,那么当 AOF 文件的体积大于 64MB,并且 AOF 文件的体积比上一次重写之后的体积大了至少一倍(100%)的时候,Redis 将执行 BGREWRITEAOF 命令。如果 AOF 重写执行的过于频繁的话,用户可以考虑将 auto-aof-rewrite-percentage 选项的值设置为 100 以上,这种做法可以让 Redis 在 AOF 文件的体积变得更大之后才执行重写操作,不过也会让 Redis 在启动时还原数据集所需的时间变得更长

总结:官方建议同时开启RDS和AOF,更加安全

持久化的时机:如果同时开启,那么redis宕机重启后,会优先选择AOF文件,降低丢失数据的量

猜你喜欢

转载自blog.csdn.net/shengjie87/article/details/108537742