关于java:一文深度剖析Redis6的持久化机制简洁易懂

31次阅读

共计 5112 个字符,预计需要花费 13 分钟才能阅读完成。

Redis 的强劲性能很大水平上是因为它所有的数据都存储在内存中,当然如果 redis 重启或者服务器故障导致 redis 重启,所有存储在内存中的数据就会失落。然而在某些状况下,咱们心愿 Redis 在重启后可能保证数据不会失落。

  1. 将 redis 作为 nosql 数据库应用。
  2. 将 Redis 作为高效缓存服务器,缓存被击穿后对后端数据库层面的刹时压力是特地大的,所有缓存同时生效可能会导致雪崩。

这时咱们心愿 Redis 能将数据从内存中以某种模式同步到硬盘上,使得重启后能够依据硬盘中的记录来复原数据。

Redis 反对两种形式的长久化,一种是 RDB 形式、另一种是 AOF(append-only-file)形式,两种长久化形式能够独自应用其中一种,也能够将这两种形式联合应用。

  • RDB:依据指定的规定“定时”将内存中的数据存储在硬盘上,
  • AOF:每次执行命令后将命令自身记录下来。

RDB 模式

RDB 的长久化形式是通过快照(snapshotting)实现的,它是 Redis 默认的长久化形式,配置如下。

# save 3600 1
# save 300 100
# save 60 10000

Redis 容许用户自定义快照条件,当合乎快照条件时,Redis 会主动执行快照操作。快照的条件能够由用户在配置文件中配置。配置格局如下

save <seconds> <changes>

第一个参数是工夫窗口,第二个是键的个数,也就是说,在第一个工夫参数配置范畴内被更改的键的个数大于前面的 changes 时,即合乎快照条件。当触发条件时,Redis 会主动将内存中的数据生成一份正本并存储在磁盘上,

这个过程称之为“快照”,除了上述规定之外,还有以下几种形式生成快照。

  1. 依据配置规定进行主动快照
  2. 用户执行 SAVE 或者 GBSAVE 命令
  3. 执行 FLUSHALL 命令
  4. 执行复制 (replication) 时

依据配置规定进行主动快照

  • 批改 redis.conf 文件,示意 5 秒内,有一个 key 发生变化,就会生成 rdb 文件。
  save 5 1                # 示意 3600s 以内至多产生 1 个 key 变动(新增、批改、删除),则重写 rdb 文件
  save 300 100
  save 60 10000
  • 批改文件存储门路

    dir /data/program/redis/bin
  • 其余参数配置阐明

    参数 阐明
    dir rdb 文件默认在启动目录下(相对路径)config get dir 获取
    dbfilename 文件名称
    rdbcompression 开启压缩能够节俭存储空间,然而会耗费一些 CPU 的计算工夫,默认开启
    rdbchecksum 应用 CRC64 算法来进行数据校验,然而这样做会减少大概 10% 的性能耗费,如果心愿获取到最大的性能晋升,能够敞开此性能。

如果须要敞开 RDB 的长久化机制,能够参考如下配置,开启save,并正文其余规定即可

save ""
#save 900 1
#save 300 10
#save 60 10000

用户执行 SAVE 或者 GBSAVE 命令

除了让 Redis 主动进行快照以外,当咱们对服务进行重启或者服务器迁徙咱们须要人工去干涉备份。redis 提供了两条命令来实现这个工作

  1. save 命令

    如图 4 -24 所示,当执行 save 命令时,Redis 同步做快照操作,在快照执行过程中会阻塞所有来自客户端的申请。当 redis 内存中的数据较多时,通过该命令将导致 Redis 较长时间的不响应。所以不倡议在生产环境上应用这个命令,而是举荐应用 bgsave 命令

图 4 -24

  1. bgsave 命令

    如图 4 -25 所示,bgsave 命令能够在后盾异步地进行快照操作,快照的同时服务器还能够持续响应来自客户端的申请。执行 BGSAVE 后,Redis 会立刻返回 ok 示意开始执行快照操作,在 redis-cli 终端,通过上面这个命令能够获取最近一次胜利执行快照的工夫(以 UNIX 工夫戳格局示意)。

    LASTSAVE

1:redis 应用 fork 函数复制一份以后过程的正本(子过程)

