去中心Redis-Cluster规范(一)-主要特性和设计依据

7 篇文章 0 订阅
6 篇文章 0 订阅

去中心Redis-Cluster规范(一)

本文翻译自官方文档

主要特性和设计依据

Redis-Cluster目标

Redis-Cluster是redis的分布式实现,设计目标如下(按重要程度排序):

  • 高性能可以线性扩展到1000个节点.没有代理节点,不需要在执行多个值的合并操作,使用异步复制.
  • 可接受的’写’安全性.系统尽最大努力保存连接在大多数节点的客户端的写操作.通常被确认的写操作只有小概率可能丢失.但是对于连接在少数节点上的客户端,概率会比较大.(这部分是说在发生分区时的对写操作的处理情况)
  • 可用性: 发生分区1后,如果大多数主节点可达且每个不再可达的主节点至少有一个从节点可达.另外使用副本迁移特性,没有从节点的主节点可以从有多个从节点的主节点接收一个从节点.

实现子集

Redis-Cluster实现了所有非分布式Redis的单键命令.负责的多键操作,例如集合类型的交集并集,只要所有的键都属于相同的节点,也是被支持的.

Redis-Cluster实现了称为hash tags的概念,可以用来强制一些键被存储在相同的节点上.然而,在执行人工重哈希期间,多键操作坑变为不可用一段时间,单键操作则一直可用.

Redis-Cluster不像独立的Redis那样支持多数据库.仅仅支持数据库0且不支持SELECT命令.

Redis-Cluster协议中的客户端和服务端角色

在Redis-Cluster中节点负责保存数据,维护集群的众泰,包括将键映射到正确的节点.集群节点也可以自动发现其他的节点,检测到不工作的节点.为了但故障发生时可以继续执行操作,可以按需将从节点升级为主节点.

为了实现他们的任务所有的集群节点通过TCP总线和二进制协议互相连接,这被称为Redis Cluster Bus.每个节点使用集群总线与集群中的其他节点进行连接.节点使用流言协议来传播集群的相关信息以发现新节点,发送ping数据包来确认所有的节点正常工作,发送集群消息来指示特别情况.集群总线也被用来跨越整个集群传播Pub/Sub消息,用户发起的是故障转移操作也需要通过集群总线执行.(人工故障转移不是由Redis-Cluster检测的,而是由系统管理员直接发起的)

因为集群节点不能代理请求,客户端可能会被重定向到其它的节点,通过使用重定向错误MOVED-ASK.理论上客户端不需要发送请求给集群中所有的节点,按需重定向即可,所以客户端不需要保存集群的状态.然而客户端也可以以一种敏感的方式缓存键和节点的关系来提升性能.

写安全性

Redis-Cluster在节点之间使用异步复制,并且最后恢复获胜暗含了合并功能.这意味着最后被选举出的主数据集最终替换所有其他的副本.当发生分区时,总是有一个时间窗口可能丢失写操作.而且这些时间窗口对于连接在大多数主节点(多数派)和少数主节点上(少数派)的客户端非常不同.

对比连接在少数节点上的客户端,Redis-Cluster会更努力保存连接在多数主节点上的客户端的写操作.以下实例场景会导致多数派已经接收到了确认的写操作在节点故障过程中丢失.

  1. 一个写操作可能到达了一个主节点,但即使这个主节点已经回复了客户端,这个写操作可能还没有通过异步复制传播给从节点.如果主节点在写操作到达所有的从节点前死掉,且主节点在一个足够长的时间周期内(足够它的一个从节点升级为主节点)依然不可达,则这个写操作将永远丢失.主节点在试图回复确认客户端的写操作时突然发生故障,且几乎同时正在传播写操作的从节点也发生故障,大体上讲这种情况是非常难发生的.但这确实是一种现实的故障模式.
  2. 另外一个理论上可能导致写操作丢失的故障模式如下:
    • 主节点由于发生分区不可达
    • 它的一个从节点执行故障转移替换了它
    • 过了一会儿它可能又变得可达了
    • 一个缓存了过期路由表的客户端可能在旧的主节点被集群变为新主的从节点之前向其继续发送写操作.

