redis持久化存储之RDB VS AOF

RDB 优点:

1.RDB是一种表示某个即时点的 Redis 数据的紧凑文件。RDB 文件适合用于备份。例如,你可能想要每小时归档最近 24 小时的 RDB 文件,每天保存近 30 天的 RDB 快照。这允许你很容易的恢复不同版本的数据集以容灾。

2.RDB非常适合于灾难恢复,作为一个紧凑的单一文件,可以被传输到远程的数据中心,或者是 Amazon S3(可能得加密)。

3.RDB最大化了 Redis 的性能,因为 Redis 父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像磁盘 IO 这样的操作。

4.RDB 在重启恢复大数据集的实例时比AOF要快。

RDB缺点:

1.当你需要在 Redis 停止工作(例如停电)时最小化数据丢失,RDB 可能不太好。你可以配置不同的保存点。然而,你通常每隔 5 分钟或更久创建一个 RDB 快照,所以一旦 Redis 因为任何原因没有正确关闭而停止工作,你就得做好最近几分钟数据丢失的准备了。

2.RDB 需要经常调用 fork()子进程来持久化到磁盘。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且 CPU 性能不够强大的话,Redis 会停止服务客户端几毫秒甚至一秒。AOF 也需要 fork(),但是你可以调整多久频率重写日志而不会有损(trade-off)持久性(durability)。

AOF优点:

1.使用 AOF Redis 会更具有可持久性(durable):你可以有很多不同的 fsync 策略:没有 fsync,每秒 fsync,每次请求时 fsync。使用默认的每秒 fsync 策略,写性能也仍然很不错(fsync 是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。

2.AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof 工具也可以很轻易的修复。

3.AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个 AOF 文件。例如,即使你不小心错误地使用 FLUSHALL 命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启 Redis 就可以。

AOF缺点:

1.对同样的数据集,AOF 文件通常要大于等价的 RDB 文件。

2.AOF可能比RDB慢,这取决于准确的 fsync 策略。在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)

RDB和AOF如何取舍

通常来说,你应该同时使用这两种持久化方法,以提高数据安全程度。

如果你很关注你的数据,但是仍然可以接受灾难时有几分钟的数据丢失,你可以只单独使用 RDB。

有很多用户单独使用 AOF,但是我们并不鼓励这样,因为时常进行 RDB 快照非常方便于数据库备份,启动速度也较之快,还避免了 AOF 引擎的 bug。

redis持久化存储

redis支持两种方式的持久化,可以单独使用或者结合起来使用
第一种:RDB方式,redis默认的持久化方式,

第二种:AOF方式,需要手动修改配置。下面我们来看一下两种持久化方式以及持久化中所注意的一些问题。

持久化之RDB

