Redis的持久化


redis数据存在于内存中,如果机器出了问题,就会导致数据丢失,所以要对redis数据进行备份。

redis数据备份有两种方式:

  • RDB
  • AOF

以下基于 redis3 进行实操,来看看两种方式有什么不同。

简单配置下redis:

port 6380
daemonize yes
pidfile /var/run/redis_6380.pid
# 日志文件、数据备份文件的目录
dir /usr/local/redis/data/
# rdb文件名
dbfilename 6380.rdb
stop-writes-on-bgsave-error yes
rdbcompression yes

为了方便测试,先创建一批数据:

127.0.0.1:6380> dbsize
(integer) 0
127.0.0.1:6380> debug populate 10000000
OK
(9.27s)
127.0.0.1:6380> dbsize
(integer) 10000000

 

RDB

rdb备份,可以用以下方式:

  • save
  • bgsave
  • 配置conf

save

[root@2207011 redis]# ls -lh data/
total 4.0K
-rw-r--r--. 1 root root 2.3K Jul 14 07:48 6380.log
[root@2207011 redis]# ./bin/redis-cli -p 6380127.0.0.1:6380> save
OK
(9.52s)
[root@2207011 redis]# ls -lh data/
total 256M
-rw-r--r--. 1 root root 2.3K Jul 14 08:13 6380.log
-rw-r--r--. 1 root root 256M Jul 14 08:13 6380.rdb

此时看到生成了rdb文件,对应的redis日志也会追加一条类似于5013:M 14 Jul 08:10:51.087 * DB saved on disk的记录。

save操作会把所有的redis数据写入到磁盘中,生成一个rdb格式的文件,由于没有fork新进程来做这件事,应该会堵塞redis:

在客户端中执行save

127.0.0.1:6380> save
OK
(9.90s)

此时客户端堵塞了(命令执行了大概10s),同时在另外一个客户端执行其它命令:

127.0.0.1:6380> get name
(nil)
(8.69s)

明显该命令被堵塞住了!redis是单线程的,该命令排在了save后面,只有save执行成功了,才会执行它。

bgsave

save方式虽然备份了数据,但会堵塞redis服务,并不友好!看看bgsave,又会怎样?

127.0.0.1:6380> bgsave
Background saving started

执行bgsave之后,立马返回 Background saving started 。

同时在另外一个客户端执行命令:

127.0.0.1:6380> get name
(nil)

直接返回了结果!

bgsave备份数据,会开新进程进行:

[root@2207011 redis]# ps -ef | grep redis | grep -v grep | grep -v cli
root      3912     1  1 08:40 ?        00:00:30 ./bin/redis-server *:6380
root      4049  3912 92 09:18 ?        00:00:01 redis-rdb-bgsave *:6380

在看看对应的日志信息:
3912:M 19 Jul 09:07:41.105 * Background saving started by pid 4049
4012:C 19 Jul 09:07:51.155 * DB saved on disk
4012:C 19 Jul 09:07:51.161 * RDB: 4 MB of memory used by copy-on-write
3912:M 19 Jul 09:07:51.239 * Background saving terminated with success

bgsave会异步的备份数据,比save更友好。但它进行了fork系统调用,开子进程,产生一定的系统开销,所以这个过程可能也会出现堵塞!

配置conf

编辑conf文件:
# rdb文件名
dbfilename 6380.rdb
stop-writes-on-bgsave-error yes
rdbcompression yes
# 备份条件:60s内,出现6个key的修改,则进行备份(为了测试这里设置的数值都相对较小)
save 60 6
rdbchecksum no

配置好之后,就可以重启服务。然后在一分钟内操作6个key修改。接着可以在日志里看到:

4155:M 19 Jul 10:00:53.542 * 6 changes in 60 seconds. Saving…
4155:M 19 Jul 10:00:53.543 * Background saving started by pid 4162
4162:C 19 Jul 10:00:53.545 * DB saved on disk
4162:C 19 Jul 10:00:53.545 * RDB: 6 MB of memory used by copy-on-write
4155:M 19 Jul 10:00:53.644 * Background saving terminated with success

也就是达到了 save 60 6 的条件之后,进行了自动的备份,在后台进行了一次bgsave操作。

总结

  save bgsave
优点 没有进程创建消耗 后台进行,不堵塞redis
缺点 堵塞redis 进程创建消耗系统资源

也就是说save和bgsave的优缺点是相对的。

AOF

aof备份,可以用以下方式:

  • bgrewriteaof
  • 配置conf

bgrewriteaof

127.0.0.1:6380> bgrewriteaof
Background append only file rewriting started

命令执行完成,会在后台进行数据备份。通过ps查看进程,会看到:

root      5389  5302 99 03:39 ?        00:00:02 redis-aof-rewrite *:6380

刚开始可以看到临时的数据文件如:temp-rewriteaof-bg-5389.aof,最终备份完成,生成的是6380.aof(aof文件名可以在配置指定:appendfilename选项)