第二种失败模式不太可能发生,因为一个主节点如果长时间无法与其他大多数主节点通信,这个时间长到执行故障转移,则这个主节点不会再接受写操作.并且当分区修复后,写操作依然会被拒绝一小会以允许其他的节点知晓配置变更.这个失败模式同时还要求客户端的路由表没有被更新.

少数派的写操作丢失会有一个比较大的时间窗口.Redis-Cluster会丢失大量的少数派的写操作,当少数派的主节点在多数侧被恢复时.

具体来说,一个需要被从节点替换的主节点必须被多数主节点不可达的时间至少到NODE_TIMEOUT,所以如果分区在这个时间之前被修复了,不会有写操作丢失.当分区持续了超过NODE_TIMEOUT,所有到此刻的少数派的写操作可能会丢失.然而Redis-Cluster的少数派主节点无法与多数主节点通信的时间超过NODE_TIMEOUT将立即拒绝写操作,所以NODE_TIMEOUT是最大的时间窗口,超过NODE_TIME之后少数派主节点将不在可用,因此不会有写操作被接受或丢失.

可用性

发生分区时Redis-Cluster的少数部分节点会不可用.在多数节点侧(有大多数的主节点,对于每个不可达的主节点有至少一个从节点),集群将在NODE_TIMEOUT再加上几秒钟(用来做从节点选举和替换它的主节点,故障转移通常需要1到2秒执行)后恢复可用.

这意味着Redis-Cluster被设计为可以容忍一部分节点故障,但是对于需要在大型的网络分割时保持可用性的应用程序来说,不是一个合适的解决方案.

例如在一个集群中有N个主节点,每个主节点有一个从节点.发生分区时一个节点被分割出去,集群的多数节点侧保持可用,当两个节点被分割出去时有1-(1/(N*2-1))的可能性保持可用.当第一个节点故障后我们剩下总共N*2-1个节点,且其中为一个没有从节点的主节点故障的可能性是1(N*2-1).

多亏了Redis-Cluster的副本迁移特性,集群的可用性在许多现实场景中获得改进.因为多余的副本会迁移给孤立的主节点(没有任何副本的主节点).这样在每次成功处理节点故障后,集群会重现配置从节点以更好的对抗下次故障.

性能

在Redis-Cluster中节点不会代理命令到负责指定键的节点,但是他们会重定向客户端到服务于指定部分键空间的节点.

一旦客户端获得了最新的集群节点信息以及那个节点服务那个键子集的信息,正常的操作客户端可以直接与正确的节点通信来发送命令.

由于使用异步复制,节点不需要等待其他节点的写确认(除非显式使用WAIT命令)

并且由于多建命令仅被限制为使用相近的键,数据不会在节点间被移动,除非执行重哈希操作.

正常的操作仅被单独的Redis实例处理.这意味着一个有N个主节点的Redis-Cluster,你可以其他得到的性能为一个独立的Reids实例乘以N,性能线性伸缩.同时每个查询仅执行一次往返,因为客户端通常与节点保持持久连接,所以延迟也与独立的Redis实例相同.

Redis-Cluster的主要目标是提供非常高的性能和扩展性,同时保持弱但合理的数据安全性和可用性.

为什么要避免合并操作

Redis-Cluster设计避免了相同的键值对在多个节点的版本冲突,就像在Redis数据模型一样,这不总是令人期望的.在Redis中值数据通常很大;总是可以看到有数百万个元素的列表和排序集合.同时数据类型也非常复杂.传输和合并这些类型的值会是一个重大的瓶颈,并且可能会需要引入大量的应用端逻辑,附加的内存来存储元数据等等.

这里没有严格的技术限制.CRDTs或者同步复制状态机可以模拟类似Redis的复杂数据类型.然而.这些系统的运行时行为不同于与Redis-Cluster.Redis-Cluster被设计为可以像非集群版本的Redis一样使用.


  1. 可能由于网络问题导致部分节点直接不能互相访问,集群节点被分割为两个部分,由于集群主节点总数建议为基数,所以总有一个分区含有更多的节点.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值