Redis 核心原理总览(全局篇)
正文开始之前,我们先思考下「如何造一个缓存组件?」
注
:该片段是 Redis 原理知识地图,请仔细阅读!(基于redis6.2
)
1)最小可用版:
- 要快:缓存最核心的目的是支持快速访问,硬件层面一般选择「内存」
- 远程访问:作为缓存组件,要支持单独部署,可以利用现有开源网络库,也可以自己实现。
大部分语言都提供了内存操作,条件 1 很容易满足,条件 2 要支持远程访问,就要和 TCP 连接打交道,我们可以利用开源的网络库,比如 C 版的 libc
等。
原理篇第一部分:将围绕一条请求探索 redis 高性能的核心原理。
2)进阶版:
第一步我们已经有了缓存组件最基本的雏形,并且已经达到了高性能的处理能力,这个时候我们可能有更多的诉求:
- 稳定:即 尽可能不丢数据、无故障或故障后快速恢复、自动处理故障的能力
- 可扩展:单机容量或者 QPS 达到上限,支持水平扩展能力。
原理篇第二部分:将围绕 redis 架构演进进行剖析。
全局知识地图:
前言
本文围绕「架构主线」来透视 Redis「高可靠」的核心原理,在正文开始之前,我们先思考几个问题:
- 数据要如何切分,在扩缩容过程迁移量最小?
- 分片元数据如何维护?中心化 or 去中心化?
- 如何平滑的从单机版升级到 cluster 集群版
如果你对以上问题了然于胸,这篇文章读起来很容易,权当帮你串联、回顾知识点,如果不是很清楚也没关系,且听我细细道来!
一、数据分片
1、集群?
即使硬件技术按照「摩尔定律」的速度快速升级,单机容量也很难支撑当前的海量数据场景。
想当年,集群的概念还未盛行时,那些优秀的工程师抠破脑袋的去升级硬件,效果你懂得 ...
当有人提出使用多台机器承载数据的方案后,多年的梦魇被打破,集群的时代 ---- 来了。
集群数据分配?
选定一种规则,将数据尽可能均匀的分配到集群的各台机器上,当然在这里插入图片描述 ,也要方便「取出来」
很多人应该想到了 ----「哈希取模」,所有数据经过哈希函数一计算,得到机器编号,数据就存在该机器上,当然,取数据也是相同的方式。
2、分片?
分片,顾名思义,将完整数据集分成多块(分片),然后将这些分片分配至集群中的各台机器上。
对集群的管理,本质也是对分片的管理。
3、分片固定?
上面的分片思路是正确的,但还有致命缺点 ---- 当集群新增或者减少机器节点时,整个数据就乱了,所有数据要重新进行分配,效率极低。
解决方案:即「固定分片」,不管集群机器数量如何变化,只要分片数量不变动,数据与分片的映射关系就不变。
当集群机器数量变更时,我们只需要将变更的机器上的分片进行迁移即可,不会存在大规模「重新洗牌」的局面。
我画了张图,你可以参考下:
值得注意的是,机器与数据没有直接关系,只和分片有直接关联。
4、元数据
你应该注意到了,集群中分片与机器的关系十分重要,所谓 "林子大了什么鸟都有",同样,机器多了什么故障都有可能出现:
- 机器变更
- 分片均衡/迁移
- ...
只要发生了变化,都需要维护这套映射关系。
这套映射关系,我们也习惯称为「元数据」,在分布式集群中应该是非常常见。可以这样说,很多分布式机制、算法都是围绕这套元数据展开。
业界有两种常见的元数据维护方案:
- 中心化:由中心化的节点来维护,所有请求都先到中心节点,该节点查询元数据后告诉你该访问集群中的具体节点。
- 去中心化:不需要中心节点,那元数据谁来维护?
值得提一下:集群中的每个节点都维护一套,一般客户端也要缓存一份,这么多份数据,最大的问题是什么?一致性
,也就是涉及到一些「分布式一致性协议」选择了
二、集群
目前市面上 Redis 有两种主流的集群方案,本质区别:多元数据的管理采用「中心化」还是「去中性化」的方案。
1、代理集群
代表:社区集群解决方案
官方集群解决方案出来的晚一些,那会,市场对集群需求性大,衍生出很多开源的代理集群解决方案。
采用典型的「中心化」方案,所有请求先经过代理节点,代理节点维护了「元数据」映射关系,也就知道这个请求应该请求哪个集群节点。
1)社区早期集群方案:Codis、Temproxy:
这些方案不具备 HA(高可用)的能力,所以需要单独部署 HA,我画了张图,你可以参考下:
2)predixy 代理:支持多种 redis 运行模式,对客户端友好:
这种方案会更加友好,也是目前比较流行的方案,你可以这样理解:
为了解耦「客户端」与「服务端」的关联(各种 SDK ...),使用代理这种中间节点(你可以想想现实中的房产中介),繁琐的工作交给代理节点来完成。
然后,客户端就像连接单个节点一样,连接到代理节点,而代理节点的背后可以是:
- 单机部署
- 主从 + 哨兵集群的高可用部署
- Redis Cluster 官方集群部署
是不是很方便,各大云厂商大多都是这种模式。我画了张图,你可以参考下:
2、分片集群
redis cluster 是官方提供的分布式集群解决方案,相对于单机版 redis 拥有更高的存储容量和更高的吞吐量。
换句话说,海量存储的终极方案,就是搞集群,多机器
。简单总结三大特性:
- 去中心化
- Gossip 协议
- 内置 HA(高可用)
我画了张图,你可以参考下:
去中心化:
redis cluster 集群采用「去中心化」的方式,集群中的每个节点以及客户端都会存储(或者说缓存)一份相同的元数据信息。
由于元数据可能会更新,因此整个集群采用 Gossip 协议进行数据交换,该协议的特点是 一传十、十传百的类似于流言的方式,集群节点越多,完成一次全同步需要的时间越长
。
所以,你会看到这种去中心化的方案,本质还是受限于集群节点总体大小,比如,很难支撑超超大集群规模(1w+节点、10w+节点),官方建议是不超过 1000 节点。
基于此,在业务上做拆分,使用不同的 redis 集群也是不错的方案。
高可用:
Cluster 集群,内置 HA 的能力,简单理解,集群内自有一套故障检测规则,并且是分布式的,这样才能避免主观下线因素。
内部的所有主节点成为最终的裁判,拥有故障判决权和新主节点的投票选举权,基于此,也就不再需要额外的哨兵来参与故障转移(其实这部分工作就相当于哨兵的工作)
对于高可用,我们首先要有足够的副本(从节点),然后是主节点(拥有选举权)以及要合适的故障检测机制、共识选举算法、执行故障转移等。
3、代理 + 分片集群
特点:
对客户端友好、无历史包袱
为啥需要这种模式?
你想想,Cluster 集群的特殊型在于「去中心化」,客户端也需要缓存元数据 ...
因此,客户端的 SDK 要做更多的工作来适配,当你启用 Cluster 集群时,你的所有客户端 SDK 是不是都要升级?成本就大了。
这个时候有一种平滑的操作,像使用单机版的 redis 一样,是不是很 Nice?
我大致画了张图,你可以参考下:
值得注意的是,集群中每个节点只存一部分数据,所以有些 redis 命令可能有些限制
三、生产实践
拿生产上使用的 Redis 例子来看看,为了方便,我们直接使用了 腾讯云的 Redis,其主要提供了两种架构:
标准架构:
代理节点 + (主从 + HA 高可用集群 ---- 类似于哨兵):
集群架构:
代理节点 + Redis Cluster 分片集群:
你可以看到的是,腾讯云提供给的这两种模式都属于我们介绍的:「代理 + Redis 服务」:
- 代理 + 单机高可用模式
- 代理 + 集群模式
对客户端十分友好,你只需要连接到一个代理节点即可,后面的 HA、集群你都不需要关心 !!!
总结
一台机器容量不够了或者 QPS 撑不住了?
- 代理集群:社区版,如 twemproxy、codis,在代理层做逻辑分片、路由等,节点间无交流。
- 分片集群:官方版,无中心化,节点间采用 Gossip 协议通信,官方建议集群节点不超过 1000
- 代理 + 分片集群:对客户端友好, 推荐使用官方版集群,另外可以在官方版集群架构下使用一层代理,对客户端支持友好。
好,我们再来回顾下文章开头提到的几个问题,看看你是否都已经清楚了呢?
- ❓ 数据要如何切分,在扩缩容过程迁移量最小?
- ❓ 分片元数据如何维护?中心化 or 去中心化?
- ❓ 如何平滑的从单机版升级到 cluster 集群版?