redis持久化(RDB、AOF、混合持久化)

1. RDB快照(snapshot)

在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb的二进制文件中。

你可以对 Redis 进行设置, 让它在“N 秒内数据集至少有 M 个改动”这一条件被满足时,

自动保存一次数据集。

比如说, 以下设置会让 Redis 在满足“60 秒内有至少有 1000 个键被改动”这一条件时,

自动保存一次数据集:

save 60 1000

优点:

RDB 是一个非常紧凑(compact)的文件,体积小,因此在传输速度上比较快,因此适合灾难恢复。

RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快得多。

缺点:

RDB是一个快照过程,无法完整的保存所有数据,尤其在数据量比较大时候,一旦出现故障丢失的数据将更多。

RDB文件是特定的格式,阅读性差,由于格式固定,可能存在不兼容情况。

~~~

bgsave

~~~

bgsave执行原理:

针对save命令进行优化,Redis中所有涉及RDB操作都采用bgsava方式 

优势

1.采用子线程创建RDB文件(),不会对redis服务器性能造成大的影响( 性能最大化);

2.快照生成的RDB文件是一种压缩的二进制文件,可以方便的在网络中传输和保存。通过RDB文件可以方便的将redis数据恢复到某一历史时刻,可以提高数据安全性,避免宕机等意外对数据的影响。

3.适合大规模的数据恢复, RDB的启动恢复效率高。

4.如果业务对数据完整性和一致性要求不高,RDB是很好的选择。 

劣势

1.在redis文件在时间点A生成,之后产生了新数据,还未到达另一次生成RDB文件的条件,redis服务器崩溃了,那么在时间点A之后的数据会丢失掉,数据一致性不是完美的好,如果可以接受这部分丢失的数据,可以用生成RDB的方式;

2.快照持久化方法通过调用fork()方法创建子线程。当redis内存的数据量比较大时,创建子线程和生成RDB文件会占用大量的系统资源和处理时间,对 redis处理正常的客户端请求造成较大影响。

3.数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。

4.备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。所以 Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。

Q: 通过RDB文件恢复数据?

答: 将dump.rdb 文件拷贝到redis的安装目录的bin目录下,重启redis服务即可。在实际开发中,一般会考虑到物理机硬盘损坏情况,选择备份dump.rdb 。 作者:WeiyiGeek https://www.bilibili.com/read/cv13235983 出处:bilibili

RDB文件恢复数据流程 

 1、先备份一份 dump.rdb 为 dump_bak.rdb(模拟线上)

 2、flushall 清空数据(模拟数据丢失,需要注意 flushall 也会触发rbd持久化) 

3、将 dump_bak.rdb 替换为 dump.rdb 

4、重启redis服务,恢复数据 

2. AOF(append-only file)

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件

AOF文件生成机制

答: 生成过程包括三个步骤,即。

redis 打开AOF持久化功能之后,redis在执行完一个写命令后,把执行的命令首先追加到redis内部的aof_buf缓冲区膜末尾,此时缓冲区的记录还没有写到Appendonly.aof文件中。然后,缓冲区的写命令会被写入到 AOF 文件,这一过程是文件写入过程。对于操作系统来说,调用write函数并不会立刻将数据写入到硬盘,为了将数据真正写入硬盘,还需要调用fsync函数,调用fsync函数即是文件同步的过程,只有经过了文件的同步过程,写命令才真正的被保存到了AOF文件中。选项 Appendfsync 就是配置同步的频率的。 

你可以通过修改配置文件来打开 AOF 功能:

appendonly yes

从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。

这样的话, 当 Redis 重新启动时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

你可以配置 Redis 多久才将数据 fsync 到磁盘一次。

有三个选项:

appendfsync always。每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。

appendfsync everysec。每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。

appendfsync no。从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

优点:

数据更完整,秒级数据丢失(取决于设置fsync策略)。、

兼容性较高,由于是基于redis通讯协议而形成的命令追加方式,无论何种版本的redis都兼容。

aof文件是明文的,可阅读性较好。

缺点:

数据文件体积较大,即使有重写机制,但是在相同的数据集情况下,AOF文件通常比RDB文件大。

相对RDB方式,AOF速度慢于RDB,并且在数据量大时候,恢复速度AOF速度也是慢于RDB。

由于频繁地将命令同步到文件中,AOF持久化对性能的影响相对RDB较大。

AOF文件重写

1、redis不断的将写命令保存到AOF文件中,导致AOF文件越来越大,当AOF文件体积过大时,数据恢复的时间也是非常长的,因此,redis提供了重写或者说压缩AOF文件的功能。

比如,AOF重写功能就是干这个事情的。重写时,可以调用BGREWRITEAOF命令重写AOF文件,与新建子线程bgsave命令的工作原理相似。也可以通过配置文件配置什么条件下对AOF文件重写。