rdb方式的持久化是通过快照完成的,当符合一定条件时redis会自动将内存中的所有数据执行快照操作并存储到硬盘上。默认存储在dump.rdb文件中(文件名在配置文件中dbfilename),默认打开可以到启动的目录去查看,注意: dump.rdb是在哪儿启动redis,就会在哪儿生成rdb文件。

  • dump.rdb
    [root@momo1 ~]# cd /usr/local/redis/
    [root@momo1 redis]# ll
    总用量 156
    -rw-rw-r--. 1 root root 34339 12月 18 23:19 00-RELEASENOTES
    -rw-rw-r--. 1 root root 53 12月 18 23:19 BUGS
    -rw-rw-r--. 1 root root 1805 12月 18 23:19 CONTRIBUTING
    -rw-rw-r--. 1 root root 1487 12月 18 23:19 COPYING
    drwxrwxr-x. 6 root root 4096 4月 27 19:40 deps
    -rw-r--r--. 1 root root 36 4月 29 01:20 dump.rdb ##dump.rdb
    -rw-rw-r--. 1 root root 11 12月 18 23:19 INSTALL
    -rw-rw-r--. 1 root root 151 12月 18 23:19 Makefile
    -rw-rw-r--. 1 root root 4223 12月 18 23:19 MANIFESTO
    -rw-rw-r--. 1 root root 5201 12月 18 23:19 README
    -rw-rw-r--. 1 root root 41561 4月 27 19:53 redis.conf
    -rwxrwxr-x. 1 root root 271 12月 18 23:19 runtest
    -rwxrwxr-x. 1 root root 280 12月 18 23:19 runtest-cluster
    -rwxrwxr-x. 1 root root 281 12月 18 23:19 runtest-sentinel
    -rw-rw-r--. 1 root root 7113 4月 29 00:26 sentinel.conf
    drwxrwxr-x. 2 root root 4096 4月 27 19:41 src
    drwxrwxr-x. 10 root root 4096 12月 18 23:19 tests
    drwxrwxr-x. 5 root root 4096 12月 18 23:19 utils
  1. redis进行快照的时机(在配置文件redis.conf中)
    1. save 900 1:表示900秒内至少一个键被更改则进行快照。
    2. save 300 10
    3. save 60 10000
  2. redis实现快照的过程
    1. redis使用fork函数复制一份当前进程的副本(子进程)
    2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件
    3. 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此,一次快照操作完成。
  3. 手动执行save或者bgsave命令让redis执行快照
    1. save是由主进程进行快照操作,会阻塞其它请求。
    2. bgsave是由redis执行fork函数复制出一个子进程来进行快照操作。
  4. 文件恢复:redis-check-dump
    [root@iZ94r8hgrjcZ /]# redis-check-dump dump.rdb 
    ==== Processed 5 valid opcodes (in 45 bytes) ===================================
    CRC64 checksum is OK
  • rdb的优缺点
    优点:由于存储的有数据快照文件,恢复数据很方便。
    缺点:会丢失最后一次快照以后更改的所有数据。
  • 注意
  1. redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的
  2. 我们可以通过定时备份RDB文件来实现redis数据库的备份。
  3. RDB文件是经过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输。
  • 示例代码:
    127.0.0.1:6379> set a 123
    OK
    127.0.0.1:6379> set b 456
    OK
    127.0.0.1:6379> keys *
    1) "b"
    2) "a"
    127.0.0.1:6379> shutdown
    not connected> exit
    ###注意此时有值,关掉退出然后我们切换一下目录后再启动,就会是一个新的rdb文件,无值
    
    [root@momo1 redis]# cd /home/up/
    [root@momo1 up]# redis-server /etc/redis.conf 
    [root@momo1 up]# redis-cli 
    127.0.0.1:6379> keys *
    (empty list or set)
    127.0.0.1:6379> shutdown
    not connected> exit
    [root@momo1 up]# ll
    总用量 1348
    -rw-r--r--. 1 root root 18 4月 29 04:04 dump.rdb

持久化之AOF

aof方式的持久化是通过日志文件的方式。默认情况下redis没有开启aof,可以通过参数appendonly参数开启。appendonly yes
aof文件的保存位置和rdb文件的位置相同,都是dir参数设置的,默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof

appendonly.aofappendonly.aof
aof同步的时机aof同步的时机
  1. redis写命令同步的时机
    1. appendfsync always 每次都会执行
    2. appendfsync everysec 默认 每秒执行一次同步操作(推荐,默认)
    3. appendfsync no不主动进行同步,由操作系统来做,30秒一次
  2. aof日志文件重写
    1. auto-aof-rewrite-percentage 100(当目前aof文件大小超过上一次重写时的aof文件大小的百分之多少时会再次进行重写,如果之前没有重写,则以启动时的aof文件大小为依据)
    2. auto-aof-rewrite-min-size 64mb
  3. 手动执行bgrewriteaof进行重写

    重写的过程只和内存中的数据有关,和之前的aof文件无关。即针对数据库中当前数据进行重新整理成redis语句

  4. 文件恢复:redis-check-aof
  • 示例代码:
    ## 在rdb是持久化下游三个keys
    [root@momo1 redis]# redis-cli
    127.0.0.1:6379> keys *
    1) "d"
    2) "a"
    3) "b"
    
    ## 
    [root@momo1 redis]# vim redis.conf #修改appendonly yes
    [root@momo1 redis]# redis-server ./redis.conf 
    [root@momo1 redis]# redis-cli
    127.0.0.1:6379> keys *
    (empty list or set)

