Redis—持久化机制

2024-08-22 07:36
文章标签 化机制 redis 持久

本文主要是介绍Redis—持久化机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Redis持久化机制

  • 1. RDB
    • 1.1 实现方式
    • 1.2 实现原理
  • 2. AOF
    • 2.1 实现方式
    • 2.2 AOF文件载入
    • 2.3 AOF重写
    • 2.4 重写触发
  • 3. RDB vs AOF
    • 3.1 RDB
    • 3.2 AOF
    • 3.3 如何选择?
  • 4. Redis 4.0 混合持久化

Redis的持久化机制有两种持久化机制,分别是 RDB 和 AOF

1. RDB

Redis Database Backup file(RDB),也被称为Redis数据快照,RDB将内存中的数据都记录在磁盘上,当Redis 出现意外,可以通过重启 Redis 加载该文件来恢复数据。

RDB 默认开启,既可以手动执行,也可以根据服务器配置选项定期 自动执行。

服务器在恢复数据库数据(载入RDB文件)时,会一直处于阻塞状态,直到载入完成为止。

1.1 实现方式

手动执行

  • SAVE命令:阻塞 Redis 进程,直到 RDB 文件创建完成为止,这个阶段服务器无法处理任何命令请求
save <时间间隔> <执行指定次数更新操作>
  • BGSAVE命令:创建一个子进程来创建RDB文件,这个阶段服务器可以处理请求,但是会拒绝SAVE、BGSAVE、BGREWRITEAOF命令

SAVE是阻塞式的,因此其可用性欠佳,如果在数据量较少的情况下,基本上体会不到两个命令的差别,建议使用BGSAVE

自动执行

BGSAVE是非阻塞的,所以Redis允许通过配置 redis.conf 文件中的 save 配置,让服务器每隔一段时间自动执行一次 BGSAVE 命令,可以设置多个保存条件,比如以下3个默认条件

# 将数据库保存到磁盘上:
#   save <秒数> <更改数>
#   如果满足给定的秒数和对数据库的写操作次数,则保存数据库。
#   在下面的示例中,行为将是:
#   当至少有1个键发生更改时,每900秒(15分钟)保存一次
#   当至少有10个键发生更改时,每300秒(5分钟)保存一次
#   当至少有10000个键发生更改时,每60秒保存一次
#   注意:您可以通过注释掉所有的 "save" 行来完全禁用保存功能。
#   也可以通过添加一个只有一个空字符串参数的保存指令来删除所有先前配置的保存点,如下面的示例:
#   save ""
save 900 1   #在900秒(15分钟)之内,对数据库进行了至少1次修改,则执行一次BGSAVE
save 300 10  #在300秒(5分钟)之内,对数据库进行了至少10次修改,则执行一次BGSAVE
save 60 10000 #在60秒之内,对数据库进行了至少10000次修改,则执行一次BGSAVE

1.2 实现原理

当Redis服务启动时,用户可以通过指定配置文件或者传入启动参数的方式设置save选项

如果没有主动设置,服务器就会使用redis.conf文件中默认的条件(上述3个默认条件)。

接着,服务器会根据save的选项所设置的保存条件,设置服务器状态 redisServer 结构的 saveparams 属性,除此之外,还有一个 dirty 计数器lastsave 属性

struct redisServer{//....//记录了保存条件的数组struct saveparam *saveparams;//修改计数器long long dirty;//上一次执行保存的时间time_t lastsave;//.....
};
  • saveparams属性:是一个数组,每个 saveparams 结构都保存了一个save选项设置的保存条件:
struct saveparam{//秒数time_t seconds;//修改数int changes;
};
  • dirty 属性:记录上一次成功成功执行 SAVE 命令或 BGSAVE 命令之后,服务器对数据库(全部数据库)进行了多少次修改(包括写入、删除、更新等操作)

  • lastsave 属性:是一个UNIX时间戳,记录服务器上一次成功执行 SAVE 或 BGSAVE 命令的时间。

Redis的服务器有一个周期性操作函数serverCron,它每隔100ms就会执行一次,该函数用于对正在运行的服务器进行维护,其中的一项工作就是检查save选项所设置的保存条件是否已满足,如果满足就执行BGSAVE命令。

2. AOF

Append Only File,采用日志的形式来记录每个写操作,并追加到文件中。