2、重写的原理:Redis 会fork出一条新进程,读取内存中的数据,并重新写到一个临时文件中。并没有读取旧文件(太大了)。最后替换旧的aof文件

3、重写触发机制:当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发,这里的“一倍”和“64M” 可以通过配置文件修改

aof 文件记录的是每一条redis命令,有时候我们会对某一个key进行多次set,中间会产生很多条命令,但是结果只有一个。

优势

1.该机制可以带来更高的数据安全性,即数据持久化; 常规三种同步策略即每秒同步()、每修改同步()和不同步;

2.由于该机制对日志文件的写入操作采用的是Append模式,即使过程中出现宕机也不会破坏日志文件中已经存在的内容,如果数据不完整在Redis下次启动之前, 通过redis-check-aof解决数据一致性问题;

3.如果日志文件体积过大可以启动rewrite机制,即redis以Append模式不断的将修改数据写到老的磁盘文件中,同时创建新文件记录期间有哪些修改命令执行,此项极大的保证数据的安全性;

4.AOF文件可读性强,其包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作()

5.数据的完整性和一致性更高

劣势

1.AOF文件比RDB文件较大, 对于相同数量的数据集而言;

2.redis负载较高时,RDB文件比AOF文件具有更好的性能;

3.RDB使用快照的方式持久化整个redis数据,而aof只是追加写命令,因此从理论上来说,RDB比AOF方式更加健壮,另外,官方文档也指出,在某些情况下,AOF的确也存在一些bug,比如使用阻塞命令时,这些bug的场景RDB是不存在的。

4.因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。

5.根据同步策略的不同,AOF在运行效率上往往会慢于RDB,总的来说每秒同步策略的效率还是比较高的 

set name 1

...

set name 12

set name 123

...

set name 1234

set name 12345

例如我们执行了上述命令,aof 文件会记录着每一条命令。在redis重启时,会逐条执行上述的命令。但是其实可以精简为set name 12345,其余的几条命令其实没有意义。AOF重写就是实现了这个功能。

相关配置:

auto-aof-rewrite-percentage 100  # 指当前aof文件比上次重写的增长比例大小,达到这个大小就进行 aof 重写

auto-aof-rewrite-min-size 64mb  # 最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了

以上配置的意思是:

在 aof 文件小于64mb的时候不进行重写,当到达64mb的时候,就重写一次。重写后的 aof 文件可能是10mb。上面配置了auto-aof-rewrite-percentage 100,即 aof 文件到了20mb的时候,又开始重写一次。以此类推。

AOF 是在后台自动重写(redis会fork一个子进程来进行备份,保证主进程不会阻塞),也可以人为执行命令 bgrewriteaof 重写 AOF。

使用子进程来进行AOF重写时会遇到的问题

问题:

子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。

解决方案:

要知道redis是怎么处理这个问题的,需要先了解下AOF重写的具体实现:

AOF文件重写过程与RDB快照bgsave工作过程有点相似,都是通过fork子进程,由子进程完成相应的操作,同样的在fork子进程简短的时间内,redis是阻塞的。

(1)开始bgrewriteaof,判断当前有没有bgsave命令(RDB持久化)/bgrewriteaof在执行,倘若有,则这些命令执行完成以后在执行。

(2)主进程fork出子进程,在这一个短暂的时间内,redis是阻塞的。

(3)主进程fork完子进程继续接受客户端请求。此时,客户端的写请求不仅仅写入aof_buf缓冲区,还写入aof_rewrite_buf重写缓冲区。一方面是写入aof_buf缓冲区并根据appendfsync策略同步到磁盘,保证原有AOF文件完整和正确。另一方面写入aof_rewrite_buf重写缓冲区,保存fork之后的客户端的写请求,防止新AOF文件生成期间丢失这部分数据。

(4.1)子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。

(4.2)主进程把aof_rewrite_buf中的数据写入到新的AOF文件。

(5.)使用新的AOF文件覆盖旧的AOF文件,标志AOF重写完成。

手动执行重写

AOF写和重写流程:

Q: 如何触发AOF快照?

答: 根据配置文件触发,可以是每次执行触发,可以是每秒触发,可以不同步。

Q: 如何根据AOF文件恢复数据?

答: 正常情况下,将Appendonly.aof 文件拷贝到redis的安装目录的bin目录下,重启redis服务即可。但在实际开发中,可能因为某些原因导致  文件格式异常,从而导致数据还原失败,可以通过命令进行修复 。 

配置说明: 

~~~

cat > redis.conf <<'EOF'

# 持久化数据存储

dir "/data"

# 是否开启AOF默认为否

appendonly yes