动态切换redis持久方式

RDB 切换到 AOF支持Redis 2.2及以上

  • 问题: 在很多情况下,默认使用了rdb持久化方式,如果我们再开启aof持久化方式,就会发现一个问题 : 原先的redis数据丢失了!
  • 主要原因: redis的aof持久化方式是最安全的,如果开启aof之后,redis会优先选择aof的方式,而appendonly.aof文件此时还是空文件于是之前的数据就丢失了。
  • 解决办法: 使用config命令,首先动态修改配置,然后再修改配置文件!
    1. cinfig set appendonly yes
    2. config set save “”(可选,如果开启了aof可以选择关闭rdb)
  • 总结:
  1. 当redis启动时,如果rdb持久化和aof持久化都打开了,那么程序会优先使用aof方式来恢复数据集,因为aof方式所保存的数据通常是最完整的。如果aof文件丢失了,则启动之后数据库内容为空。
  2. 如果想把正在运行的redis数据库,从RDB切换到AOF,先使用动态切换方式,再修改配置文件,重启数据库。(不能自己修改配置文件,重启数据库,否则数据库中数据就为空了。)
  3. 如果我们失误操作,没有动态切换数据为空了,我们应该尽快手动kill掉redis进程,然后删掉aof备份文件改掉配置后重新动态切换。
  • 示例代码:动态切换
    127.0.0.1:6379> config set appendonly yes
    OK
    127.0.0.1:6379> mget a b d
    1) "123"
    2) "123"
    3) "999"
    
    ####然后我们来看一下appendonly.aof文件内容
    [root@momo1 redis]# vim appendonly.aof 
    *2
    $6
    SELECT
    $1
    0
    *3
    $3
    SET
    $1
    d ##d的值
    $3 ##长度为3
    999 ##值为999
    *3
    $3
    SET
    $1
    b
    $3
    123
    *3
    $3
    SET
    $1
    a
    $3
    123
  • 示例代码:如果我们失误操作,没有动态切换数据为空了
    [root@momo1 redis]# vim redis.conf #修改appendonly yes此时没有动态切换
    [root@momo1 redis]# redis-server ./redis.conf ##启动
    [root@momo1 redis]# redis-cli ##此时有数据
    127.0.0.1:6379> keys *
    (empty list or set)
    
    [root@momo1 redis]# ps -ef|grep redis ##重开一个端口kill进程
    root 6399 1 0 04:20 ? 00:00:00 redis-server *:6379 
    root 6402 5794 0 04:20 pts/2 00:00:00 redis-cli
    root 6413 6113 0 04:21 pts/3 00:00:00 grep redis
    [root@momo1 redis]# kill -9 6399 
    [root@momo1 redis]# rm -rf appendonly.aof ##删掉appendonly.aof
    [root@momo1 redis]# vim redis.conf ##再次改回no
    [root@momo1 redis]# redis-server ./redis.conf ##启动
    [root@momo1 redis]# redis-cli
    127.0.0.1:6379> keys * ##数据还在,万幸
    1) "d"
    2) "b"
    3) "a"