2:父过程持续接管并解决客户端发来的命令,而子过程开始将内存中的数据写入硬盘中的临时文件

3:当子过程写入完所有数据后会用该临时文件替换旧的 RDB 文件,至此,一次快照操作实现。

留神:redis 在进行快照的过程中不会批改 RDB 文件,只有快照完结后才会将旧的文件替换成新的,也就是说任何时候 RDB 文件都是残缺的。这就使得咱们能够通过定时备份 RDB 文件来实现 redis 数据库的备份,RDB 文件是通过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输。

bgsave 是异步执行快照的,bgsave 写入的数据就是 for 过程时 redis 的数据状态,一旦实现 fork,后续执行的新的客户端命令对数据产生的变更都不会反馈到本次快照

Redis 启动后会读取 RDB 快照文件,并将数据从硬盘载入到内存。依据数据量大小以及服务器性能不同,这个载入的工夫也不同。

图 4 -25

执行 FLUSHALL 命令

该命令在后面讲过,会革除 redis 在内存中的所有数据。执行该命令后,只有 redis 中配置的快照规定不为空,

也就是 save 的规定存在。redis 就会执行一次快照操作。不论规定是什么样的都会执行。如果没有定义快照规定,就不会执行快照操作。

执行复制 (replication) 时

该操作次要是在主从模式下,redis 会在复制初始化时进行主动快照。这个会在前面讲到;

这里只须要理解当执行复制操作时,即时没有定义主动快照规定,并且没有手动执行过快照操作,它依然会生成 RDB 快照文件。

RDB 数据恢复演示

  • 筹备初始数据
  redis> set k1 1
  redis> set k2 2
  redis> set k3 3
  redis> set k4 4
  redis> set k5 5
  • 通过 shutdown 命令敞开触发 save

    redis> shutdown
  • 备份 dump.rdb 文件(用来后续复原)

    cp dump.rdb dump.rdb.bak
  • 接着再启动 redis-server(systemctl restart redis_6379),通过 keys 命令查看,发现数据还在

    keys *

模仿数据失落

  • 执行 flushall

    redis> flushall
  • shutdown(从新生成没有数据的快照,用来模仿后续的数据恢复)

    redis> shutdown
  • 再次启动 redis, 通过 keys 命令查看,此时 rdb 中没有任何数据。
  • 复原之前备份的 rdb 文件(之前保留了数据的 rdb 快照)

    mv dump.rdb.bak dump.rdb
  • 再次重启 redis,能够看到之前快照保留的数据

    keys *

文件的劣势和劣势

一、劣势

1.RDB 是一个十分紧凑 (compact) 的文件,它保留了 redis 在某个工夫点上的数据集,这种文件非常适合用于进行备份和劫难复原。

2. 生成 RDB 文件的时候,redis 主过程会 fork()一个子过程来解决所有保留工作,主过程不须要进行任何磁盘 IO 操作。

3.RDB 在复原大数据集时的速度比 AOF 的复原速度要快。

二、劣势

  • 1、RDB 形式数据没方法做到实时长久化 / 秒级长久化。因为 bgsave 每次运行都要执行 fork 操作创立子过程,频繁执行老本过高
  • 2、在肯定间隔时间做一次备份,所以如果 redis 意外 down 掉的话,就会失落最初一次快照之后的所有批改(数据有失落)。

如果数据相对来说比拟重要,心愿将损失降到最小,则能够应用 AOF 形式进行长久化。

AOF 模式

AOF(Append Only File):Redis 默认不开启。AOF 采纳日志的模式来记录每个写操作,并 追加 到文件中。开启后,执行更改 Redis 数据的命令时,就会把命令写入到 AOF 文件中。

Redis 重启时会依据日志文件的内容把写指令从前到后执行一次以实现数据的复原工作。

AOF 配置开关

# 开关
appendonly no  /yes
# 文件名
appendfilename "appendonly.aof"

通过批改 redis.conf 重启 redis 之后:systemctl restart redis_6379。

再次运行 redis 的相干操作命令,会发现在指定的 dir 目录下生成 appendonly.aof 文件,通过 vim 查看该文件内容如下

*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$3
mic
*3
$3
set
$4
name
$3
123

AOF 配置相干问题解答

问题 1:数据都是实时长久化到磁盘吗?

