redis数据库的基本原理

本文全面解析Redis,涵盖其特性、数据结构支持、持久化机制、高可用性、集群模式、故障转移及扩容策略,深入探讨Redis在现代应用架构中的关键角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis简介:Redis 是开源免费的高性能 Key-V alue Nosql型数据库,不使用表。

redis特点:

  • Redis 支持数据的持久化(包括 AOF 和 RDB 两种模式),可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用,性能与可靠性兼顾;
  • Redis 不是仅仅支持简单的 Key-Value类型的数据,还支持字符串、列表、集合、散列表、有序集合数据结构的存储,这一优势使 Redis 适用于更广泛的应用场景;
  • Redis 支持数据的备份,即 Master-Slave 模式,Master 故障时,对应的 Slave 将通过选举升主,保障可用性;
  • Redis 主进程是单线程工作,因此,Redis 的所有操作都是原子性的,即操作要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性;
  • Redis 性能优越,读的速度达110000次/s,写的速度达81000次/s。
  • 除了上述特点,Redis 还支持 Publish/Subscribe,通知,Key 老化逐出等特性。

redis和memocached的区别和比较

  • Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,String。

  • Redis支持数据的备份,即master-slave模式的数据备份。

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中

  •  redis的速度比memcached快很多

  • Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的IO复用模型。

redis高可用

  • 哨兵模式:

    1.1每隔10s,每个S节点(哨兵节点)会向主节点和从节点发送info命令获取最新的拓扑结构

    1.2 每隔2s,每个S节点会向某频道上发送该S节点对于主节点的判断以及当前Sl节点的信息,

    同时每个Sentinel节点也会订阅该频道,来了解其他S节点以及它们对主节点的判断(做客观下线依据)

    1.3 每隔1s,每个S节点会向主节点、从节点、其余S节点发送一条ping命令做一次心跳检测(心跳检测机制),来确认这些节点当前是否可达

  • 主客观下线:

    2.1主观下线:根据第三个定时任务对没有有效回复的节点做主观下线处理

    2.2客观下线:若主观下线的是主节点,会咨询其他S节点对该主节点的判断,超过半数,对该主节点做客观下线

  • 故障转移:选举出某一哨兵节点作为领导者,来进行故障转移。选举方式:raft算法。每个S节点有一票同意权,哪个S节点做出主观下线的时候,就会询问其他S节点是否同意其为领导者。获得半数选票的则成为领导者。基本谁先做出客观下线,谁成为领导者。

redis数据持续化:

  • RDB方式:通过bgsave命令触发,然后父进程执行fork操作创建子进程,子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换(定时一次性将所有数据进行快照生成一份副本存储在硬盘中)
  1. 优点:是一个紧凑压缩的二进制文件,Redis加载RDB恢复数据远远快于AOF的方式。

  2. 缺点:由于每次生成RDB开销较大,非实时持久化,

  • AOF方式:开启后,Redis每执行一个修改数据的命令,都会把这个命令添加到AOF文件中。
  1. 优点:实时持久化。

  2. 缺点:所以AOF文件体积逐渐变大,需要定期执行重写操作来降低文件体积,加载慢

redis数据淘汰机制:

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。

  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。

  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

key的过期清除策略:

  • 惰性过期(类比懒加载,这是懒过期):只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

redis常见的面试问题参考这里:https://blog.youkuaiyun.com/zlc3323/article/details/80836881

redis单机模式:

  • 局限性:不支持自动故障转移,扩容能力极为有限,高并发瓶颈。

dba4bde0-26d0-11e8-ab3c-8d277e03c8cduploading.gif正在上传…重新上传取消

