天天看点

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

2 RDB(Redis database)- 全量写入

Redis Server在有多db 中存储的K.V可理解为Redis的一个状态。当发生写操作时,Redis就会从一个状态切换到另外一个状态。

基于全量的持久化就是在某个时刻,将Redis的所有数据持久化到硬盘中,形成一个快照。快照,顾名思义可以理解为拍照一样,把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可,不像 AOF,一条条的执行操作命令。

当Redis 重启时,通过加载最近一个快照数据,可以将 Redis 恢复至最近一次持久化状态上。

快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。

2.1 触发方式

save

  • 客户端显示触发
  • 或客户端发送 shutdown 命令,系统会先执行 save 命令阻塞客户端,然后关闭服务器

save本身是

单线程串行

方式执行,因此当数据量大时,可能会发生Redis Server的长时间卡顿。

其备份期间其他命令全部阻塞,无法执行,因此备份时期

数据的状态始终一致

若存在老的RDB文件,则新的会替换老的,时间复杂度O(N)。

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

设置 redis.conf

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

再使用脚本初始化 500w 数据,等待后发现已经落盘:

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

bgsave

bgsave 可由

  • 客户端显式触发
  • 配置定时任务触发
  • 当有主从架构时,从服务器向主服务器发送 sync 命令来执行复制操作时,主服务器会执行 bgsave

bgsave命令在执行时,会fork一个子进程。子进程提交完成后,会立即给客户端返回响应,备份操作在后台异步执行,期间不会影响Redis的正常响应。

对于bgsave来说,当父进程Fork完子进程之后,异步任务会将当前的内存状态作为一个版本进行复制。在复制过程中产生的变更,不会反映在这次备份当中。

不用命令,而使用配置

在Redis的默认配置中,当满足下面任一条件,会自动触发 bgsave 的执行:

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

bgsave相对于save的优势是

异步执行

,不影响后续命令执行。但Fork子进程,涉及父进程的内存复制,会增加服务器内存开销。

当内存开销高到使用虚拟内存时,bgsave的Fork子进程会阻塞运行

,可能会造成秒级不可用。因此使用bgsave需要保证服务器空闲内存足够。

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践
Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

2.2 RDB执行流程

rdb.c文件执行流程:

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

2.3 RDB 最佳配置

关闭自动RDB:

dbfilename dump-${port}.rdb
dir /redisDataPath
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes      

需要注意的触发时机

  • 主从复制时机的全量复制,master节点会执行bgsave
  • debug reload
  • shutdown
  • flushDB 、 flushAll

2.4 RDB性质

  1. RDB是Redis内存到硬盘的快照,用于持久化
  2. save通常会阻塞Redis
  3. bgsave不会阻塞Redis,但会fork新进程
  4. save自动配置满足任一就会被执行

2.5 RDB 优点

  • 紧凑压缩的二进制文件

    RDB会生成多个数据文件,每个文件都代表了某时刻Redis中的所有数据,这种方式非常适合做冷备。可将这种完整数据文件发送到云服务器存储,比如ODPS分布式存储,以预定好的备份策略来定期备份Redis中的数据

  • fork子进程性能最大化

    RDB对Redis对外提供的读写服务,影响非常小,可让Redis保持高性能,因为Redis主进程只要fork一个子进程,让子进程执行RDB

  • 启动效率高

    相对于AOF,直接基于RDB文件重启和恢复Redis进程,更加快速

2.6 RDB缺点

耗时

O(n)

写时复制(copy-on-write)

耗内存,copy-on-write策略。RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。

执行 fork 时,os会使用写时复制,即 fork 函数发生的一刻父子进程共享同一内存数据。当父进程要更改其中某片数据时(如执行一个写命令),os会将该片数据复制一份以保证子进程数据不受影响,所以新的 RDB 文件存储的是执行 fork 一刻的内存数据。

不可控

容易丢失数据。一般RDB每隔5分钟,或者更长时间生成一次,若过程中Redis宕机,就会丢失最近未持久化的数据

2.7 恢复流程

当Redis重新启动时,会从本地磁盘加载之前持久化的文件。当恢复完成之后,再受理后续的请求操作。

4 选型及最佳实践

Redis的持久化机制(下)2 RDB(Redis database)- 全量写入4 选型及最佳实践

混合持久化

Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,通过配置项

aof-use-rdb-preamble

开启)。

如果把混合持久化打开,AOF 重写时就直接把 RDB 内容写到 AOF 文件开头:

  • 好在可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多数据
  • 但是,AOF 里的 RDB 部分就是压缩格式不再是 AOF 格式,可读性较差

RDB最佳策略

  • 关闭
  • 集中手动管理RDB操作
  • 在从节点打开自动执行配置,但是不宜频繁执行RDB

AOF最佳策略

  • 建议打开,但是如果只是纯作为缓存使用可不开
  • AOF重写集中管理
  • everysec

抉择RDB & AOF

不要仅使用RDB,因为那样会导致丢失很多数据

也不要仅使用AOF,因为那样有两个问题

你通过AOF做冷备,没有RDB做冷备,来的恢复速度更快

RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug

综合使用AOF和RDB

用AOF保证数据不丢失,作为数据恢复的第一选择

用RDB做不同程度的冷备,在AOF文件都丢失或损坏不可用时,还可使用RDB快速实现数据恢复

一些最佳实践

  • 小分片

    例如设置maxmemory参数设置每个redis只存储4个G的空间,这样各种操作都不会太慢

  • 监控(硬盘、内存、负载、网络)
  • 足够的内存

参考

继续阅读