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 的操作日志以追加的方式写入文件)
RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是 fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储
AOF 持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
RDB优点:
RDB缺点:
AOF优点:
AOF缺点:
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的方式
现在定义一个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 <-----后台存储过程中如果出现错误现象是否停止保存操作
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
在 Redis 的配置文件中存在三种同步方式,它们分别是
本例我们设置第一种方式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
Redis 会不断地将被执行的命令记录到 AOF 文件里面,所以随着 Redis 不断运行,AOF 文件的体积也会不断增长。在极端情况下,体积不断增大的 AOF 文件甚至可能会用完硬盘 的所有可用空间。Redis 在重启之后需要通过重新执行 AOF 文件记录的所有写命令来还原数据集,所以如果 AOF 文件的体积非常大,那么还原操作执行的时间就可能会非常长。
为了解决 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þ^@û^A^@^@^Dname^FwangwuÿÕ@ýCj<87>yÂ
BGREWRITEAOF 的工作原理和 BGSAVE 创建快照的工作原理非常相似:Redis 会创 建一个子进程,然后由子进程负责对 AOF 文件进行重写。因为 AOF 文件重写也需要用到 子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在 AOF 持久 化中也同样存在。
与快照持久化通过设置 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文件,降低丢失数据的量