Redis集群(一)

1、简介  

  • redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。redis3.0版本以前只支持单例模式,在3.0版本及之后才支持集群,我这里用的是redis3.0.0版本;
  • redis集群采用P2P模式,是彻底去中心化的,不存在中心节点或者代理节点;
  • redis集群是没有统一的入口的,客户端(client)链接集群的时候链接集群中的任意节点(node)便可,集群内部的节点是相互通讯的(PING-PONG机制),每一个节点都是一个redis实例;
  • 为了实现集群的高可用,即判断节点是否健康(可否正常使用),redis-cluster有这么一个投票容错机制:若是集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
  • 那么如何判断集群是否挂了呢? -> 若是集群中任意一个节点挂了,并且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;
  • 那么为何任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 由于集群内置了16384个slot(哈希槽),而且把全部的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当须要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,而后获得一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪一个节点中。因此一旦某个节点挂了,该节点对应的slot就没法使用,那么就会致使集群没法正常工做。
  • 综上所述,每一个Redis集群理论上最多能够有16384个节点。

2、三种集群模型

  一、主从模型

  在主从复制中,数据库分为两类:主数据库(master)和从数据库(slave)。node

  当slave启动后,主动向master发送SYNC命令。master接收到SYNC命令后在后台保存快照(RDB持久化)和缓存保存快照这段时间的命令,而后将保存的快照文件和缓存的命令发送给slave。slave接收到快照文件和命令后加载快照文件和缓存的执行命令。redis

  为了在主节点子集发生故障或没法与大多数节点通讯时保持可用,Redis Cluster使用主从模型,其中每一个哈希槽具备从1(主节点自己)到N个副本(N个) -1个其余从属节点)。在具备节点A,B,C的示例集群中,若是节点B失败,则集群将没法继续,由于咱们再也不有办法为5501-11000范围内的哈希槽提供服务。算法

  可是,在建立集群(或稍后)时,咱们向每一个主节点添加一个从属节点,以便最终集群由做为主节点的A,B,C和做为从属节点的A1,B1,C1组成,若是节点B发生故障,系统将可以继续。数据库

  节点B1复制B,而且B发生故障,群集会将节点B1提高为新的主节点,并将继续正常运行。缓存

  可是请注意,若是节点B和B1同时失败,则Redis Cluster没法继续运行。安全

  解决问题:服务器

    解决Redis单例下,数据体量大与数据备份形成的性能瓶颈问题,redis cluster 主从模型很好的解决这个问题。能够将读写操做分离到不一样redis实例上,提升系统的吞吐量    网络

  引入新的问题:并发

    一、配置重连问题dom

      不一样的redis实例,须要不一样的ip和端口对应,若是某个实例下线了,须要从新更改配置进行重连

    二、故障转移问题

      若是某个结点故障下线,没法进行故障转移,好比某个master下线,对应的slave结点也只能进行读操做,没法进行写操做,替代不了master的功能。

  特色以下:

  • 主数据库能够进行读写操做,当读写操做致使数据变化时会自动将数据同步给从数据库
  • 从数据库通常都是只读的,而且接收主数据库同步过来的数据
  •  一个master能够拥有多个slave,可是一个slave只能对应一个master
  • slave挂了不影响其余slave的读和master的读和写,从新启动后会将数据从master同步过来
  • master挂了之后,不影响slave的读,但redis再也不提供写服务,master重启后redis将从新对外提供写服务
  • master挂了之后,不会在slave节点中从新选一个master

  缺点以下:

  master节点在主从模式中惟一,若master挂掉,则redis没法对外提供写服务,不具有高可用性。

  二、哨兵模型

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance)。

监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运做正常。 

提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 能够经过 API 向管理员或者其余应用程序发送通知。

自动故障迁移(Automatic failover): 当一个主服务器不能正常工做时, Sentinel 会开始一次自动故障迁移操做, 它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其余从服务器改成复制新的主服务器; 当客户端试图链接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可使用新主服务器代替失效服务器。

