作者:贲绍华
爱可生研发中心工程师,负责项目的需求与维护工作。其他身份:柯基铲屎官。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
一、集群架构的一些基本概念
当我们只使用一台 Redis 实例也就是 Single 架构时,需要考虑一些非常实际的问题,如:单节点一但宕机则业务停摆、单节点的容量不可能是无限制的、性能同样存在瓶颈等......
集群架构模式最主要的三个目的就是:高可用、提升资源限制瓶颈、提升网络吞吐:
1.1 高可用 - Sentinel
Redis Sentinel 是一个分布式系统, 可以在一个架构中运行多个 Sentinel 进程(progress)
这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,
以及选择哪个从服务器作为新的主服务器。
1.2 提升资源限制瓶颈 - 数据分区存储(Partitioning)
将数据通过对应的算法规则,自动分割数据到不同的节点上,每一个节点都是主,都承担一部分数据。
在整个集群的部分节点失败或者不可达的情况下依然能够继续处理命令。
数据的拆分可以依据AKF原则根据不同维度进行灵活拆分:
1.3 提高网络吞吐
Redis使用的是epoll IO模型,单机吞吐量也足够优秀,但当业务流量单一入口不能兜住时则需要考虑分流策略了。
如:增加 slave 节点、使用 proxy 作为流量入口、Redis cluster、LVS等
灵活的架构能使业务侧不需要太关心具体到哪个节点,节点资源瓶颈如何。均使用统一流量入口即可。
二、客户端分区
此处的客户端指的就是业务侧,根据业务类型分类存取,自行维护一个 client to redis node 的映射关系或服务发现机制。
简单场景下这么做并不会有什么问题,但是也存在一些缺点,如:
- 存取规则需要统一,需要考虑扩缩容时业务逻辑调整的影响面
- 业务其实并不清楚 Redis 节点机器的瓶颈
- 每个客户端都需要连接所有的 Redis 节点
三、代理分区
Redis 也有一些优秀的 proxy ,它们在作为统一流量入口的同时也提供了一些非常实用的功能,如数据 sharding 。
根据一定规则使对应的key落到集群的不同节点上,下边简单介绍一下常见的redis proxy与分片的算法逻辑:
3.1 Modula 根据算法 + 取模存取
通过算法对key进行取模,决定最终需要在哪个节点上进行存取。
- 缺点:可能会出现数据分布节点不均匀的情况,机器扩缩容时需要调整取模策略 3.2 Random 随机存取
3.2 Random 随机存取
作为消息队列使用时候,可以将多个Redis实例组成Topic,生产者存入(lpush)数据,消费者消费(rpop)
- 缺点:可能会出现数据分布节点不均匀的情况
3.3 Ketama 一致性哈希
一致哈希算法是对一组数进行取模运算的结果值组织成一个圆环,就像钟表一样,它可以被想象成带有60个刻度的圆,这个圆环被称为哈希环。
在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。
一致性哈希解决了简单哈希算法在分布式哈希表中存在的动态伸缩等问题。
- 优点:增加节点可以分担其他节点存储压力,因为没有取模过程不会影响其他节点的存储策略
- 缺点:新增节点会造成一小部分数据不能命中(此时应再取附近的2个节点查看数据是否存在)
操作步骤:
- 规划一个哈希环,环上node hash后的槽位为物理节点,其余为虚拟节点
- 将所有物理节点标记起来
- 数据(key)加进来时通过hash过后查询该槽位是否为物理节点,如果是虚拟节点,则找寻离它最近的物理节点后存入
四、Redis Cluster(无中心架构)
Redis Cluster没有使用一致性hash, 而是引入了哈希槽的概念。每一台实例都会分配对应的槽位,自带了算法与集群内所有槽位的记录,所以每一台都是主。
客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点。简单的说就是每一个节点的组成都是:数据+路由
- 优点:扩缩容方便,Redis自带了工具与脚本对于Redis cluster架构也有很好的支持
- 缺点:客户端连接直接压在了实例自身(可以在上层增加 proxy),删除重定向也会造成过多的请求转发与处理流程
为了方便理解,下边通过图解进行说明:
五、其他
当使用Redis cluster架构时候:
- 涉及多个key的操作通常不会被支持。例如不能对两个集合求交集,因为他们可能被存储到不同的Redis实例(KEYS *、WATCH、MULTI...)
- 同时操作多个key,则不能使用Redis事务