栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

redis的持久化

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

redis的持久化

redis的持久化 持久化流程
  1. 客户端向服务端发送写操作(数据在客户端的内存中)。
  2. 数据库服务端接收到写请求的数据(数据在服务端的内存中)。
  3. 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
  4. 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
  5. 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。

这5个过程是在理想条件下一个正常的保存流程,但是在大多数情况下,我们的机器等等都会有各种各样的故障,这里划分了两种情况:

  1. Redis数据库发生故障,只要在上面的第三步执行完毕,那么就可以持久化保存,剩下的两步由操作系统替我们完成。
  2. 操作系统发生故障,必须上面5步都完成才可以。

Redis持久化存储有两种持久化方案,RDB(Redis Database)和 AOF(Append-only File)。其中RDB是将内存中的数据进行快照存储到磁盘,AOF则为可回放的命令日志记录redis内的所有操作。它们各有特点也相互独立。Redis4之后支持RDB-AOF混合持久化的方式,结合了两者的优点,可以通过 aof-use-rdb-preamble 配置项可以打开混合开关。

AOF和RDB的恢复顺序

当Redis服务重启时数据恢复的顺序如下:

  1. 判断是否开启AOF持久化,若开启了AOF,则使用AOF持久化文件恢复数据,否则使用RDB持久化文件恢复数据;
  2. 若AOF文件不存在则从RDB文件恢复【其实并没有】;若AOF文件存在则使用AOF文件恢复;
  3. 若AOF文件和RDB文件都不存在则直接启动Redis;
  4. 若AOF或RDB文件出现错误,则启动失败返回错误信息;
1. RDB策略

RDB(Redis Database)是将Redis内存中的数据进行Snaptshot快照存储在磁盘内,是Redis的默认持久化方案。使用RDB持久化默认有三种策略,该持久化策略在redis.conf中可配置,会以一段时间内有指定次数据修改的规则触发快照动作,快照文件名为dump.rdb,该文件默认使用LZF压缩算法 。每当Redis服务重启的时候会从该文件中加载数据进内存。

RDB持久化除了可以根据配置中的策略触发,也可以手动触发,使用save和bgsave命令即可。这两个命令的区别的save会阻塞服务器进程,在进行save的过程中,服务器不能处理任何请求,而bgsave会通过一个子进程在后台处理rdb持久化。事实上save和bgsave调用的都是rdbSave函数,因此Redis不允许save和bgsave同时运行,这也是为了避免出现竞争导致rdb文件数据不准确。

bgsave操作使用CopyOnWrite机制进行写时复制,是由一个子进程将内存中的最新数据遍历写入临时文件,此时父进程仍旧处理客户端的操作,当子进程操作完毕后再将该临时文件重命名为dump.rdb替换掉原来的dump.rdb文件,因此无论bgsave是否成功,dump.rdb都不会受到影响。

  1. 自动触发:

    #RDB持久化策略 默认三种方式,[900秒内有1次修改],[300秒内有10次修改],[60秒内有10000次修改]即触发RDB持久化,我们可以手动修改该参数或新增策略
    save 900 1
    save 300 10
    save 60 10000
     
    #RDB文件名
    dbfilename dump.rdb
    #RDB文件存储路径
    dir ./
    
    #在seconds秒内有changes次数据修改就触发RDB持久化
    save  
    

    另外在主从全量同步、debug reload以及shutdown的情况下也会自动触发RDB数据持久化。

    主要参数配置:

    ①save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave。

    默认如下配置:

    #表示900 秒内如果至少有 1 个 key 的值变化,则保存save 900 1#表示300 秒内如果至少有 10 个 key 的值变化,则保存save 300 10#表示60 秒内如果至少有 10000 个 key 的值变化,则保存save 60 10000

    不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。

    ②stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了

    ③rdbcompression ;默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。

    ④rdbchecksum :默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

    ⑤dbfilename :设置快照的文件名,默认是 dump.rdb

    ⑥dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。

  2. 手动触发之save:
    该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下:

    执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。

  3. 手动触发之bgsave:
    执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:

    具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

  4. save和bgsave比较

  5. RDB 的优势和劣势
    优势:

    1. RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
    2. 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
    3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

    劣势:

    1. 无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
    2. 最后一次备份时,可能还没触发备份就宕机,导致数据丢失
    3. 保存后的二进制文件,不同版本直接存在兼容性问题
2. AOF策略