解决问题:  

    Sentinel哨兵模式,确实实现自动故障切换。提供稳定的服务,解决主从模型引入的新问题。 

  未解决的问题:

    在哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。

  特色以下:

  • Sentinel能够监控任意多个Master和该Master下的Slaves。(即多个主从模式) 
  • 同一个哨兵下的、不一样主从模型,彼此之间相互独立。
  • Sentinel会不断检查Master和Slaves是否正常。
  • 监控同一个Master的Sentinel会自动链接,组成一个分布式的Sentinel网络,互相通讯并交换彼此关于被监视服务器的信息,在sentinel网络中,只要还有一个sentinel活着,就能够实现故障切换。当只有一个sentinel的时候,若是这个sentinel挂掉了,那么就没法实现自动故障切换了。
  • 故障转移:投票(半数原则),当任何一个Sentinel发现被监控的Master下线时,会通知其它的Sentinel开会,投票肯定该Master是否下线(半数以上,因此sentinel一般配奇数个)。
  • 故障转移:选举,当Sentinel肯定Master下线后,会在全部的Slaves中,选举一个新的节点,升级成Master节点。其它Slaves节点,转为该节点的从节点。 
  • 原Master从新上线,当原Master节点从新上线后,自动转为当前Master节点的从节点。

  三、Redis cluster 集群 

   Redis 3.0 以后版本支持 Redis Cluster 集群,Redis Cluster采用无中心结构,每一个节点保存数据和整个集群状态,每一个节点都和其余全部节点链接。 

     目标:  

  • 高达1000个节点的高性能和线性可扩展性。没有代理,使用异步复制,而且不对值执行合并操做。
  • 可接受的写安全程度:系统尝试(以尽力而为的方式)保留全部来自与大多数主节点链接的客户端的写操做。一般,有一些小窗口,在这些小窗口中,可能会丢失已确认的写入。当客户端位于少数分区中时,丢失已确认写入的Windows更大。
  • 可用性:Redis Cluster可以在大多数主节点可访问且每一个再也不可用的主节点上至少有一个可访问的从节点的分区中生存。并且,经过使用副本迁移,再也不由任何从属复制的主将从一个由多个从属覆盖的主接收一个。

    高性能:

  • 采用了异步复制机制,向某个节点写入数据时,无需等待其它节点的写数据响应。
  • 无中心代理节点,而是将客户端直接重定向到拥有数据的节点。
  • 对于N个 Master 节点的 Cluster ,总体性能理论上至关于单个 Redis 的性能的N倍。

    高可用:

    采用了主从复制的机制,Master 节点失效时 Slave 节点自动提高为 Master 节点。若是 Cluster 中有N个 Master 节点,每一个 Master 拥有1个 Slave 节点,那么这个   Cluster 的失效几率为 1/(2*N-1),可用几率为 1-1/(2*N-1)。

    高可扩展:

    可支持多达1000个服务节点。随时能够向 Cluster 中添加新节点,或者删除现有节点。Cluster 中每一个节点都与其它节点创建了相互链接

    一致性:  

  Redis Cluster没法保证强一致性实际上,这意味着在某些状况下,Redis Cluster可能会丢失系统承认给客户端的写入。

Redis Cluster可能丢失写入的第一个缘由是由于它使用异步复制。这意味着在写入期间会发生如下状况:

    • 您的客户写信给主B。
    • 主B向您的客户答复“肯定”。
    • 主机B将写操做传播到其从机B1,B2和B3。

  B在回复客户端以前不会等待B1,B2,B3的确认,由于这会对Redis形成延迟性的延迟,所以,若是您的客户端写了一些东西,B会确认写,可是在崩溃以前崩溃因为可以将写操做发送到其从属服务器,所以一个从属服务器(未接收到写操做)能够升级为主服务器,从而永远丢失该写操做。

  特色以下:

  • 全部的 Redis 节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  • 节点的fail是经过集群中超过半数的节点检测失效时才生效。
  • 客户端与 Redis 节点直连,不须要中间Proxy层,客户端不须要链接集群全部节点,链接集群中任何一个可用节点便可。
  • Redis Cluster 把全部的物理节点映射到[0-16383] slot(哈希槽) 上(不必定是平均分配),Cluster 负责维护node <-> slot <-> value。
  • Redis 集群预分好 16384 个哈希槽,当须要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384 的值,决定将一个 key 放到哪一个桶中。

3、集群主要组件 

一、密钥分配模型 

  密钥空间被划分为16384个插槽,有效地设置了16384个主节点的群集大小的上限(可是建议的最大节点大小约为1000个节点)。

  群集中的每一个主节点都处理16384个哈希槽的子集。当没有正在进行的集群从新配置时(即哈希槽从一个节点移动到另外一个节点),该集群是稳定的。当群集稳定时,单个哈希槽将由单个节点提供服务(可是,服务节点能够具备一个或多个从属设备,在发生网络分裂或故障的状况下能够替换该从属设备,而且能够用于扩展)可接受过期数据的读取操做)。

  键映射到哈希槽的基本算法HASH_SLOT = CRC16(key) mod 16384

