Redis作为常用的K-V内存数据库经常被用在大型互联网项目中,作为缓存使用,由于大型互联网项目一般数据量大并且必须保证服务高可用,使用redis一般都是以集群形式来使用,这样带来2点好处:
每个 Redis 集群节点需要两个 TCP 连接打开。正常的 TCP 端口用来服务客户端,例如 6379,加 10000 的端口用作数据端口,在上面的例子中就是 16379。 第二个大一些的端口用于集群总线(bus),也就是使用二进制协议的点到点通信通道。集群总线被节点用 于错误检测,配置更新,故障转移授权等等。客户端不应该尝试连接集群总线端口,而应一直与正常的 Redis 命令端口通信,但是要确保在防火墙中打开了这两个端口,否则 Redis 集群的节点不能相互通信。 命令端口和集群总线端口的偏移量一直固定为 10000。 注意,为了让 Redis 集群工作正常,对每个节点:
Redis 集群没有使用一致性哈希,而是另外一种不同的分片形式,每个键概念上是被我们称为哈希槽 (hash slot)的东西的一部分。 Redis 集群有 16384 个哈希槽,我们只是使用键的 CRC16 编码对 16384 取模来计算一个指定键所属的 哈希槽。 每一个 Redis 集群中的节点都承担一个哈希槽的子集,例如,你可能有一个 3 个节点的集群,其中:
这可以让在集群中添加和移除节点非常容易。例如,如果我想添加一个新节点 D,我需要从节点 A,B, C 移动一些哈希槽到节点 D。同样地,如果我想从集群中移除节点 A,我只需要移动 A 的哈希槽到 B 和 C。 当节点 A 变成空的以后,我就可以从集群中彻底删除它。 因为从一个节点向另一个节点移动哈希槽并不需要停止操作,所以添加和移除节点,或者改变节点持有 的哈希槽百分比,都不需要任何停机时间(downtime)。
架构细节:
node<->slot<->value
redis-cluster 选举:容错
a:如果集群任意 master 挂掉,且当前 master 没有 slave.集群进入 fail 状态,也可以理解成集群的 slot 映 射[0-16383]不完成时进入 fail 状态. ps : redis-3.0.0.rc1 加入 cluster-require-full-coverage 参数,默认关闭, 打开集群兼容部分失败.
b:如果集群超过半数以上 master 挂掉,无论是否有 slave 集群进入 fail 状态.
ps:当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down) 错误
为了当部分节点失效时,或者无法与大多数节点通信时仍能保持可用,Redis 集群采用每个节点拥有 1(主 服务自身)到 N 个副本(N-1 个附加的从服务器)的主从模型。 在我们的例子中,集群拥有 A,B,C 三个节点,如果节点 B 失效集群将不能继续服务,因为我们不再 有办法来服务在 5501-11000 范围内的哈希槽。 但是,如果当我们创建集群后(或者稍后),我们为每一个主服务器添加一个从服务器,这样最终的集群 就由主服务器 A,B,C 和从服务器 A1,B1,C1 组成,如果 B 节点失效系统仍能继续服务。 B1 节点复制 B 节点,于是集群会选举 B1 节点作为新的主服务器,并继续正确的运转。
Redis 集群不保证强一致性。实践中,这意味着在特定的条件下,Redis 集群可能会丢掉一些被系统收 到的写入请求命令。
Redis 集群为什么会丢失写请求的第一个原因,是因为采用了异步复制。这意味着在写期间下面的事情 发生了:
有时候在主服务器事实上没有任何故障的情况下强制一次故障转移是很有用的。例如,为了升级主服务 器节点中的一个进程,可以对其进行故障转移使其变为一个从服务器,这样最小化了对可用性的影响。
Redis 集群支持使用 CLUSTER FAILOVER 命令来手动故障转移,必须在你想进行故障转移的主服务的 其中一个从服务器上执行。
手动故障转移很特别,和真正因为主服务器失效而产生的故障转移要更安全,因为采取了避免过程中数 据丢失的方式,仅当系统确认新的主服务器处理完了旧的主服务器的复制流时,客户端才从原主服务器切 换到新主服务器。
添加一个新节点的过程基本上就是,添加一个空节点,然后,如果是作为主节点则移动一些数据进去, 如果是从节点则其作为某个节点的副本。
两种情况我们都会讨论,先从添加一个新的主服务器实例开始。
两种情况下,第一步要完成的都是添加一个空节点。
我们使用与其他节点相同的配置(端口号除外)在 7006 端口(我们已存在的 6 个节点已经使用了从 7000 到 7005 的端口)上开启一个新的节点,那么为了与我们之前的节点布局一致,你得这么做:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
添加新副本可以通过两种方式执行。最明显的一种方法是再次使用redis cli,但是使用–cluster slave选项,如下所示:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave
请注意,这里的命令行与我们用来添加新主控形状的命令行完全相同,因此我们没有指定要将副本添加到哪个主控形状。在这种情况下,redis cli将在副本较少的主节点中添加新节点作为随机主节点的副本。
但是,可以使用以下命令行指定新副本的目标主机:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
要删除从属节点,只需使用redis cli的del node命令:
redis-cli --cluster del-node 127.0.0.1:7000 ``
第一个参数只是集群中的一个随机节点,第二个参数是要删除的节点的ID。
您也可以用同样的方法删除主节点,但是要删除主节点,它必须为空。如果主节点不为空,则需要将数据从主节点重新硬存到所有其他主节点。
删除主节点的另一种方法是在其一个从属节点上对其执行手动故障转移,并在该节点变为新主节点的从属节点后将其删除。显然,当您想要减少集群中主服务器的实际数量时,这并没有帮助,在这种情况下,需要重新数据分片。
在Redis集群中,只要使用以下命令,就可以随时将从机重新配置为使用不同的主机进行复制:
CLUSTER REPLICATE
但是,有一种特殊的情况是,您希望副本在没有系统管理员帮助的情况下自动从一个主服务器移动到另一个主服务器。副本的自动重新配置称为副本迁移,它能够提高Redis集群的可靠性。
在某些情况下,您可能希望让群集副本从一个主服务器移动到另一个主服务器,原因是通常Redis群集的故障抵抗能力与连接到给定主服务器的副本数量相同。
例如,主节点只有一个从节点,如果主节点和其从节点同时不可用,那么集群将不可用,原因很简单,因为没有其他实例具有该主节点正在服务的哈希槽的副本。然而,虽然网络拆分可能会同时隔离多个节点,但许多其他类型的故障(如单个节点本地的硬件或软件故障)是一类非常显著的故障,不太可能同时发生,因此在每个主节点都有一个从节点的集群中,奴隶在凌晨4点被杀,主人在早上6点被杀。这仍然会导致集群无法再运行。
为了提高集群可用性,可用向主节点添加更多的从节点,但是这样成本就比较高。副本迁移允许向部分主节点添加更多的从节点。例如,你有10个主节点,每个主节点有1个从节点,整个集群就是20个节点。然而,例如你可以向集群添加3个从节点挂到部分主节点上,这样部分主节点就有多于1个的从节点。
对于副本迁移,如果一个主节点没有从节点,那么一个主节点有多个从节点的副本将迁移到孤立的主节点。所以当你的从节点像我们上面的例子一样在凌晨4点宕掉后,另一个从节点将取代它,当主节点在早上5点同样宕掉时,仍然有一个从节点可以被选为主节点,这样集群可以继续运行。
升级从节点很容易,因为您只需要停止该节点并使用更新版本的Redis重新启动它。如果有客户机使用从节点扩展读取,那么如果给定的从节点不可用,它们应该能够重新连接到其他从节点。
升级主服务器要稍微复杂一些,建议的步骤是:
参考