在进行第二次学习前, 首先说明下 redis
安装目录 bin
下的文件说明
-
redis-benchmark
redis性能测试工具 -
redis-check-aof
AOF文件修复工具 -
redis-check-rdb
RDB文件修复工具 -
redis-cli
命令行工具 -
redis-sentinel
集群管理工具 -
redis-server
服务进程指令
本次学习的是 Redis
的持久化. 大多是理论知识.
Redis 持久化
Redis
的持久化大致分为3种.
- RDB 快照
- AOF 重写
- 混合持久化.
下面将会对这三种持久化的方式进行学习.
1. Redis 持久化之 RDB
在默认情况下, Redis
将内存数据库快照保存在名字为 dump.rdb
的二进制文件中, 使用者可以对 Redis
进行设置, 让它在 N 秒内数据集至少有 M 个改动 这一条件被满足时, 自动保存一次数据集.
save 60 1000
, 这个设置会让 Redis 在满足 60 秒内至少有 1000 个键被改动 这一条件时, 自动保存一次数据集.
使用者还可以手动执行命令来生成 RDB 快照, 操作方式为: 进入 Redis
客户端执行命令 save
或者 bgsave
就可以生成 dump.rdb
文件. 每次命令执行都会将所有的 Redis
内存快照保存到一个新的 rdb
文件里, 并覆盖原有的 rdb
快照文件.
上面说到了 save
和 bgsave
. 这两个命令是用来做什么的呢?
-
save
是同步的, 会阻塞 -
bgsave
是异步的, 不会阻塞. 属于写时复制. 在生成快照的同时, 依然可以正常处理写的命令.
bgsave 子进程是由主进程 fork 生成的, 可以共享主进程的所有内存数据, bgsave子进程运行后, 开始读取主进程的内存数据,并把它写入到 RDB 文件, 此时如果主进程对这些数据也是读操作, 那么主进程和 bgsave 进程互不影响, 但是主进程要修改一块数据, 那么这块数据就会被复制一份, 生成改数据的副本, 然后 bgsave 子进程会把这个副本写入到 RDB 文件, 而在这个过程中, 主进程仍然可以直接修改原来的数据.
save 和 bgsave 的对比
命令 | save | bgsave |
---|---|---|
IO 类型 | 同步 | 异步 |
是否阻塞 redis 其他命令 | 是 | 否, 但是在生成子进程时, 调用 fork 函数会有短暂阻塞 |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要 fork 子进程, 消耗内存 |
配置自动生成
rdb
文件, 后台使用的是 bgsave 方式.
2. Redis 持久化之 AOF
如果 redis
因为某些原因而造成故障停机, 那么服务器就会丢失最近写入, 且仍未保存到快照中的那些数据. 从 1.1 版本开始, Redis
增加了另一种持久化的方式, 就是 AOF. 它将修改的每一条指令都记录进 appendonly.aof
文件中.
AOF 全称
append-only file
打开 AOF 功能: 在配置文件中找到 appendonly
设置为 yes
, 重启后执行写入数据的命令, 就会看到在设置RDB的目录中生成了一个 appendonly.aof
文件.
现在测试一下. 执行命令 set zhangsan4 4444
, 然后退出命令模式, 执行 cat appendonly.aof
查看.
输出的内容为:
*3
$3
set
$9
zhangsan4
$4
4444
解读: 一条命令一般是以 * 开头,
*3 表示当前命令有3部分组成.
$3 表示 set 命令有3个字符的长度
set 表示具体执行的命令
$9 表示 key 的长度
zhangsan4 表示实际的key
$4 表示 value 的长度
4444 表示实际的value
这是一种 resp
协议格式数据. *
号后面的数据代表命令有多少个参数, $
号后面的数字代表这个参数有几个字符.
在进行数据恢复的时候, 就会将这个文件内数据逐条进行恢复.
每当 Redis
执行一个改变数据集的命令时, 这个命令就会被追加到 AOF 文件的末尾. 这样的话, 每当 Redis
重新启动时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的.
2.1 AOF 的策略
-
appendfsync always
:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全. -
appendfsync everysec
:每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据. -
appendfsync no
:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择.
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性. 策略的修改, 也同样在配置文件中.
2.2 AOF 的重写
AOF 文件里可能会有太多无用的指令, 所以 AOF会定期根据内存的最新数据来生成 AOF 文件.
例如执行了如下几条命令
1 127.0.0.1:1234> incr readcount
2 (integer) 1
3 127.0.0.1:1234> incr readcount
4 (integer) 2
5 127.0.0.1:1234> incr readcount
6 (integer) 3
7 127.0.0.1:1234> incr readcount
8 (integer) 4
9 127.0.0.1:1234> incr readcount
10 (integer) 5
那么执行重写后 AOF 文件里变成
1 *3
2 $3
3 SET
4 $2
5 readcount
6 $1
7 5
AOF 自动重写频率配置
auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写, 文件太小恢复速度本来就 很快,重写的意义不大
auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写
当然 AOF还支持手动重写, 进入到 Redis
客户端执行bgrewriteaof
进行 AOF 重写.
AOF 重写
Redis
会 fork 出一个子进程去做.(与 bgsave 命令类似), 不会对Redis
正常命令处理有太多影响.
RDB 与 AOF 的区别
命令 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 容易丢失数据 | 根据策略决定 |
在生产环境的话, 两者都可以启用, Redis
启动时如果既有 rdb
文件又有 aof
文件, 则优先选择 aof
文件恢复数据, 因为 aof
一般来说数据更全一点.
3. Redis 混合持久化
当重启 Redis
时, 一般很少使用 rdb
来恢复内存状态, 因为会丢失大量数据. 我们通常使用 aof
的方式. 但是 aof
性能相对 rdb
来说要会慢很多, 这样在 Redis
实例很大的情况下, 启动需要花费很长时间, Redis
4.0 后 为了解决这个问题, 带来了一个新的持久化选项, 那就是混合持久化.
混合持久化的开启方式.(前提是 AOF 已经开启)
aof‐use‐rdb‐preamble yes
如果开启了混合持久化, aof
在重写时, 不再是单存的将内存数据转换为 resp
命令写入 aof
文件, 而是将重写这一刻之前的内存作为 rdb
快照处理, 并且将 rdb
快照内容和增量的 aof
修改内存数据的命令存在一起. 都写入新的 aof
文件, 新的文件一开始名字不是 appendonly.aof
, 而是等重写完后新的 aof
文件才会进行重命为 appendonly.aof
并覆盖原有的 aof
文件, 完成新旧两个aof
文件的替换.
Redis 数据备份策略
- 写定时调度脚本, 每隔一小时都复制一份
rdb
或aof
的备份到一个目录中去, 仅仅保留最近48小时的备份. - 每天都保留一份当日的数据备份到一个目录中, 可以保留最近1个月的备份.
- 每次复制备份的时候, 都把太久的备份删除.
- 每晚将当前机器上的备份,复制一份到其他机器上, 防止机器损坏.