默认不开启,可在redis.conf文件中配置

Redis 重启会根据日志文件的内容将写命令从前到后执行一遍来恢复数据,解决生成 RDB 文件后数据不能实时一致的问题

2.1 实现方式

AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤

  • 命令追加:服务器在执行完一个写命令后,会将被写命令追加到服务器状态的aof_buf缓冲区的末尾

  • 文件写入:将aof缓冲区的数据写入到AOF文件,此时数据并没有写入到硬盘,而是拷贝到了内核缓冲区page cache(操作系统),等待内核将数据写入硬盘;具体内核缓冲区的数据什么时候写入到硬盘,由内核决定。

  • 文件同步:将内核缓冲区中的数据写入到硬盘中的AOF文件中。

如果由内核决定将内核数据写入硬盘的话,如果服务器宕机,那么就会丢失数据。为了解决这个问题,系统提供了 fync 和 fdatasync 两个同步函数,它们可以强制让操作系统立即将缓冲区中的数据写入到硬盘,以及三种策略:

  • always:同步写回,每个写命令执行完立刻同步地将日志写回磁盘。(性能最差,最多丢失一个写指令的数据)
  • everysec(默认):每秒执行一次。(是性能和数据安全性的折中方案,最多也就丢一秒的数据)
  • no:根据操作系统和资源的情况,一定时间执行一次,时间不确定。(性能最好,可能会丢失上次同步AOF文件之后的所有写命令数据)

2.2 AOF文件载入

因为AOF文件里包含了所有写命令,所以服务器只要读入并重新执行一遍AOF文件里面的命令,就可以还原服务器关闭之前的数据,详细步骤如下:

  1. 创建一个不带网络连接的伪客户端(fake client):因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样。
  2. 从AOF文件中分析并读取出一条写命令。
  3. 使用伪客户端执行被读出的写命令。
  4. 一直执行步骤2和步骤3,直到AOF文件中的所有写命令都被处理完毕为止。

当完成以上步骤之后,AOF文件所保存的数据库状态就会被完整地还原出来,流程如下图所示:
在这里插入图片描述

2.3 AOF重写

AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大

Redis重写功能的大致流程如下:

  • Redis 会启动一个 AOF 重写子进程,负责执行 AOF 重写操作。同时,Redis 会继续处理新的写入命令,并将这个写命令发送给AOF缓冲区和AOF重写缓冲区。
  • 子进程会按照一定的规则,读取当前数据库的键值对,并将其转化为合适的命令格式,保存到AOF重写缓冲区中。
  • 子进程在遍历完整个数据库之后,就完成了重写工作。
  • 接着,服务器父进程就会执行以下操作:
    • 将AOF重写缓冲区中的所有内容写入到新的AOF文件中,使得新的AOF文件于当前数据库中的数据一致。
    • 对新的AOF文件进行改名,原子地(atomic)覆盖现有的AOF文件,完成新旧两个AOF文件的替换。
  • 最后,Redis 会关闭并销毁旧的 AOF 文件。

AOF缓冲区:无论重不重写都有这个缓冲区,AOF日志写入是AOF缓冲区->AOF文件
AOF重写缓冲区:AOF重写子进程启动后开始使用。

2.4 重写触发

手动触发:手动执行 BGREWRITEAOF 命令,开始重写 aof 文件
自动触发:可以在 redis.conf 文件中修改对应的配置,让服务器自动执行 BGREWRITEAOF 命令。

3. RDB vs AOF

RDB 和 AOF 在数据可靠性、性能、存储空间、使用场景等方面都有不同的优缺点,具体可以根据实际业务需求和硬件条件选择合适的持久化机制,或者同时使用两种持久化机制来实现更高的数据可靠性

3.1 RDB

优点:

  1. 只有⼀个紧凑的⼆进制文件 dump.rdb ,非常适合备份、全量复制的场景
  2. 容灾性好,可以把 RDB 文件拷贝道远程机器或者⽂件系统张,用于容灾恢复。
  3. 恢复速度快,RDB 恢复数据的速度远远快于 AOF 的⽅式

缺点:

  1. 实时性低,RDB 是间隔⼀段时间进行持久化,没法做到实时持久化、秒级持久化。如果在这⼀间隔事件发生故障,数据会丢失。
  2. 存在兼容问题,Redis 演进过程存在多个格式的 RDB 版本,存在老版本 Redis 无法兼容新版本 RDB 的问题。