尽管每次执行更改 Redis 数据库内容的操作时,AOF 都会将命令记录在 AOF 文件中,然而事实上,因为操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了零碎的硬盘缓存。在默认状况下零碎每 30 秒会执行一次同步操作。以便将硬盘缓存中的内容真正地写入硬盘。

在这 30 秒的过程中如果零碎异样退出则会导致硬盘缓存中的数据失落。一般来说可能启用 AOF 的前提是业务场景不能容忍这样的数据损失,这个时候就须要 Redis 在写入 AOF 文件后被动要求零碎将缓存内容同步到硬盘中。在 redis.conf 中通过如下配置来设置同步机制。

参数 阐明
appendfsync everysec AOF 长久化策略(硬盘缓存到磁盘),默认everysec 1 no 示意不执行 fsync,由操作系统保证数据同步到磁盘,速度最快,然而不太平安;2 always 示意每次写入都执行 fsync,以保证数据同步到磁盘,效率很低;3 everysec 示意每秒执行一次 fsync,可能会导致失落这 1s 数据。通常抉择 everysec,兼顾安全性和效率。

问题 2:文件越来越大,怎么办?

因为 AOF 长久化是 Redis 一直将写命令记录到 AOF 文件中,随着 Redis 一直的运行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 复原要求工夫越长。

例如 set gupao 666,执行 1000 次,后果都是 gupao=666。

为了解决这个问题,Redis 新增了重写机制,当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩,只保留能够复原数据的最小指令集。

能够应用命令上面这个命令被动触发重写

redis> bgrewriteaof

AOF 文件重写并不是对原文件进行重新整理,而是间接读取服务器现有的键值对,而后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。

重写触发机制如下

参数 阐明
auto-aof-rewrite-percentage 默认值为 100。示意的是当目前的 AOF 文件大小超过上一次重写时的 AOF 文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时 AOF 文件大小为根据
auto-aof-rewrite-min-size 默认 64M。示意限度了容许重写的最小 AOF 文件大小,通常在 AOF 文件很小的状况下即便其中有很多冗余的命令咱们也并不太关怀

在启动时,Redis 会一一执行 AOF 文件中的命令来将硬盘中的数据载入到内存中,载入的速度绝对于 RDB 会慢一些

问题:重写过程中,AOF 文件被更改了怎么办?

Redis 能够在 AOF 文件体积变得过大时,主动地在后盾对 AOF 进行重写:重写后的新 AOF 文件蕴含了复原以后数据集所需的最小命令汇合。

重写的流程是这样,

  • 主过程会 fork 一个子过程进去进行 AOF 重写,这个重写过程并不是基于原有的 aof 文件来做的,而是有点相似于快照的形式,全量遍历内存中的数据,而后一一序列到 aof 文件中。
  • 在 fork 子过程这个过程中,服务端依然能够对外提供服务,那这个时候重写的 aof 文件的数据和 redis 内存数据不统一了怎么办?不必放心,这个过程中,主过程的数据更新操作,会缓存到 aof_rewrite_buf 中,也就是独自开拓一块缓存来存储重写期间收到的命令,当子过程重写完当前再把缓存中的数据追加到新的 aof 文件。
  • 当所有的数据全副追加到新的 aof 文件中后,把新的 aof 文件重命名正式的文件名字,尔后所有的操作都会被写入新的 aof 文件。
  • 如果在 rewrite 过程中呈现故障,不会影响原来 aof 文件的失常工作,只有当 rewrite 实现后才会切换文件。因而这个 rewrite 过程是比拟牢靠的。

图 4 -26

Redis 容许同时开启 AOF 和 RDB,既保证了数据安全又使得进行备份等操作非常容易。如果同时开启后,Redis 重启会应用 AOF 文件来复原数据,因为 AOF 形式的长久化可能失落的数据更少。

AOF 的优劣势

长处:

1、AOF 长久化的办法提供了多种的同步频率,即便应用默认的同步频率每秒同步一次,Redis 最多也就失落 1 秒的数据而已。

毛病:

1、对于具备雷同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大(RDB 存的是数据快照)。

2、尽管 AOF 提供了多种同步的频率,默认状况下,每秒同步一次的频率也具备较高的性能。在高并发的状况下,RDB 比 AOF 具好更好的性能保障。

正文完
 0