config命令

  • 1、使用config set可以动态设置参数信息,服务器重启之后就失效了。
    config set appendonly yes
    config set save "90 1 30 10 60 100"
  • 2、使用config get可以查看所有可以使用config set命令设置的参数
    127.0.0.1:6379> config get * ##这里我省略了很多
     1) "dbfilename" ##rdb存储文件
     2) "dump.rdb"
     9) "logfile" ##日志文件
     10) "" ##可重新配置
     11) "pidfile" ##pid文件
     12) "/var/run/redis.pid"
     13) "maxmemory"
     14) "0"
     15) "maxmemory-samples"
     16) "5"
     17) "timeout"
     18) "0"
     40) "3000"
     41) "lua-time-limit"
     42) "5000"
     43) "slowlog-log-slower-than" 
     44) "10000"
     45) "latency-monitor-threshold"
     46) "0"
     47) "slowlog-max-len"
     48) "128"
     49) "port" ##端口
     50) "6379"
     51) "tcp-backlog"
     52) "511"
     53) "databases" ##支持数据库
     54) "16"
     75) "cluster-node-timeout" ##集群的一些信息
     76) "15000"
     77) "cluster-migration-barrier"
     78) "1"
     79) "cluster-slave-validity-factor"
     80) "10"
     81) "repl-diskless-sync-delay"
     82) "5"
     83) "cluster-require-full-coverage"
     84) "yes"
     85) "no-appendfsync-on-rewrite"
     86) "no"
     87) "slave-serve-stale-data"
     88) "yes"
     89) "slave-read-only"
     90) "yes"
     91) "stop-writes-on-bgsave-error"
     92) "yes"
     93) "daemonize" ##是否开启daemonize
     94) "yes"
     95) "rdbcompression"
     96) "yes"
     97) "rdbchecksum"
     98) "yes"
     99) "activerehashing"
    100) "yes"
    101) "repl-disable-tcp-nodelay"
    102) "no"
    103) "repl-diskless-sync"
    104) "no"
    105) "aof-rewrite-incremental-fsync"
    106) "yes"
    107) "aof-load-truncated"
    108) "yes"
    109) "appendonly" ##
    110) "no"
    111) "dir" ##dir 目录,可修改
    112) "/root"
    117) "save" ##rdb持久化点
    118) "900 1 300 10 60 10000"
    119) "loglevel" ##日志级别
    120) "notice"
    124) "0"
    125) "slaveof"  ##主从
    129) "bind"  ##bind ip
    130) ""
  • 3、 使用config rewrite命令对启动 Redis 服务器时所指定的 redis.conf 文件进行改写(Redis 2.8 及以上版本才可以使用),主要是把使用
    config set动态指定的命令保存到配置文件中。
    config rewrite
  • 注意:

config rewrite命令对 redis.conf 文件的重写是原子性的, 并且是一致的:如果重写出错或重写期间服务器崩溃, 那么重写失败, 原有 redis.conf 文件不会被修改。 如果重写成功, 那么 redis.conf 文件为重写后的新文件

修改持久化、日志路径:

###########1、创建目录存储redis,博主在/data/创建redis目录来存放数据###
mkdir /data/redis 
kill -9 redis进程号或shutdown redis#关掉redis进程

###########2、修改日志文件、dump文件路径###########
logfile "/data/redis/redis.log"
dir /data/redis/

###########3、移动之前dump文件到新目录##########
mv /dump.rdb /data/redis/ #我这里之前dump文件在根目录下

###########4、启动redis、查看数据正常##########
[root@iZ94r8hgrjcZ usr]# service redis start ##启动redis
Starting Redis server...
[root@iZ94r8hgrjcZ redis]# pwd  
/data/redis
[root@iZ94r8hgrjcZ redis]# ll         ##以生成日志文件
total 8
-rw-r--r-- 1 root root   62 Apr 30 11:51 dump.rdb
-rw-r--r-- 1 root root 2206 Apr 30 13:04 redis.log
[root@iZ94r8hgrjcZ redis]# redis-cli  ##数据正常
127.0.0.1:6379> keys *
//......

////////##########如果还想测试aof#############
127.0.0.1:6379> config set appendonly yes ##1、动态修改持久化
OK

[root@iZ94r8hgrjcZ redis]# vim /etc/redis/6379.conf ##2、修改配置appendonly yes
[root@iZ94r8hgrjcZ redis]# ll   ##3、查看数据正常
total 12
-rw-r--r-- 1 root root  132 Apr 30 13:20 appendonly.aof
-rw-r--r-- 1 root root   62 Apr 30 11:51 dump.rdb
-rw-r--r-- 1 root root 2937 Apr 30 13:20 redis.log
参考:
http://redisbook.readthedocs.io/en/latest/internal/aof.html

https://lanjingling.github.io/2015/11/16/redis-chijiuhua/