[root@2207011 redis]# ls -lh data/
total 740M
-rw-r--r--. 1 root root 485M Jul 26 03:23 6380.aof
-rw-r--r--. 1 root root  732 Jul 26 03:23 6380.log
-rw-r--r--. 1 root root 256M Jul 26 03:20 6380.rdb

和rdb文件不同,aof文件保存的是生成redis数据的命令,所以通常备份相同的数据情况下,aof文件要比rdb文件大得多。

在看看对应的日志信息:

5302:M 26 Jul 03:23:33.211 * Background append only file rewriting started by pid 5389
5302:M 26 Jul 03:23:43.782 * AOF rewrite child asks to stop sending diffs.
5389:C 26 Jul 03:23:43.783 * Parent agreed to stop sending diffs. Finalizing AOF…
5389:C 26 Jul 03:23:43.785 * Concatenating 0.00 MB of AOF diff received from parent.
5389:C 26 Jul 03:23:43.786 * SYNC append only file rewrite performed
5389:C 26 Jul 03:23:43.795 * AOF rewrite: 0 MB of memory used by copy-on-write
5302:M 26 Jul 03:23:43.910 * Background AOF rewrite terminated with success
5302:M 26 Jul 03:23:43.911 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
5302:M 26 Jul 03:23:43.911 * Background AOF rewrite finished successfully

配置conf
编辑conf文件:
# 开启aof备份
appendonly yes
# aof文件名
appendfilename “6380.aof”
# 把输出缓冲区的数据写入到磁盘的策略,有no、always、everysec三种方式。其中no表示让操作系统决定什么时候刷入磁盘;always表示一有数据就调用fsync刷入磁盘;everysec表示每秒去调用一次fsync刷入磁盘。相对于no不可控,always导致磁盘io高,官方文档描述这是一种折中方式。
appendfsync everysec
# 在重写过程中,不进行appendfsync操作(aof重写就是对重复的、过期失效的数据命令进行整理,不然一个key进行数亿次的count,aof记录数亿次该count命令,aof文件就会很大;还有过期数据也是,最终还原并没有该数据。所以通过重写整理这些命令)。由于appendfsync和重写过程都进行磁盘io,磁盘io过大可能会导致redis在调用fsync的时候堵塞住!而且重写完成之后,数据备份也是完整的,所以可以在重写的时候不进行appendfsync操作。
no-appendfsync-on-rewrite no
# aof文件多大时会进行自动重写
auto-aof-rewrite-min-size 10mb
# aof文件自动重写的比例(即aof文件的增长率,该比例=当前aof文件大小-上次aof文件启动或重写的大小/上次aof文件启动或重写的大小),以下设置成100,意味着当aof文件从10mb变成20mb的时候,会自动进行重写,依此类推。
auto-aof-rewrite-percentage 100
# 通过aof文件恢复数据时尽可能多的读取完整的备份。如果redis生成aof文件过程发生死机或者其它异常的故障,就会导致aof文件不完整,再次通过aof文件恢复数据的时候,这里设置为no则会启动不了redis,设置为yes则可以最大程度去恢复数据。
aof-load-truncated yes
为了方便测试重写过程,可以设置auto-aof-rewrite-min-size 1kb。
配置好之后,重启redis服务。可以发现生成了一个空的6380.aof文件。
通过客户端执行多次incr命令,可以看到6380.aof文件不断增大。
大致看下aof文件内容,会发现:
*2
$4
incr
$1
a
大致的意思就是incr a命令
当aof文件达到了1kb的时候就会进行重写,在后台进行了一次bgrewriteaof,可以看对应的日志:
5916:M 26 Jul 10:08:14.989 * Starting automatic rewriting of AOF on 103000% growth
5916:M 26 Jul 10:08:14.990 * Background append only file rewriting started by pid 5975
5916:M 26 Jul 10:08:15.024 * AOF rewrite child asks to stop sending diffs.
5975:C 26 Jul 10:08:15.024 * Parent agreed to stop sending diffs. Finalizing AOF…
5975:C 26 Jul 10:08:15.024 * Concatenating 0.00 MB of AOF diff received from parent.
5975:C 26 Jul 10:08:15.024 * SYNC append only file rewrite performed
5975:C 26 Jul 10:08:15.024 * AOF rewrite: 6 MB of memory used by copy-on-write
5916:M 26 Jul 10:08:15.090 * Background AOF rewrite terminated with success
5916:M 26 Jul 10:08:15.090 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
5916:M 26 Jul 10:08:15.090 * Background AOF rewrite finished successfully
当关闭redis的时候,redis会一次把缓冲区的数据刷入磁盘中,可以看到对应的日志:
5814:M 26 Jul 10:00:26.290 # User requested shutdown…
5814:M 26 Jul 10:00:26.290 * Calling fsync() on the AOF file.
5814:M 26 Jul 10:00:26.290 * Removing the pid file.
5814:M 26 Jul 10:00:26.290 # Redis is now ready to exit, bye bye…

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/277164.html

(0)
上一篇 2022年7月26日
下一篇 2022年7月26日

相关推荐

发表回复

登录后才能评论