1. Redis持久化

redis的持久化

redis有两张持久化的方式:快照(RDB文件)和追加式文件(AOF文件):

  • RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。
  • AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
  • Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
  • 两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。

1.1.1. RDB

工作原理
  • redis调用fork(),产生一个子进程。
  • 子进程把数据写入到一个临时的RDB文件。
  • 当子进程写完新的RDB文件后,把旧的RDB文件替换掉。
优点
  • RDB文化文件是一个很简洁的单文件,它保存了某个时间点的redis数据,很适合用于做备份。你可以见设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
  • 基于上面描述的特性。RDB很适合用于灾备。单文件很方便就能传输到远程的服务器上。
  • RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
  • 比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
缺点
  • RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果redis因为某些原因不能正常工作,那么从上次产生快照到redis出现问题这段时间的数据就会丢失。
  • RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能会花费点时间,造成redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1s。
文件路径和名称

默认redis会把快照文件存储在当前目录下名为dump.rdb的文件。要修改文件的存储路径和名称,可以修改配置文件reids.conf,配置如下:

# RDB文件名,默认为dump.rdb。
dbfilename dump.rdb

# 文件存放的目录,AOF文件同样存放在此目录下。默认为当前工作目录。
dir ./
保存点(RDB的启用和禁用)

你可以配置保存点,是redis如果在N秒后数据发生了M次改变就保存快照文件。例如下面这个保存点配置表示每60s,如果数据发生了1000次以上的变动,redis就会自动保存快照文件。

save 60 1000

保存点可以设置多个,redis的配置文件就默认设置了3个保存点:

# 格式为:save <seconds> <changes>
# 可以设置多个。
save 900 1 #900秒后至少1个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动

如果想禁用快照保存功能,可以通过注释所有save配置,或者在最后一天save配置后添加如下配置:

save ""
错误处理

默认情况下,如果redis在后台生成快照的时候失败,就会停止接收数据,目的是让用户知道数据没有持久化成功,如果你有其他的方式可以监控到redis及其持久化的状态,那么可以把这个功能禁止掉,配置如下:

stop-writes-on-bgsave-error yes
数据压缩

默认redis采用LZF对数据进行压缩,如果想节省CPU的性能,可以把压缩功能禁用掉,但是数据集就会比没压缩的时候要大。配置如下:

rdbcompression yes
数据校验

从版本5的RDB开始,一个CRC64的校验码会放在文件的末尾。这样更能保证文件的完整性,但是在保存或者加载文件时会损失一定的性能(大概10%)。如果想追求更高的性能,可以禁用,这样文件在写入校验时会用0替代,加载的时候看到0就会直接跳过校验。

rdbchecksum yes
手动生成快照

redis提供了两个命令手动生成快照。注:配置文件禁用了快照生成功能不影响SAVE 和BGSAVE命令。

SAVE

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

BGSAVE

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

127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394

1.1.2. AOF

快照并不是很可靠。如果电脑突然宕机,或者电源断电,或者不小心杀掉进程,那么最新的数据就会丢失,而AOF文件则提供了一种更为可靠的持久化方式。每当redis接受到会修该数据集的命令是,就会把命令追加到AOF文件中,重启redis时,AOF里的命令就会被重新执行一次,重建数据。

优点
  • 比RDB可靠。可以制定不同的fsync策略:不进行fsync、每秒fsync一次(默认)、每次查询进行fsync。这意味着最多丢失1s的数据。
  • AOF日志文件是一个纯追加的文件。就算是突然断电的情况下,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(eg:磁盘满了)命令只写了一般到日志文件中,我们也可以使用redis-check-aof工具很简单的进行修复。
  • 当AOF文件太大时,reids会自动在后台进行重写。重写很安全,因为重写实在一个新的文件上进行,同时redis会继续往旧的文件上追加数据。新文件上会写入能重建当前数据集的最小操作命令集合。当新文件重写完,redis会把新旧文件进行切换,然后开始把数据写入到新文件上。
  • AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来易于恢复数据。例如不小心用FLUSHALL命令把所有数据删掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把删掉的数据恢复回来。
缺点
  • 在相同的数据集下,AOF文件的大小会比RDB文件大。
  • 在某些fsync策略下,APOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
  • 在过去曾经发现一些很罕见的bug导致使用AOF重建的数据与原数据不一致的问题。
启用AOF

修改配置项appendonlyyes

appendonly yes
文件路径和名称
# 文件存放目录,与RDB共用。默认为当前工作目录。
dir ./

# 默认文件名为appendonly.aof
appendfilename "appendonly.aof"
可靠性

redis调用fsync频率分为三种方式,推荐使用每秒fsync一次的方式(默认方式),因为它速度快,安全性也不错。

# appendfsync always //每当有新命令追加到AOF的时候调用fsync。速度最慢,最安全。
appendfsync everysec //每秒fsync一次,速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1s的数据)。
# appendfsync no //从不fsync,交由系统处理,速度最快,安全性一般。
日志重写

随着写操作的不断增加,AOF文件会越来越大。例如你递增一个计数器100次,那么最终结果就是数据集里的计数器值为最终的递增结果,但是AOF文件里却会把这100次操作完整记录下来。而事实上要恢复这个记录,只要1个命令就行了,也就是说AOF文件里那100条命令可以精简成1条。所以redis支持这样的一个功能:在不中断服务的情况下在后台重建AOF文件。

工作原理:
  • redis调用fork(),产生一个子进程。
  • 子进程把新的AOF写到一个临时文件里。
  • 主进程持续把新的变动写到内存里的buffer,同时也会把这些的变得写到旧的AOF里,这样即使重写失败也能保证数据的安全。
  • 当子进程完成文件的重写后,主进程就会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新的AOF文件里。
  • redis自动对新旧文件进行切换,然后开始把数据写到新文件上。

我们可以通过配置设置日志重写的条件:

# Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。
# 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。
# 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

要禁用自动的日志重写功能,配置如下:

auto-aof-rewrite-percentage 0
Redis 2.4以上才可以自动进行日志重写,之前的版本需要手动运行BGREWRITEAOF这个命令。
数据损坏修复

如果因为某些原因(例如服务器崩溃)AOF文件损坏了,导致redis加载不了,可以通过一下方式进行修复:

  • 备份AOF文件
  • 使用redis-check-aof命令修复原始的AOF文件。
    $ redis-check-aof --fix
    
  • 可以使用diff -u命令看下两个文件的差异。
  • 使用修复过的文件重启redis服务。
从RDB切换到AOF

这里只说redis version>=2.2的情况:

  • 备份一个最新的dump.rdb文件
  • 运行以下两条命令:

$ redis-cli config set appendonly yes
$ redis-cli config set save "" //禁用RDB的持久化非必须,可以同时启用两种持久化方式

***在切换之前必须在redis.conf中启用AOF,因为命令行方式修改配置在重启redis后就会失效。
  • 确保数据和切换前一直
  • 确保数据正确的写到AOF文件里
备份
建议的备份方法:
  • 创建一个定时任务,每小时和每天创建一个快照,保存在不同的文件夹里。
  • 定时任务运行时,把太旧的文件进行删除。例如之保存48小时的按小时创建的快照和一到两个月的按天创建的快照。
  • 每天确保一次把快照文件传输到数据中心以外的地方进行保存,至少不能保存在redis服务所在的服务器。
参考

https://segmentfault.com/a/1190000002906345

results matching ""

    No results matching ""