前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Redis持久化存储总结与备份

Redis持久化存储总结与备份

作者头像
用户8851537
修改2021-07-27 18:04:37
修改2021-07-27 18:04:37
87300
代码可运行
举报
运行总次数:0
代码可运行

Redis的读写性能俱佳,但由于是内存数据库,如果没有提前备份,Redis数据是掉电即失的。好在Redis提供了两种方式进行持久化:1、RDB持久化 2、AOF持久化

原理

RDB持久化

将Redis在内存中的数据定时dump到磁盘上,实际操作过程是fork一个子进程,先将数据写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储

打印rdb文件

代码语言:javascript
代码运行次数:0
复制
root@pa6:/var/lib/redis# od -c dump.rdb
0000000   R   E   D   I   S   0   0   0   6 376  \0  \0 003   k   e   y
0000020 301 177   # 377   ]   } 362 366 313 362   n 020
0000034

AOF持久化

AOF持久化:将Redis的操作日志以文件追加的方式写入文件,只记录写、删除操作,查询操作不会记录(类似于MySQL的Binlog日志)

自动间隔性保存

因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令

用户可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令 举个例子,如果我们向服务器提供以下配置

vim redis.conf

代码语言:javascript
代码运行次数:0
复制
save 900 1
save 300 10
save 60 10000

那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行 服务器在900秒之内,对数据库进行了至少1次修改

服务器在300秒之内,对数据库进行了至少10次修改

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

RDB持久化实现

Redis数据库Redis是一个字典结构的存储服务器,一个Redis实例提供了多个用来存储数据的容器, 客户端可以指定将数据存储在哪个容器中(类似于MySQL中的数据库)。

Redis默认支持16个数据库,可以通redis.conf配置文件修改数据库个数,客户端与Redis建立连接之后默认选择0号数据库

备份
  • 自动开启RDB持久化

修改配置文件

代码语言:javascript
代码运行次数:0
复制
# 默认redis会开启RDB持久化
备份文件的名称
dbfilename dump.rdb

备份文件存放路径
dir /var/lib/redis   
  • 当前数据库备份

Redis的SAVE命令和BGSAVE命令用于将当前数据库备份

代码语言:javascript
代码运行次数:0
复制
127.0.0.1:6379> save  #数据量大的话cpu会爆炸
OK

127.0.0.1:6379> bgsave    #建议使用这个
Background saving started

SAVE和BGSAVE命令的区别在于:SAVE命令是阻塞主进程,save操作完成之后,主进程才开始工作,客户端可以连接;BGSAVE命令是fork一个专门save的子进程,此操作不会影响主进程

注:SAVE只是将当前的数据库备份,备份文件名默认为dump.rdb,可通过配置文件修改备份文件名 dbfilename xxx.rdb(发现一个问题:如果要对多个数据库进行备份,那么最终只能备份最后一个数据库,因为dump.rdb文件会相互覆盖)

恢复

将备份的RDB文件,cp到要恢复的redis指定目录,重启Redis即可自动读取持久化文件,自动恢复数据

  • 备份的RDB文件: 通过命令redis 127.0.0.1:6379> CONFIG GET dir查看执行SAVE命令之后,redis默认存放备份文件的目录;通过命令redis 127.0.0.1:6379> CONFIG GET dbfilename查看备份RDB文件的文件名称;
代码语言:javascript
代码运行次数:0
复制
root@pa6:~# redis-cli
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/var/lib/redis"
127.0.0.1:6379> CONFIG GET dbfilename
1) "dbfilename"
2) "dump.rdb"

AOF持久化实现

备份

备份过程分以下三个阶段
  • 命令传播: Redis将执行完的命令、命令参数等信息发送到AOF程序
  • 缓存追加: AOF程序将接收到的命令内容追加到服务器的AOF缓存中
  • 文件写入和保存: AOF缓存中的内容被写入到AOF文件末尾,如果满足AOF保存条件,写入的内容会真正保存到磁盘中