redis集群模式:

  • Redis 集群实现的基础是分片,即将数据集有机的分割为多个片,并将这些分片指派给多个 Redis 实例,每个实例只保存总数据集的一个子集。利用多台计算机内存和来支持更大的数据库,而避免受限于单机的内存容量;通过多核计算机集群,可有效扩展计算能 力;通过多台计算机和网络适配器,允许我们扩展网络带宽
  • 分片:
  1. 查询路由(Query Routing):你可以发送你的查询到一个随机实例,这个实例会保证转发你的查询到正确的节点。Redis-Cluster 在客户端的帮助下,实现了查询路由的一种混合形式(请求不是直接从 Redis 实例转发到另一个,而是客户端收到重定向到正确的节点)。
  2. 客户端分片(Client Side Partitioning):客户端直接选择正确的节点来写入和读取指定键
  3. 代理协助分片(Proxy Assisted Partitioning):我们的客户端发送请求到一个可以理解 Redis 协议的代理上,而不是直接发送请求到 Redis 实例上。代理会根据配置好的分片模式,来保证转发我们的请求到正确的 Redis 实例,并返回响应给客户端。Redis 和 Memcached 的代理 Twemproxy 实现了代理协助的分片

3882e890-2607-11e8-b275-597c20833f3duploading.gif正在上传…重新上传取消

Redis-Cluster 原理:

(1)Hash slot

基于“分片”的思想,Redis 提出了 Hash Slot。Redis-Cluster 把所有的物理节点映射到预分好的16384个 Slot,当需要在 Redis 集群中放置一个 Key-Value 时,根据 CRC16(key) Mod 16384的值,决定将一个 Key 放到哪个 Slot 中。

(2)集群内的每个 Redis 实例监听两个 TCP 端口,6379(默认)用于服务客户端查询,16379(默认服务端口 + 10000)用于集群内部通信。

(3)节点间状态同步:Gossip 协议,最终一致性。所有的 Redis 节点彼此互联(PING-PONG机制),节点间通信使用轻量的二进制协议,减少带宽占用。

Redis-Cluster 请求路由方式

客户端直连 Redis 服务,进行读写操作时,Key 对应的 Slot 可能并不在当前直连的节点上,经过“重定向”才能转发到正确的节点

enter image description here

和普通的查询路由相比,Redis-Cluster 借助客户端实现的请求路由是一种混合形式的查询路,它并非从一个 Redis 节点到另外一个 Redis,而是借助客户端转发到正确的节点。

在实际应用中,可以在客户端缓存 Slot 与 Redis 节点的映射关系,当接收到 MOVED 响应时修改缓存中的映射关系。如此,基于保存的映射关系,请求时会直接发送到正确的节点上,从而减少一次交互。

目前,包括 Lettuce(下文将介绍),Jedis 在内的许多 Redis Client,都已经实现了对 Redis-Cluster 的支持。

客户端分片

  • 由客户端决定 Key 写入或者读取的节点。
  • 包括 Lettuce、Jedis 在内的一些客户端,实现了客户端分片机制。

enter image description here

采用客户端分片具有逻辑简单,性能高的优点,但缺点也很明显:业务逻辑与数据存储逻辑耦合,可运维性差;多业务各自使用 Redis,集群资源难以管理,不支持动态增删节点。

基于代理的分片

为了克服客户端分片业务逻辑与数据存储逻辑耦合的不足,可以通过 Proxy 将业务逻辑和存储的逻辑隔离。客户端发送请求到一个代理,代理解析客户端的数据,将请求转发至正确的节点,然后将结果回复给客户端。这种架构还有一个优点 就是可以把 Proxy 当成一个中间件,在这个中间件上你可以做任何事情,比如可以把集群和主从的兼容性做到几乎一致、可以做无缝扩缩容、安全策略等等。

基于代理的分片已经有很多成熟的方案,如开源的 Codis,此外,阿里云 ApsaraDB for Redis/ApsaraCache 等大企业很多也是采用 Proxy+Redis-server 的架构。

enter image description here

Redis故障转移

在上面已经介绍过单机模式的故障转移(主节点下线后,对应从节点升主并替代原主节点继续工作的过程),单机模式下故障转移需要 Sentinel 系统的辅助,与之不同,Redis 集群模式故障转移并不需要 Sentinel 系统辅助,而是通过集群内部主节点选举完成,是一个“自治”的系统