AOF(Append-only File)记录Redis中每次的写命令,类似mysql中的binlog,服务重启时会重新执行AOF中的命令将数据恢复到内存中,RDB(按策略持久化)持久化方式记录的粒度不如AOF(记录每条写命令),因此很多生产环境都是开启AOF持久化。

AOF中记录了操作和数据,在日志文件中追加完成后才会将内存中的数据进行变更。

AOF持久化流程:

  1. 客户端的请求写命令会被append追加到AOF缓冲区内;
  2. AOF缓冲区根据AOF持久化策略**[always,everysec,no]**将操作sync同步到磁盘的AOF文件中;
  3. AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;
  4. Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;

开启了AOF之后,RDB就默认不使用了。使用下面的配置开启AOF以及策略。(如果使用AOF,推荐选择always方式持久化,否则在高并发场景下,每秒钟会有几万甚至百万条请求,如果使用everysec的方式的话,万一服务器挂了那几万条数据就丢失了)

文件重写原理:

AOF持久化机制记录每个写命令,当服务重启的时候会复现AOF文件中的所有命令,会消耗太多的资源且重启很慢。因此为了避免AOF文件中的写命令太多文件太大,Redis引入了AOF的重写机制来压缩AOF文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。

redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。

重写会根据重写策略或手动触发AOF重写。

重写流程:

  1. bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行。
  2. 主进程fork出子进程执行重写操作,保证主进程不会阻塞。
  3. 子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区 保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。
  4. 1).子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。2).主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
  5. 使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。

重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

AOF也有三种触发机制:

  1. always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
  2. everysec:异步操作,每秒记录 如果一秒内宕机,有数据丢失
  3. no:从不同步

配置:

#开启AOF持久化
appendonly yes
 
#AOF文件名
appendfilename appendonly.aof
 
#AOF文件存储路径 与RDB是同一个参数
dir ./
 
#AOF策略,一般都是选择第一种[always:每个命令都记录],[everysec:每秒记录一次],[no:看机器的心情高兴了就记录]
appendfsync always
#appendfsync everysec
# appendfsync no
 
 
#aof文件大小比起上次重写时的大小,增长100%(配置可以大于100%)时,触发重写。[假如上次重写后大小为10MB,当AOF文件达到20MB时也会再次触发重写,以此类推]
auto-aof-rewrite-percentage 100 
 
#aof文件大小超过64MB时,触发重写
auto-aof-rewrite-min-size 64mb 

AOF 的优势和劣势

优势:

  1. 以文本形式保存,易读
  2. AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。也可以配置为always,保证数据不丢失。
  3. AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
  4. AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。

劣势:

  1. 存储所有写操作命令,且文件为文本格式保存,未经压缩,文件体积高
  2. 恢复数据时重放AOF中所有代码,恢复性能弱于RDB方式
  3. 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
  4. AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
3. RDB和AOF如何选择

选择的话,两者加一起才更好。因为两个持久化机制你明白了,剩下的就是看自己的需求了,需求不同选择的也不一定,但是通常都是结合使用。有一张图可供总结:

4. RDB和AOF混合使用(推荐)

看了上面的RDB和AOF的介绍后,我们可以发现,使用RDB持久化会有数据丢失的风险,但是恢复速度快,而使用AOF持久化可以保证数据完整性,但恢复数据的时候会很慢。于是从Redis4之后新增了混合AOF和RDB的模式,先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,即保证了数据完整性,又提高了恢复的性能。

配置:

#修改下面的参数即可开启AOF,RDB混合持久化:
aof-use-rdb-preamble yes
#开启后,AOF在重写时会直接读取RDB中的内容

运行过程:
通过bgrwriteaof完成,不同的是当开启混合持久化后,

  1. 子进程会把内存中的数据以RDB的方式写入aof中,
  2. 把重写缓冲区中的增量命令以AOF方式写入到文件
  3. 将含有RDB个数和AOF格数的AOF数据覆盖旧的AOF文件

新的AOF文件中,一部分数据来自RDB文件,一部分来自Redis运行过程时的增量数据

数据恢复过程:

当我们开启了混合持久化时,启动redis依然优先加载aof文件,aof文件加载可能有两种情况如下:

  1. aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
  2. aof文件开头不是rdb的格式,直接以aof格式加载整个文件。

优点:既能快速备份又能避免大量数据丢失
缺点:RDB是压缩格式,AOF在读取它时可读性较差

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/323046.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号