进行AOF备份
  • 首先开启AOF功能

修改配置文件

代码语言:javascript
代码运行次数:0
复制
#此选项为aof功能的开关,默认为“no”,通过“yes”来开启aof功能
appendonly yes  

#指定aof文件名称
appendfilename appendonly.aof

#备份文件存放路径(此参数同样适用于指定RDB备份文件存放路径)
dir /var/lib/redis
设置保存模式(配置文件)

AOF有3种方式将操作命令存入AOF文件

1. appendfsync no 不保存

只执行WHRITE操作,SAVE操作会被略过,只有在Redis被关闭AOF功能被关闭系统的写缓存被刷新(如缓存已被写满)这三种情况,SAVE操作会被执行,但是这三种情况都会引起Redis主进程阻塞

2. appendfsync everysec 每秒钟保存一次

这种模式中,SAVE原则上每隔一秒钟就会执行一次,具体的执行周期和文件写入、保存时,Redis所处的状态有关,此模式下SAVE操作由后台子线程调用,不会引起服务器主进程的阻塞

3. appendfsync always 每执行一个命令保存一次 在这种模式下,每执行一个命令,WRITESAVE都会被执行,且SAVE操作会阻塞主进程

模式

WRITE阻塞

SAVE阻塞

停机时丢失的数据量

appendfsync no

阻塞

阻塞

操作系统最后一次对 AOF 文件触发 SAVE 操作之后的数据

appendfsync everysec

阻塞

不阻塞

一般情况下不超过 2 秒钟的数据

appendfsync always

阻塞

阻塞

最多只丢失一个命令的数据

设置好AOF写入的模式之后,只要达到写入条件(比如一秒钟、执行一个命令),就会自动在指定路径下生成AOF文件,并往里面记录操作命令

AOF文件重写

AOF文件通过同步Redis服务器所执行的命令,实现对数据库状态的记录。有些被频繁操作的键,对它们所调用的命令可能有成百上千、甚至上万条,这样很容易出现AOF文件体积急速膨胀,对Redis甚至整个系统造成影响。

  • AOF重写实现原理

如果服务器对键list执行以下四条命令:

代码语言:javascript
代码运行次数:0
复制
RPUSH list 1 2 3 4      // [1, 2, 3, 4]

RPOP list               // [1, 2, 3]

LPOP list               // [2, 3]

LPUSH list 1            // [1, 2, 3]

那么当前列表键list在数据库的值就是[1,2,3],如果我们要保存这个列表的当前状态,并且尽可能地减少使用命令数,最简单的方法是直接读取list键在数据库的当前值,然后用一条RPUSH list 1 2 3命令代替前面四条命令。

根据键的类型,使用适当的写入命令来重现键的当前值,这就是AOF重写的实现原理

  • AOF后台重写

子程序处理: AOF重写程序,会阻塞主进程,作为一种辅助性的维护手段,Redis不希望AOF重写造成服务器无法处理请求,所以Redis会将重写程序放到子进程执行。

AOF重写缓存: 不过,使用子进程也有一个问题需要解决:子进程在进行AOF重写期间,主进程还在继续处理命令,新的数据更新不能同步到重写后的AOF文件中。为了解决这个问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,重写期间的写操作,除了会将写命令追加到现有的AOF文件之外,还会追加到这个缓存中。子进程完成重写操作之后,它会向父进程发送一个完成信号,父进程接到完成信号之后,会调用一个信号函数,将AOF重写缓存中的内容写入新的AOF文件中。

性能影响: 在整个AOF后台重写的过程中,只有最后的写入缓存会造成主进程的阻塞,其他时候,AOF后台重写都不会阻塞主进程。

  • 进行后台重写:

1. 系统自动后台重写(需满足一定触发条件):

i 没有正在执行的BGSAVEBGREWRITEAOF命令

ii 当前AOF文件大小大于aof_rewrite_min_size