3.2 AOF

优点:

  1. 实时性好,aof 持久化可以配置 appendfsync 属性,有 always ,每进行⼀次命令操作就记录到 aof 文件中⼀次。
  2. 通过 append 模式写⽂件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据⼀致性问题

缺点:

  1. AOF 文件比 RDB 文件大,且恢复速度慢
  2. 数据集大的时候,比 RDB 启动效率低

3.3 如何选择?

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

4. Redis 4.0 混合持久化

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

我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB 来说要慢很多,这样在 Redis 实很大的情况下,启动需要花费很长的时间。

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

将 rdb 文件的内容和增量的 AOF 日志文件存在一起。

这里的 AOF 日志不再是全量的日志,而是 自持久化开始到持久化结束 的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小,如下图所示
在这里插入图片描述
于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

优点:混合持久化结合了 RDB 和 AOF 持久化的优点,开头为RDB格式,可以使Redis启动的更快,同时结合AOF的优点,又降低了大量数据丢失的风险。

缺点:在 AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差;如果开始混合持久化,那么混合持久化的 AOF 是不能在旧版本中用的,不能向下兼容


参考《Redis设计与实现》& 二哥的面渣逆袭,加油!

这篇关于Redis—持久化机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095643

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题 缓存穿透是指查询一个一定不存在的数据,由于缓存中没有命中,会去数据库中查询,而数据库中也没有该数据,并且每次查询都不会命中缓存,从而每次请求都直接打到了数据库上,这会给数据库带来巨大压力。 二、布隆过滤器原理 布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用多个不同的哈希函数将一个元素映射到一个位数组中的多个位置,并将这些位置的值置

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

laravel框架实现redis分布式集群原理

在app/config/database.php中配置如下: 'redis' => array('cluster' => true,'default' => array('host' => '172.21.107.247','port' => 6379,),'redis1' => array('host' => '172.21.107.248','port' => 6379,),) 其中cl

Redis的rehash机制

在Redis中,键值对(Key-Value Pair)存储方式是由字典(Dict)保存的,而字典底层是通过哈希表来实现的。通过哈希表中的节点保存字典中的键值对。我们知道当HashMap中由于Hash冲突(负载因子)超过某个阈值时,出于链表性能的考虑,会进行Resize的操作。Redis也一样。 在redis的具体实现中,使用了一种叫做渐进式哈希(rehashing)的机制来提高字典的缩放效率,避

【吊打面试官系列-Redis面试题】说说 Redis 哈希槽的概念?

大家好,我是锋哥。今天分享关于 【说说 Redis 哈希槽的概念?】面试题,希望对大家有帮助; 说说 Redis 哈希槽的概念? Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

Redis地理数据类型GEO

通常要计算两个地理位置的距离不是很方便,这里可以直接通过Redis提供的GEO操作来完成地理位置相关的计算 1)添加地理位置 语法:geoadd key longitude latitude member [longitude latitude member] ...字段说明:key:存放地理位置的集合名称longitude:地理坐标的经度latitude:地理坐标的纬度member:表示这

Redis-主从集群

主从架构 单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。 主从数据同步原理 全量同步 主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程: 判断是否是第一次同步,如果是,返回版本信息(replication id 和offset),将salve节点的版本信息变为master的

Redis安装使用总结

一、下载安装 从 github 下载:https://github.com/MSOpenTech/redis/releases 或者 https://github.com/ServiceStack/redis-windows 解压缩,如图: 二、配置 打开redis.windows-sevice.conf文件, 2.1 绑定ip:搜索127.0.0.1 ,发现bind 127.0.0.

面对Redis数据量庞大时的应对策略

面对Redis数据量庞大时的应对策略,我们可以从多个维度出发,包括数据分片、内存优化、持久化策略、使用集群、硬件升级、数据淘汰策略、以及数据结构选择等。以下是对这些策略的详细探讨: 一、数据分片(Sharding) 当Redis数据量持续增长,单个实例的处理能力可能达到瓶颈。此时,可以通过数据分片将数据分散存储到多个Redis实例中,以实现水平扩展。分片的主要策略包括: 一致性哈希:使用一