Write by lyc at 2018-02-05
Modify by lyc at 2018-11-28
学会这15点,让你分分钟拿下Redis数据库
关于Redis持久化

1.Redis 持久化有两种方式

  1. Snapshotting(SAVE快照):RDB持久化方式是在一个特定的间隔保存某个时间点的一个数据快照。
  2. Append-only file(AOF):AOF(Append only file)持久化方式则会记录每一个服务器收到的写操作。数据恢复时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。

Redis的持久化是可以禁用的,两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。

2.RDB 备份与恢复

每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。

配置 RDB 自动备份

配置文件配置RDB自动备份

1
2
3
4
5
6
7
8
9
10
$ vim /usr/local/redis/etc/redis-6379.conf
# rdb自动备份配置
save 900 1, # 900 秒内如果超过 1 个 Key 被修改,则启动快照保存。
save 300 10, # 300 秒内如果超过 10 个 Key 被修改,则启动快照保存。
save 60 10000, # 60 秒内如果超过 10000 个 Key 被修改,则启动快照保存。

# 其他rdb备份配置
stop-writes-on-bgsave-error yes # yes 备份失败停止接收数据
rdbcompression yes # 开启压缩
rdbchecksum yes # 开启数据校验

命令行配置RDB自动备份

1
2
3
redis-cli > config get save             # 查看配置
redis-cli > config set save "" # 关闭rdb
redis-cli > config set save "300 100" # 设置

SAVE,BGSAVE 手动备份命令

SAVE命令会使用同步的方式生成RDB快照文件,这意味着在这个过程中会阻塞所有其他客户端的请求。因此不建议在生产环境使用这个命令,除非因为某种原因需要去阻止Redis使用子进程进行后台生成快照(例如调用fork(2)出错)。

BGSAVE命令使用后台的方式保存RDB文件,调用此命令后,会立刻返回OK返回码。Redis会产生一个子进程进行处理并立刻恢复对客户端的服务。在客户端我们可以使用LASTSAVE命令查看操作是否成功。

1
2
3
4
5
6
7
8
9
10
redis-cli > SAVE
redis-cli > BGSAVE

redis-cli > lastsave
(integer) 1543395804 # 查看最后一次备份的时间戳

redis-cli > info
....
rdb_last_save_time:1543395804
rdb_last_bgsave_status:ok # 备份状态

RDB数据恢复

如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 备份目录并重新启动服务即可

两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。

3.AOF 备份与恢复

RDB快照并不是很可靠。如果服务器突然Crash了,那么最新的数据就会丢失。而AOF文件则提供了一种更为可靠的持久化方式。每当Redis接受到会修改数据集的命令时,就会把命令追加到AOF文件里,当你重启Redis时,AOF里的命令会被重新执行一次,重建数据。

原理

  • redis调用fork ,现在有父子两个进程
  • 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
  • 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题
  • 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件
  • 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加

优点

  • 比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。
  • AOF日志文件是一个纯追加的文件。就算服务器突然Crash,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。
  • 当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
  • AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。

缺点

  • 在相同的数据集下,AOF文件的大小一般会比RDB文件大。
  • 在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
  • 在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。

配置 AOF 自动备份

配置文件配置AOF自动备份

1
2
3
4
5
6
7
8
$ vim /usr/local/redis/etc/redis-6379.conf
appendonly yes
appendfsync everysec
# 指定更新日志条件,共有3个可选值:
# no:表示等操作系统进行数据缓存同步到磁盘(快)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)
appendfilename appendonly-6379.aof # aof持久化备份文件,指定更新日志文件名,默认为appendonly.aof

bgrewriteaof AOF文件重写命令

配置文件配置AOF重写相关参数

1
2
3
4
$ vim /usr/local/redis/etc/redis-6379.conf
no-appendfsync-on-rewrite yes # 设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes
auto-aof-rewrite-percentage 100 # 如果当前的aof文件大小比起上一次rewrite的aof文件大小超过指定的百分比,则会触发重写。
auto-aof-rewrite-min-size 64mb # 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。

命令行手工执行 BGREWRITEAOF

1
redis-cli > bgrewriteaof

禁用 aofrewrite,不推荐这么做,因为禁用以后,AOF文件会无限大下去。

1
2
$ vim /usr/local/redis/etc/redis-6379.conf
auto-aof-rewrite-percentage 0

4.总结

AOF 与 RDB 加载顺序

服务读取文件的优先顺序不同,会按照以下优先级进行启动:

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

注意:只要配置了 AOF,但是没有 AOF 文件,这个时候启动的数据库会是空的。

注意:save会占用2倍的内存

  • 上面说了RDB快照的持久化,在进行快照的时候savefork出来进行dump操作的子进程会占用与父进程一样的内存,真正的copy-on-write,对性能的影响和内存的耗用都是比较大的。
  • 比如机器8G内存,Redis已经使用了6G内存,这时save的话会再生成6G,变成12G,大于系统的8G。这时候会发生交换;要是虚拟内存不够则会崩溃,导致数据丢失。所以在用redis的时候一定对系统内存做好容量规划。

主备架构

通常的设计思路是利用Replication机制来弥补aof、snapshot性能上的不足,达到了数据可持久化。

  • 即Master上Snapshot和AOF都不做,来保证Master的读写性能
  • 而Slave上则同时开启Snapshot和AOF来进行持久化,保证数据的安全性。