iii AOF文件大小和最后一次重写大小的比率大于aof_rewrite_perc

2. 手动后台重写:

通过BGREWRITEAOF手动重写

恢复

和RDB恢复是一样的操作,将备份的AOF文件,放在指定目录,重启Redis即可恢复数据(具体可参照上文的RDB恢复数据)

ps: 当指定目录同时有RDB文件和AOF文件时,还原数据时AOF文件的优先级是高于RDB文件的,所以优先通过AOF文件还原数据

二者优缺点

RDB持久化

优点:

  • RDB方式备份,整个Redis数据库最终备份成一个文件,这对于文件备份而言是完美的(方便管理、还原、压缩、转储)
  • 对服务进程影响最小,唯一需要做的是fork出子进程,之后所有的持久化工作交由子进程处理
  • 相比于AOF机制,如果数据量比较大,RDB的启动效率会更高(记录的是源数据,而非数据操作)

缺点:

  • 数据的可用性得不到太大的保障,如果在定时持久化之前出现宕机现象,此前没来得及写入磁盘的数据都将丢失
  • 如果数据量较大,fork子进程的操作可能会使服务短暂停止(通常是几百毫秒)

AOF持久化

优点:

  • 拥有更高的数据可用性,数据持久化最完整
  • 日志文件采用append模式,即使在写入过程中出现宕机现象,也不会破坏日志文件之前已经存在的内容
  • 提供rewrite机制,当日志过大时,Redis以append模式不断将修改的日志写入老的磁盘文件,同时Redis还会创建一个新的文件用于记录此期间有哪些命令被执行

缺点:

  • 对于相同数量的数据,AOF文件通常大于RDB文件,RDB文件在恢复大数据集的速度比AOF恢复的更快(RDB省去了执行的步骤,直接导入源数据)

总结

RDB持久化,性能更好(所有操作均由子进程处理,主进程不进行任何IO操作),数据一致性一般。

AOF持久化,数据一致性更好,性能一般(记录操作日志,写入日志和执行日志恢复数据的时间都比RDB更长)。

Redis 恢复的机制

  • 如果只配置 AOF ,重启时加载 AOF 文件恢复数据;
  • 如果同时配置了 RDB 和 AOF ,启动是只加载 AOF 文件恢复数据;
  • 如果只配置 RDB,启动是将加载 dump 文件恢复数据。

备份脚本

demo

代码语言:javascript
代码运行次数:0
复制
#!/bin/bash
# 避免造成雪崩
set -e
# bak 目录
BACKUPDIR=/data/redis/backup
#PASSWD='redis密码'
#DATADIR=`/usr/local/bin/redis-cli -p 端口 -a "$PASSWD" config get dir|grep -Ev 'dir|grep'`
# 获取redis-cli 二进制文件
REDIS_CMD=$(which redis-cli)
DATADIR=`$REDIS_CMD  config get dir|grep -Ev 'dir|grep'`
DATE=`date +'%Y-%m-%d-%H-%M'`
BACKUPDIR_DATE=$BACKUPDIR_$DATE

if [ ! -d $BACKUPDIR ];then
        mkdir -p $BACKUPDIR \
        || echo "can't make dir !!!" \
        && exit 1
fi
#以日期分类
mkdir -p $BACKUPDIR/$BACKUPDIR_DATE
$REDIS_CMD  bgsave
sleep 3
cp -rf $DATADIR/* $BACKUPDIR/$BACKUPDIR_DATE

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理
    • RDB持久化
    • AOF持久化
  • 自动间隔性保存
  • RDB持久化实现
    • 备份
    • 恢复
  • AOF持久化实现
    • 备份
      • 备份过程分以下三个阶段
      • 进行AOF备份
      • 设置保存模式(配置文件)
      • AOF文件重写
    • 恢复
  • 二者优缺点
    • RDB持久化
    • AOF持久化
  • 总结
    • Redis 恢复的机制
  • 备份脚本
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档