40.【面试宝典】面试宝典-redis持久化

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【面试宝典】面试宝典-redis持久化

前文如上:

39.【面试宝典】面试宝典-redis过期k值回收策略,缓存淘汰策略


合集参考:面试宝典

redis持久化

1.概述


由于 redis 是一个内存数据库,所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写效率)。但是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的数据将会全部丢失. redis持久化是指在指定的时间间隔内将内存中的数据集快照(snapshotting)写入磁盘,恢复时是将快照文件读入内存。redis提供了两种持久化方式:

  1. RDB(Redis DataBase)
  2. AOF(Append of File)

2.rdb:


2.1 概念:


在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里,在默认配置中,Redis将内存数据库快照保存在名字为dump.rdb的二进制文件中。

2.2 原理:


Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。如图所示:

注: fork函数的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

网络异常,图片无法展示
|

2.3 优点:


  1. 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
  2. 节省磁盘空间
  3. 恢复速度快

2.4 缺点:


  1. Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
  2. 虽然Redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
  3. 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。

适合场景: 适合大规模的数据恢复,适合对数据完整性和一致性要求不高更适合使用。


2.5 触发方式


  1. 自动触发

可以通过配置文件配置持久化策略:save N M,表示m秒内数据集存在n次修改时,自动触发bgsave 例如redis的默认策略有:


save 900 1   -- 900秒内至少有一个改动
save 300 10   -- 300秒内至少有10个改动
save 60 10000 -- 60秒内至少有10000个改动


当然如果你只是用Redis的缓存功能,不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。 也可以直接一个空字符串来实现停用:


save ""


或者连接客户端手动停止RDB:


redis-cli config set save ""  #save后给空值,表示禁用保存策略

  1. 手动触发 手动触发Redis进行RDB持久化的命令有两种:
  • save: 该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。
  • bgsave: 执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

网络异常,图片无法展示
|


注意:执行执行 flushall 命令,也会产生dump.rdb文件,但里面是空的.shutdown也会触发RedisRDB持久化机制,我们在客户端执行shutdown即可


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

  • rdbcompression :默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。

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

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

  • dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。

也就是说通过在配置文件中配置的 save 方式,当实际操作满足该配置形式时就会进行 RDB 持久化,将当前的内存快照保存在 dir 配置的目录中,文件名由配置的 dbfilename 决定。

3. aof


3.1 概念


为解决RDB方式丢失数据的问题,从1.1版本开始,redis增加了一种更加可靠的方式:AOF持久化方式。


AOF(Append Only File)是把所有对内存进行修改的指令(写操作)以独立日志文件的方式进行记录,只许追加文件但不可以改写文件(类似于wal日志)。AOF能够解决数据持久化实时性问题,是现在Redis持久化机制中主流的持久化方案。redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

3.2 流程


  1. 客户端所有请求的写命令都会被追加到AOF缓冲区中;
  2. AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;
  3. AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;
  4. AOF重写:当AOF的文件达到重写策略配置的阈值时,Redis会对AOF日志文件进行重写,给AOF日志文件瘦身)

  5. Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;

网络异常,图片无法展示
|

3.3 优势


  1. 备份机制更稳健,丢失数据概率更低。
  2. 可读的日志文本,通过操作AOF稳健,可以处理误操作。

3.4 劣势


  1. 客户端所有请求的写命令都会存储,比起RDB占用更多的磁盘空间。
  2. 恢复备份速度要慢。
  3. 每次读写都同步的话,有一定的性能压力。
  4. 存在个别Bug,造成不能恢复。

3.5 配置


1 打开 redis.conf 文件,找到 APPEND ONLY MODE 对应内容 redis 默认关闭,开启需要手动把no改为yes


appendonly yes

2 指定本地数据库文件名,默认值为 appendonly.aof


appendfilename "appendonly.aof"


3 指定更新日志条件


# appendfsync always
appendfsync everysec
# appendfsync no


AOF同步频率设置

  • appendfsync always 始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
  • appendfsync everysec 每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
  • appendfsync no redis不主动进行同步,把同步时机交给操作系统。