二、键哈希标签 

  哈希标签是一种确保在同一哈希槽中分配多个密钥的方法。这用于在Redis Cluster中实现多键操做。 

  为了实现哈希标签,在某些状况下,密钥的哈希槽以略有不一样的方式计算。若是密钥包含一个“{...}”图案仅之间子 {},以得到散列时隙被散列。可是,因为可能存在屡次出现{}算法由如下规则很好地指定: 

    • 若是键包含一个{字符。
    • 若是有一个}字符的右{
    • AND若是在的第一次出现{和的第一次出现之间存在一个或多个字符}

三、集群节点属性 

  每一个节点在集群中都有惟一的名称。节点名称是160位随机数的十六进制表示形式,是在节点首次启动时得到的(一般使用/ dev / urandom)。节点将其ID保存在节点配置文件中,并将永久使用相同的ID,或者至少在系统管理员未删除节点配置文件或经过CLUSTER RESET命令请求硬重置的状况下使用该ID  

  节点ID用于标识整个集群中的每一个节点。给定节点能够更改其IP地址,而无需也更改节点ID。群集还可以检测IP /端口的更改,并使用在群集总线上运行的八卦协议进行从新配置。 

  节点ID并非与每一个节点关联的惟一信息,而是惟一始终全局一致的信息。每一个节点还具备如下关联的信息集。一些信息与该特定节点的集群配置详细信息有关,而且最终在整个集群中保持一致。某些其余信息(例如上次对节点执行ping操做)则是每一个节点本地的。 

  每一个节点都维护着有关群集中其余节点的如下信息:节点ID,节点的IP和端口,一组标志,若是将节点标志为slave则该节点的主节点是什么?对节点执行ping操做,最后一次接收到pong时,将显示该节点的当前 配置时期(在本规范的后面部分进行说明),连接状态以及最终服务的哈希槽集。 

四、集群总线 

  每一个Redis Cluster节点都有一个额外的TCP端口,用于接收来自其余Redis Cluster节点的传入链接。此端口与用于从客户端接收传入链接的普通TCP端口处于固定偏移量。要得到Redis Cluster端口,应在常规命令端口中添加10000。例如,若是Redis节点正在端口6379上侦听客户端链接,则群集总线端口16379也将打开。

  节点到节点的通讯仅使用群集总线和群集总线协议进行:群集协议是由不一样类型和大小的帧组成的二进制协议。未公开记录集群总线二进制协议,由于它不打算供外部软件设备使用该协议与Redis Cluster节点通讯。可是,您能够经过阅读Redis Cluster源代码中cluster.hcluster.c文件来获取有关集群总线协议的更多详细信息  

五、集群拓扑

  Redis Cluster是一个完整的网格,其中每一个节点都使用TCP链接与其余每一个节点链接。 

  在N个节点的群集中,每一个节点都有N-1个传出TCP链接和N-1个传入链接。 

  这些TCP链接始终保持活动状态,而且不会按需建立。当节点但愿对集群总线中的ping作出回应时,会在等待足够长的时间以将节点标记为不可访问以前进行Pong响应,它将尝试经过从头开始从新链接来刷新与该节点的链接。 

  虽然Redis Cluster节点造成一个完整的网格,可是节点使用八卦协议和配置更新机制以免在正常状况下在节点之间交换太多消息,所以交换的消息数量不是指数级的。 

六、节点握手

  节点始终接受群集总线端口上的链接,即便收到ping节点不受信任,甚至会在收到ping时回复ping。可是,若是不将发送节点视为群集的一部分,则接收节点将丢弃全部其余数据包。 

一个节点仅以两种方式将另外一个节点做为群集的一部分:

    • 节点是否向其显示MEET消息。Meet消息PING消息彻底同样,可是会强制接收者接受该节点做为群集的一部分。只有系统管理员经过如下命令请求节点时,节点才会将MEET消息发送到其余节点

      群集会议IP端口

    • 若是已经受信任的节点将闲聊该节点,则该节点还将另外一个节点注册为群集的一部分。所以,若是A知道B,B知道C,则最终B会向A发送有关C的八卦消息。发生这种状况时,A会将C注册为网络的一部分,并尝试与C链接。

这意味着只要咱们在任何链接图中加入节点,它们最终将自动造成彻底链接图。这意味着群集可以自动发现其余节点,但前提是存在系统管理员强制创建的信任关系。

这种机制使群集更加健壮,但能够防止更改IP地址或其余与网络相关的事件后,不一样的Redis群集意外混合。        

参考连接:

  官网:https://redis.io/topics/cluster-spec 集群规范

相关文章
相关标签/搜索