# AOF文件名字及路径,若RDB路径已设置这里可不设置

appendfilename "appendonly.aof"

# AOF的3种模式,no(使用系统缓存处理,快)、always(记录全部操作,慢但比较安全)、everysec(每秒同步,折中方案,默认使用)

appendfsync everysec

# 重写期间是否同步数据,默认为no

no-appendfsync-on-rewrite no

# 配置重写触发机制: 确保AOF日志文件不会过大,保持跟redis内存数据量一致。

# 配置说明:当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发(根据实际环境进行配置)

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 256mb

# AOF重写策略是否启用,默认为yes

aof-rewrite-incremental-fsync yes

# 加载AOF时如果报错则会继续但写入log,如果为no则不会继续

aof-load-truncated yes

# Redis5.0有的功能AOF重写及恢复可以使用RDB文件及AOF文件,速度更快,默认yes

aof-use-rdb-preamble yes

EOF

~~~

Q: 如何通过AOF文件恢复数据流程? 

1、执行flushall,模拟数据丢失

2、重启 redis 服务,恢复数据

3、修改 appendonly.aof,模拟文件异常

4、重启 Redis 服务失败,这同时也说明了RDB和AOF可以同时存在,且优先加载AOF文件。

5、使用 redis-check-aof 校验 appendonly.aof 文件。

#  针对Redis aof 持久化文件进行完整性检测并进行修复

/usr/local/redis/bin/redis-check-aof --fix appendonly.aof

  # The AOF appears to start with an RDB preamble.

  # Checking the RDB preamble to start:

  # [offset 0] Checking RDB file appendonly.aof

  # [offset 27] AUX FIELD redis-ver = '5.0.10'

  # [offset 41] AUX FIELD redis-bits = '64'

  # [offset 53] AUX FIELD ctime = '1631088747'

  # [offset 68] AUX FIELD used-mem = '31554944'

  # [offset 84] AUX FIELD aof-preamble = '1'

  # [offset 86] Selecting DB ID 0

  # [offset 13350761] Checksum OK

  # [offset 13350761] \o/ RDB looks OK! \o/

  # [info] 157070 keys read

  # [info] 0 expires

  # [info] 0 already expired

  # RDB preamble is OK, proceeding with AOF tail...

  # 0x        27b66b0: Expected prefix '*', got: 'R'

  # AOF analyzed: size=116993914, ok_up_to=41641648, ok_up_to_line=1816854, diff=75352266

  # AOF is not valid. Use the option to try fixing it.

6、重启Redis 服务后正常。

# 利用源实例生成的aof文件数据进行恢复到其它主机中。

redis-cli -h 17.20.0.2 -a password --pipe < applendonly.aof

注意:当你使用 flushall 清空数据的时候,重启redis服务发现数据没恢复,是因为 FLUSHALL 命令也被写入AOF文件中,会导致数据恢复失败,所只需要删除aof文件中的flushall就行了。

在数据库恢复时把 aof(Append only file) 从中对redis数据库操作的命令,增删改操作的命令,执行了一遍即可。

实际案例:

描述: 用于异步执行一个  文件重写操作, 重写会创建一个当前 AOF 文件的体积优化版本,因为AOF为记录每次的操作会导致实际记录冗杂、使得文件过大,所以需要做重写操作。

重写方式分为以下两种:

# (1) AOF自动重写:按配置文件条件自动触发重写

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 256mb

# (2) AOF手动重写:使用 redis-cli 连接到 server 端执行 bgrewriteaof 进行手动重写。

# 注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

127.0.0.1:6379> BGREWRITEAOF

# 即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

Background append only file rewriting started 

合并两个不同实例的数据 

描述: 我们可以利用如下方式进行集群多个主节点持久化数据的合并。

(1) AOF 备份合并: 我们说过它实际上是一些列Redis的命令文本。

例如,假设有两台 Redis(6379, 6479),它们的AOF文件名分别为(6379.aof, 6479.aof),现在要将6379的数据合并到 6479.aof 

# 首先

cp 6379.aof 6379.aof.bak, cp 6479.aof 6479.aof.bak

# 合并

cat 6379.aof 6479.aof > new.aof

# 检查&修复

/usr/local/redis/bin/redis-check-aof --fix appendonly.aof

(2) RDB 备份合并: 注意以下方法可能由于服务端版本不同而有些许差异。

RDB格式如下:头5个字节是字符REDIS,之后4个字节代表版本号,阿里的版本分别是 00 00 00 06,之后2个字节 FE 00,FE是标识 00是数据库,还好我们只有一个库, 最后的结尾9个字节 , FF 加上8个字节的CRC64校验码(实在没空弄,后来偷了一个懒)