3.6 总结


  1. 官方推荐两个都启用。
  2. 如果对数据不敏感,可以选单独用RDB。
  3. 不建议单独用 AOF,因为可能会出现Bug。
  4. 如果只是做纯内存缓存,可以都不用。


3.7 AOF重写


前面提到,AOF持久化客户端所有请求的写命令都会存储,比起RDB占用更多的磁盘空间,文件的冗余内容会越来越多。比如同一个key被写了10000次,最后却被删除了,这种情况不仅占内存,也会导致恢复的时候非常缓慢,因此Redis提供重写机制来解决这个问题。


1.AOF重写原理

Redis 会fork出一条新进程,读取内存中的数据,并重新写到一个临时文件中。并没有读取旧文件。最后替换旧的aof文件。RedisAOF持久化机制执行重写后,保存的只是恢复数据的最小指令集,我们如果想手动触发可以使用如下指令:

bgrewriteaof
复制代码


2.AOF重写流程

AOF重写不会阻塞主线程,其重写过程是由后台子进程 bgrewriteaof 来完成的,从而避免了性能下降。具体流程如下:

  1. 把主线程的内存拷贝一份给fork出来的 bgrewriteaof 子进程,这里面包含了Redis中最新的数据。
  2. 子进程将其中的数据进行重写。
  3. 主线程维护一个AOF缓冲区(实际上无论重不重写都有这个缓冲区,因为AOF日志写入是 → AOF缓冲区 → AOF文件),如果此时有写操作,则会写入到AOF缓冲区以及AOF日志中,保证数据完整。
  4. 主线程在重写时维护一个AOF重写缓冲区,将重写过程中的写操作记入其中,保证重写后的AOF日志也能记录在重写过程中产生的新数据。
  5. 用新AOF替换老AOF日志。

文档参考:Redis持久化

网络异常,图片无法展示
|

由于重写AOF文件时,会对Redis的性能带来一定的影响,因此也不能随便的进行自动重写,Redis提供两个配置用于自动进行AOF重写的指标,只有这两个指标同时满足的时候才会发生重写:


3.AOF重写触发机制

当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。这里的“一倍”和“64M” 可以通过配置文件修改

  • auto-aof-rewrite-percentage 100:指的是当文件的内存达到原先内存的两倍
  • auto-aof-rewrite-min-size 64mb:指的是文件重写的最小内存大小

4.思考:为什么AOF重写不采用覆盖的方式

父子进程写同一个文件必然会产生竞争,如果控制竞争就意味着会影响父进程的性能。 如果AOF重写失败,那么原本的AOF文件相当于被污染了,就直接废了。而采用覆盖的方式则不会有这种负面影响(重写失败就直接删了,一点影响没有)。

4. 拓展


4.1 如何选择合适的持久化方式

  • 一般来说,如果想达到足以媲美PostgreSQL的数据安全性,你应该同时使用两种持久化功能。在这种情况下,当Redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
  • 如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。
  • 有很多用户都只使用AOF持久化,但并不推荐这种方式,因为定时生成RDB快照(snapshot)非常便于进行数据库备份,并且RDB恢复数据集的速度也要比AOF恢复的速度要快,除此之外,使用RDB还可以避免AOF程序的bug
  • 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。

4.2 Redis持久化数据和缓存怎么做扩容?

  • 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。
  • 如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。

公众号,感谢关注

网络异常,图片无法展示
|



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
14天前
|
存储 缓存 NoSQL
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
31 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
|
6天前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
12天前
|
NoSQL 算法 Redis
Redis面试篇
Redis面试篇
31 5
|
13天前
|
缓存 NoSQL Java
Java中redis面试题
Java中redis面试题
25 1
|
14天前
|
消息中间件 分布式计算 NoSQL
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
20 2
|
14天前
|
存储 缓存 NoSQL
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
38 1
|
2天前
|
存储 缓存 NoSQL
面试官:Redis如何实现延迟任务?
面试官:Redis如何实现延迟任务?
11 0
|
11天前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!
|
2月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
14天前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
35 2