故障检测:

  • (1)单点视角检测

    集群中的每个节点都会定期通过集群内部通信总线向集群中的其它节点发送 PING 消息,用于检测对方是否在线,如果接收 PING 消息的节点没有在规定的时间内向发送 PING 消息的节点返回 PONG 消息,那么,发送 PING 消息的节点就会将接收 PING 消息的节点标注为疑似下线状态(Probable Fail,Pfail)。

    (2)检测信息传播

    集群中的各个节点会通过相互发送消息的方式来交换自己掌握的集群中各个节点的状态信息,如在线,疑似下线(Pfail),下线(fail)。例如, 当一个主节点 A 通过消息得知主节点 B 认为主节点 C 疑似下线时,主节点 A 会更新自己保存的集群状态信息,将从 B 获得的下线报告保存起来。

    (3)基于检测信息作下线判决

    如果在一个集群里,超过半数的处理槽的主节点都将某个主节点 X 报告为疑似下线,那么,主节点 X 将被标记为下线(fail),并广播出去,所有收到这条 fail 消息的节点都会立即将主节点 X 标记为 fail。至此,故障检测完成。

选举

  • (1)从节点拉票

    基于故障检测信息的传播,集群中所有正常节点都将感知到某个主节点下线的信息,当然也包括这个下线主节点的所有从节点。当从节点发现自己的复制的主节点状态为已下线时,从节点就会向集群广播一条请求消息,请求所有收到这条消息并且具有投票权的主节点给自己投票。

    (2)拉票优先级

    严格的讲,从节点在发现其主节点下线时,并不是立即发起故障转移流程而进行“拉票”的,而是要等待一段时间,在未来的某个时间点才发起选举。这个时 间点有如下计算表达式:其中,固定延时500ms,是为了留出时间,使主节点下线的消息能传播到集群中其他节点,这样集群中的主节点才有可能投票;随机延 时是为了避免两个从节点同时开始故障转移流程;rank 表示从节点的排名,排名是指当前从节点在下线主节点的所有从节点中的排名,排名主要是根据复制数据量来定,复制数据量越多,排名越靠前,因此,具有较多复 制数据量的从节点可以更早发起故障转移流程,从而更可能成为新的主节点。

    (3)主节点投票

    如果一个主节点具有投票权(负责处理 Slot 的主节点),并且这个主节点尚未投票给其它从节点,那么这个主节点将向请求投票的从节点返回一条回应消息,表示支持该从节点升主。

    (4)根据投票结果决策

    在一个具有 N 个主节点投票的集群中,理论上每个参与拉票的从节点都可以收到一定数量的主节点投票,但是,在同一轮选举中,只可能有一个从节点收到的票数大于 N/2 + 1,也只有这个从节点可以升级为主节点,并代替已下线的主节点继续工作。

    (5)选举失败

    跟生活中的选举一样,选举可能失败——没有一个候选从节点获得超过半数的主节点投票。遇到这种情况,集群将会进入下一轮选举,直到选出新的主节点为止。

    (6)选举算法

    选举新的主节点的算法是基于 Raft 算法的 Leader Election 方法来实现的,本文就不展开了

故障转移

  • (1)身份切换

    通过选举晋升的从节点会执行一系列的操作,清除曾经为从的信息,改头换面,成为新的主节点。

    (2)接管职权

    新的主节点会通过轮询所有 Slot,撤销所有对已下线主节点的 Slot 指派,消除影响,并且将这些 Slot 全部指派给自己。

    (3)广而告之

    升主了嘛,必须让圈子里面的都知道,新的主节点会向集群中广播一条 PONG 消息,将自己升主的信息通知到集群中所有节点。

    (4)履行义务

    在其位谋其政,新的主节点开始处理自己所负责 Slot 对应的请求,至此,故障转移完成。

Redis 扩容

随着应用场景的升级,缓存可能需要扩容,扩容的方式有两种:纵向扩容(Scale Up)和横向扩容(Scale Out)。纵向扩容可以通过客户端命令:config set maxmemory xxx 实现,无需详述。实际应用场景中,采用横向扩容更多一些,根据是否增加主节点数量,横向扩容方式有两种

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值