Redis持久化方式

1、RDB

  RDB全称Redis DataBase,在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时直接将快照文件直接读到内存里;在默认情况下,Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中,有手动触发和自动触发两种方式。

  手动触发:save 和 bgsave 两命令

  save命令:阻塞当前 Redis,直到 RDB 持久化过程完成为止,若内存实例比较大 会造成长时间阻塞,线上环境不建议用它

  bgsave命令:redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的时间。redis 进程执行 fork 操作创建子线程,由子线程完成持久化,阻塞时间很短(微秒级),是 save 的优化,在执行 redis-cli shutdown 关闭 redis 服务时,如果没有开启 AOF 持久化,自动执行 bgsave;

    bgsave的写时复制(COW)机制

    Redis 借助操作系统提供的写时复制技术(Copy-On-Write, COW),在生成快照的同时,依然可以正常处理写命令。简单来说,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。此时,如果主线程对这些数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

  自动触发:通过配置文件对 Redis 进行设置, 让它在“N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动进行数据集保存操作。

  RDB相关配置:

# RDB自动持久化规则
# 当 900 秒内有至少有 1 个键被改动时,自动进行数据集保存操作
save 900 1
# 当 300 秒内有至少有 10 个键被改动时,自动进行数据集保存操作
save 300 10
# 当 60 秒内有至少有 10000 个键被改动时,自动进行数据集保存操作
save 60 10000

# RDB持久化文件名
dbfilename dump.rdb

# 数据持久化文件存储目录
dir /var/lib/redis

# bgsave发生错误时是否停止写入,通常为yes
stop-writes-on-bgsave-error yes

# 对于储存到磁盘的快照,是否启用LZF算法进行压缩存储,默认是yes,但会消耗一定CPU。
rdbcompression yes

# 在存储快照后,是否让redis使用CRC64算法来进行数据校验,通常为yes
rdbchecksum yes

 优点:

  1. 整个Redis数据库将只包含一个文件 dump.rdb,方便持久化

  2. 压缩后的二进制文,方便备份、全量复制,灾性好

  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化,使用单独的子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能

  4. 相对于数据集大时,比AOF的启动效率更高

缺点:

  1. 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化时redis 发生故障,会发生数据丢失,所以这种更适用于数据要求不严谨的场景

  2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟

  3. 保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题

2、AOF

  AOF全称Append Only File(文件追加方式),将修改的每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间fsync到磁盘)

  比如执行命令 set name james,aof文件里会记录如下数据Redis持久化方式

  这是一种resp协议格式数据,星号后面的数字代表命令有多少个参数,$号后面的数字代表这个参数有几个字符注意,如果执行带过期时间的set命令,aof文件里记录的是并不是执行的原始命令,而是记录key过期的时间戳

  比如执行 set age 20 ex 1000,对应aof文件里记录如下Redis持久化方式

AOF相关配置 

appendonly yes         // 启用aof持久化方式

# appendfsync always   // 每收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

appendfsync everysec   // 每秒强制写入磁盘一次,性能和持久化方面做了折中,只会丢失一秒钟的数据,推荐
    
# appendfsync no       // 从不进行写入,更不安全的选择

AOF重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件,例如执行如下几条命令:Redis持久化方式

  此时,AOF文件里的内容为: Redis持久化方式

 重写AOF后:

Redis持久化方式

 如下两个配置可以控制AOF自动重写频率

auto-aof-rewrite-percentage 100  // aof文件大小比起上次重写时的大小,增长率100%时,重写

auto-aof-rewrite-min-size 64mb   // aof文件,至少超过64M时,重写

当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF

注意,AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多影响

AOF重写原理:

  AOF重写并不是对原有AOF文件进行任何写入和读取,它针对的是数据库中键的当前值。将当前数据库中的数据转换成一系列的redis的操作指令,存储到一个新的aof日志文件中,完毕后再将操作期间发生的增量aof日志追加到这个新的aof日志文件中,追加完毕后就立即替换旧的aof。在重写的过程中,由于redis还会有新的写入,为了避免数据丢失,会开辟一块内存用于存放重写期间产生的写入操作,等到重写完毕后会将这块内存中的操作再追加到aof文件中。如果在重写过程中redis的写入很频繁或写入量很大,就会导致占用大量额外的内存来缓存写操作,导致内存爆涨

优点:

  1. 数据安全,Redis中提供了3种同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失,而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中

  2. 通过append模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过redis-check-aof工具解决数据一致性问题

  3. AOF机制的rewrite模式。定期对AOF文件进行重写,以达到压缩的目的

缺点:

  1. AOF 文件比 RDB 文件大,且恢复速度慢

  2. 数据集大的时候,比rdb 启动效率低

  3. 运行效率没有RDB高

AOF文件比RDB更新频率高,优先使用AOF还原数据。

3、混合持久化

  重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。集成了 RDB 和 AOF 的优点

  通过如下配置可以开启混合持久化(必须先开启aof):

aof‐use‐rdb‐preamble yes  // 开启混合持久化,必须先开启AOF

  如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。

  混合持久化AOF文件结构如下:

Redis持久化方式Redis持久化方式

 

 

 Redis数据备份策略:

  1. 写crontab定时调度脚本,每小时都copy一份rdb或aof的备份到一个目录中去,仅仅保留最近48小时的备份
  2. 每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份
  3. 每次copy备份的时候,都把太旧的备份给删了
  4. 每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏

 

上一篇:redis中间件


下一篇:Java学习(多表查询(内连接查询,外连接查询,子查询),事务(基本介绍,四大特征,隔离级别),DCL(管理用户,权限管理))