# 1.线上服务使用的阿里云的集群版本redis服务,数据量1千万,rdb文件4GB,8个rdb文件,每个500MB。

#文件1 大小566346503,截取尾部的9个字节

dd bs=1 if=src_1.rdb of=1.rdb count=566346494

#文件2 大小570214520,跳过头部的11个字节,再截取尾部的9个字节

dd bs=1 if=src_2.rdb of=2.rdb skip=11 count=570214500

...

#文件8 大小569253061,跳过头部的11个字节,再截取尾部的8个字节,保留FF。

dd bs=1 if=src_8.rdb of=8.rdb skip=11 count=569253042

# 2.合并文件(得到备份文件dump.rdb)

cat 1.rdb > dump.rdb

cat 2.rdb >> dump.rdb

...

cat 8.rdb >> dump.rdb

# 3.检查备份文件(应该会提示没有crc校验)

redis-check-rdb dump.rdb

# 4.修改配置文件,因为数据库备份文件里面不包含crc64的校验码,配置文件中关闭选项。

rdbchecksum no 

Tips : 数据恢复到此结束,此方法只适合用于临时恢复和导出数据,数据完整性不敢保证。

参考地址: https://github.com/sripathikrishnan/redis-rdb-tools/wiki/Redis-RDB-Dump-File-Format

其它工具:

https://github.com/leonchen83/redis-rdb-cli/ | 一个可以解析, 过滤, 分割, 合并 rdb 离线内存分析的工具. 也可以在两个redis之前同步数据并允许用户自定义同步服务来把redis数据同步到其他地方. 

3.混合持久化(redis4.0之后才支持)

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。

如果使用 AOF 日志重放,性能则相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动的时候需要花费很长的时间。

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。

混合持久化同样也是通过bgrewriteaof完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将aof_rewrite_buf重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据,如下图:

在redis重启的时候,加载 aof 文件进行恢复数据:先加载 rdb 内容再加载剩余的 aof。

混合持久化配置:

aof-use-rdb-preamble yes  # yes:开启,no:关闭

RDB和AOF,应该用哪一个?

如果你可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。如果只用AOF持久化,数据量很大时,在redis启动的时候需要花费大量的时间。

如果你非常关心你的数据,建议使用 redis 4.0 以后的混合持久化特性。

混合模式配置项

save " "

dbfilename "dump.rdb"

appendonly "yes"

appendfilename "appendonly.aof"

AOF重写

aof文件里可能有太多“琐碎”指令,所以aof会定期根据内存的最新数据重新生成aof文件

有两个配置可以控制aof自动重写的频率:

auto-aof-rewrite-min-size  64mb

#aof文件至少要达到64m才会触发制动重写,文件太小恢复速度本来就很快,重写的意义不大

auto-aof-rewrite-percentage  100

#aof文件上一次重写后文件大小增长了100%则再次触发重写

appendfsync   "everysec"

aof-use-rdb-preamble "yes"

参考:https://www.bilibili.com/read/cv13235983 


相关资源:

redis哨兵配置文件 - Dcsdn 

Redis数据的导出和导入 - Dcsdn 

GitOps 初探 - Dcsdn

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RDBRedis Database)和AOF(Append-Only File)是Redis中两种常见的持久化方式,它们有以下区别: 1. RDB持久化RDB是将Redis数据库在某个时间点的数据快照保存到硬盘上的一种方式。它通过fork一个子进程来完成持久化操作,首先将数据写入一个临时文件,然后用这个临时文件替换上一个RDB文件,从而实现数据的持久化RDB方式适合用于备份、灾难恢复和数据库迁移等场景。 2. AOF持久化AOF是通过将Redis的写命令追加到文件的末尾来记录数据库的操作。Redis重启时,通过重新执行AOF文件中的命令来恢复数据库状态。相比于RDB方式,AOF可以提供更高的数据安全性,因为它记录了每个写操作的历史,可以保证在Redis异常退出或宕机时不会丢失数据。AOF方式适合用于数据持久化和实时备份等场景。 3. RDB的优点:RDB方式对于数据恢复速度较快,在大规模数据恢复时比AOF更高效。由于RDB是一个紧凑的二进制文件,相对于AOF文件来说更小,可以节省存储空间。此外,RDB方式对Redis的性能影响较小。 4. AOF的优点:AOF方式可以提供更高的数据安全性,因为它记录了每个写操作的历史,可以保证在Redis异常退出或宕机时不会丢失数据。AOF文件是一个文本文件,易于理解和修改。 总结来说,RDB方式适合于备份和灾难恢复,而AOF方式适合于数据持久化和实时备份。在选择持久化方式时,需要根据实际需求进行权衡和选择。另外,也可以同时使用RDBAOF两种方式,以提供更好的数据安全性和灾难恢复能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值