redis系列(八)—集群

redis系列(八)—集群

前言

大家好,牧码心今天给大家推荐一篇redis系列(八)—集群的文章,在实际工作中有很多应用场景,希望对你有所帮助。内容如下:

  • 概述
  • 集群搭建
  • 集群工作原理
  • 集群数据结构
  • 访问集群方式
  • 集群实践

概述

  • 什么是集群
    Redis集群是Redis的分布式解决方案,在3.0版本后推出,有效地解决了Redis分布式方面的需求。集群由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制。
  • 集群作用
    • 高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。
    • 负载均衡:集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力;

集群搭建

下面将搭建一个简单的集群:共6个节点,3主3从。方便起见:所有节点在同一台服务器上,以端口号进行区分;配置从简。3个主节点端口号:7000/7001/7002,对应的从节点端口号:8000/8001/8002。
集群的搭建有两种方式:(1)手动执行Redis命令,一步步完成搭建;(2)使用Ruby脚本搭建。二者搭建的原理是一样的,只是Ruby脚本将Redis命令进行了打包封装;在实际应用中推荐使用脚本方式,简单快捷不容易出错。下面分别介绍这两种方式。
手动执行Redis命令搭建集群
此方式可以理解为以下几部:启动节点-> 节点握手—>分配槽->指定主从关系;

  • 启动节点
    集群节点的启动仍然是使用redis-server命令,但需要使用集群模式启动。下面是7000节点的配置文件(只列出了节点正常工作关键配置,其他配置(如开启AOF)可以参照单机节点进行):
#redis-7000.conf
port 7000
cluster-enabled yes
cluster-config-file "node-7000.conf"
logfile "log-7000.log"
dbfilename "dump-7000.rdb"
daemonize yes

其中的cluster-enabled和cluster-config-file是与集群相关的配置。

  • cluster-enabled yes:Redis实例可以分为单机模式(standalone)和集群模式(cluster);cluster-enabled yes可以启动集群模式。在单机模式下启动的Redis实例,如果执行info server命令,可以发现redis_mode一项为standalone,如下图所示:
    单机模式
    集群模式下的节点,其redis_mode为cluster,如下图所示:
    集群模式
  • cluster-config-file:该参数指定了集群配置文件的位置。每个节点在运行过程中,会维护一份集群配置文件;每当集群信息发生变化时(如增减节点),集群内所有节点会将最新信息更新到该配置文件;当节点重启后,会重新读取该配置文件,获取集群信息,可以方便的重新加入到集群中。也就是说,当Redis节点以集群模式启动时,会首先寻找是否有集群配置文件,如果有则使用文件中的配置启动,如果没有,则初始化配置并将配置保存到文件中。集群配置文件由Redis节点维护,不需要人工修改。
    编辑好配置文件后,使用redis-server命令启动该节点:
redis-server redis-7000.conf

节点启动以后,通过cluster nodes命令可以查看节点的情况,如下图所示。
节点的情况
其中返回值第一项表示节点id,由40个16进制字符串组成,节点id与 主从复制 一文中提到的runId不同:Redis每次启动runId都会重新创建,但是节点id只在集群初始化时创建一次,然后保存到集群配置文件中,以后节点重新启动时会直接在集群配置文件中读取。
其他节点使用相同办法启动,不再赘述。需要特别注意,在启动节点阶段,节点是没有主从关系的,因此从节点不需要加slaveof配置。

  • 节点握手
    节点启动以后是相互独立的,并不知道其他节点存在;需要进行节点握手,将独立的节点组成一个网络。
    节点握手使用cluster meet {ip} {port}命令实现,例如在7000节点中执行cluster meet hadoop09 7001,可以完成7000节点和7001节点的握手;注意ip使用的是局域网ip而不是localhost或127.0.0.1,是为了其他机器上的节点或客户端也可以访问。此时再使用cluster nodes查看:
    节点握手后状态
    在7001节点下也可以类似查看:
    节点握手后状态7001
    同理,在7000节点中使用cluster meet命令,可以将所有节点加入到集群,完成节点握手:
cluster meet hadoop09 7002
cluster meet hadoop09 8000
cluster meet hadoop09 8001
cluster meet hadoop09 8002

执行完上述命令后,可以看到7000节点已经感知到了所有其他节点:
全部节点握手后状态

  • 分配槽
    在Redis集群中,借助槽实现数据分区,具体原理后文会介绍。集群有16384个槽,槽是数据管理和迁移的基本单位。当数据库中的16384个槽都分配了节点时,集群处于上线状态(ok);如果有任意一个槽没有分配节点,则集群处于下线状态(fail)。

cluster info命令可以查看集群状态,分配槽之前状态为fail:
分配槽之前状态
分配槽使用cluster addslots命令,执行下面的命令将槽(编号0-16383)全部分配完毕:

redis-cli -p 7000 cluster addslots {0..5461}
redis-cli -p 7001 cluster addslots {5462..10922}
redis-cli -p 7002 cluster addslots {10923..16383}

此时查看集群状态,显示所有槽分配完毕,集群进入上线状态:
分配槽的状态

  • 指定主从关系
    集群中指定主从关系不再使用slaveof命令,而是使用cluster replicate命令;参数使用节点id。通过cluster nodes获得几个主节点的节点id后,执行下面的命令为每个从节点指定主节点:
redis-cli -p 8000 cluster replicate d22391d2cbebfcabd3f676df05b063e4af2d6fb3
redis-cli -p 8001 cluster replicate 2f865edddd054a664c27ef50533b48fdb5c3d068
redis-cli -p 8002 cluster replicate b1d180a8c75c6e5f8aef41dc8e40ae31acbd8c2d

此时执行cluster nodes查看各个节点的状态,可以看到主从关系已经建立。
指定主从关系后状态至此,集群搭建完毕。

使用ruby搭建
在{REDIS_HOME}/src目录下可以看到redis-trib.rb文件,这是一个Ruby脚本,可以实现自动化的集群搭建。

  • 安装ruby环境
sudo yum install ruby    # CentOS, Fedora, 或 RHEL 系统sudo apt-get install ruby-full # Debian 或 Ubuntu 系统
  • 启动节点
    与第一种方法中的“启动节点”完全相同。
  • 配置集群
    redis-trib.rb脚本提供了众多命令,其中create用于搭建集群,使用方法如下:
./redis-trib.rb create --replicas 1 hadoop09:7000 hadoop09:7001 hadoop09:7002 hadoop09:8000 hadoop09:8001 hadoop09:8002

其中:–replicas=1表示每个主节点有1个从节点;后面的多个{ip:port}表示节点地址,前面的做主节点,后面的做从节点。使用redis-trib.rb搭建集群时,要求节点不能包含任何槽和数据。
执行创建命令后,脚本会给出创建集群的计划,包含;计划包括哪些是主节点,哪些是从节点,以及如何分配槽。输入yes确认执行计划,脚本便开始按照计划执行。

集群方案设计
设计集群方案,应考虑的因素如下:

  • 高可用:根据故障转移的原理,至少需要3个主节点才能完成故障转移,且3个主节点不应在同一台物理机上;每个主节点至少需要1个从节点,且主从节点不应在一台物理机上;因此高可用集群至少包含6个节点。
  • 请求量:估算应用需要的数据量和总访问量(考虑业务发展,留有冗余),结合每个主节点的容量和能承受的访问量(可以通过benchmark得到较准确估计),计算需要的主节点数量。
  • 冗余性:Redis可以在不影响集群服务的情况下增加节点,因此节点数量适当冗余即可,不用太大。
  • 扩展性:Redis官方给出的节点数量限制为1000,主要是考虑节点间通信带来的消耗。在实际应用中应尽量避免大集群;如果节点数量不足以满足应用对Redis数据量和访问量的要求,可以考虑:业务分割,大集群分为多个小集群;减少不必要的数据;调整数据过期策略等。

集群工作原理

前面已经介绍了集群的搭建方法和设计方案,下面将进一步深入,介绍集群的原理。集群最核心的功能是数据分区,因此首先介绍数据的分区规则;然后介绍集群实现的细节:通信机制和数据结构;最后以cluster meet(节点握手)、cluster addslots(槽分配)为例,说明节点是如何利用上述数据结构和通信机制实现集群命令的。
数据分区方案
数据分区有顺序分区、哈希分区等,其中哈希分区由于其天然的随机性,使用广泛;集群的分区方案便是哈希分区的一种。
哈希分区的基本思路是:对数据的特征值(如key)进行哈希,然后根据哈希值决定数据落在哪个节点。常见的哈希分区包括:哈希取余分区、一致性哈希分区、带虚拟节点的一致性哈希分区等。
衡量数据分区方法好坏的标准有很多,其中比较重要的两个因素是:(1)数据分布是否均匀(2)增加或删减节点对数据分布的影响。由于哈希的随机性,哈希分区基本可以保证数据分布均匀;因此在比较哈希分区方案时,重点要看增减节点对数据分布的影响。

  • 哈希取余分区
    哈希取余分区思路非常简单:计算key的hash值,然后对节点数量进行取余,从而决定数据映射到哪个节点上。该方案最大的问题是,当新增或删减节点时,节点数量发生变化,系统中所有的数据都需要重新计算映射关系,引发大规模数据迁移。

  • 一致性哈希分区
    一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环,如下图所示,范围为0-2^32-1;对于每个数据,根据key计算hash值,确定数据在环上的位置,然后从此位置沿环顺时针行走,找到的第一台服务器就是其应该映射到的服务器。
    一致性哈希分区图
    与哈希取余分区相比,一致性哈希分区将增减节点的影响限制在相邻节点。以上图为例,如果在node1和node2之间增加node5,则只有node2中的一部分数据会迁移到node5;如果去掉node2,则原node2中的数据只会迁移到node4中,只有node4会受影响。
    一致性哈希分区的主要问题在于,当节点数量较少时,增加或删减节点,对单个节点的影响可能很大,造成数据的严重不平衡。还是以上图为例,如果去掉node2,node4中的数据由总数据的1/4左右变为1/2左右,与其他节点相比负载过高。

  • 带虚拟节点的一致性哈希分区
    该方案在一致性哈希分区的基础上,引入了虚拟节点的概念。Redis集群使用的便是该方案,其中的虚拟节点称为槽(slot)。槽是介于数据和实际节点之间的虚拟概念;每个实际节点包含一定数量的槽,每个槽包含哈希值在一定范围内的数据。引入槽以后,数据的映射关系由数据hash->实际节点,变成了数据hash->槽->实际节点
    在使用了槽的一致性哈希分区中,槽是数据管理和迁移的基本单位。槽解耦了数据和实际节点之间的关系,增加或删除节点对系统的影响很小。仍以上图为例,系统中有4个实际节点,假设为其分配16个槽(0-15); 槽0-3位于node1,4-7位于node2,以此类推。如果此时删除node2,只需要将槽4-7重新分配即可,例如槽4-5分配给node1,槽6分配给node3,槽7分配给node4;可以看出删除node2后,数据在其他节点的分布仍然较为均衡。

槽的数量一般远小于2^32,远大于实际节点的数量;在Redis集群中,槽的数量为16384。

下面这张图很好的总结了Redis集群将数据映射到实际节点的过程:
数据映射到槽的过程图
(1)Redis对数据的特征值(一般是key)计算哈希值,使用的算法是CRC16。
(2)根据哈希值,计算数据属于哪个槽。
(3)根据槽与节点的映射关系,计算数据属于哪个节点。

节点通信机制

  • 两个端口
    在哨兵系统中,节点分为数据节点和哨兵节点:前者存储数据,后者实现额外的控制功能。在集群中,没有数据节点与非数据节点之分:所有的节点都存储数据,也都参与集群状态的维护。为此,集群中的每个节点,都提供了两个TCP端口:

普通端口:即我们在前面指定的端口(7000等)。普通端口主要用于为客户端提供服务(与单机节点类似);但在节点间数据迁移时也会使用。
集群端口:端口号是普通端口+10000(10000是固定值,无法改变),如7000节点的集群端口为17000。集群端口只用于节点之间的通信,如搭建集群、增减节点、故障转移等操作时节点间的通信;不要使用客户端连接集群接口。为了保证集群可以正常工作,在配置防火墙时,要同时开启普通端口和集群端口。

  • Gossip协议
    节点间通信,按照通信协议可以分为几种类型:单对单、广播、Gossip协议等。重点是广播和Gossip的对比。
    广播是指向集群内所有节点发送消息;优点是集群的收敛速度快(集群收敛是指集群内所有节点获得的集群信息是一致的),缺点是每条消息都要发送给所有节点,CPU、带宽等消耗较大。
    Gossip协议的特点是:在节点数量有限的网络中,每个节点都“随机”的与部分节点通信(并不是真正的随机,而是根据特定的规则选择通信的节点),经过一番杂乱无章的通信,每个节点的状态很快会达到一致。Gossip协议的优点有负载(比广播)低、去中心化、容错性高(因为通信有冗余)等;缺点主要是集群的收敛速度慢。

  • 消息类型
    集群中的节点采用固定频率(每秒10次)的定时任务进行通信相关的工作:判断是否需要发送消息及消息类型、确定接收节点、发送消息等。如果集群状态发生了变化,如增减节点、槽状态变更,通过节点间的通信,所有节点会很快得知整个集群的状态,使集群收敛。
    节点间发送的消息主要分为5种:meet消息、ping消息、pong消息、fail消息、publish消息。不同的消息类型,通信协议、发送的频率和时机、接收节点的选择等是不同的。
    (1). MEET消息:在节点握手阶段,当节点收到客户端的CLUSTER MEET命令时,会向新加入的节点发送MEET消息,请求新节点加入到当前集群;新节点收到MEET消息后会回复一个PONG消息。
    (2). PING消息:集群里每个节点每秒钟会选择部分节点发送PING消息,接收者收到消息后会回复一个PONG消息。PING消息的内容是自身节点和部分其他节点的状态信息;作用是彼此交换信息,以及检测节点是否在线。PING消息使用Gossip协议发送,接收节点的选择兼顾了收敛速度和带宽成本,具体规则如下:随机找5个节点,在其中选择最久没有通信的1个节点;扫描节点列表,选择最近一次收到PONG消息时间大于cluster_node_timeout/2的所有节点,防止这些节点长时间未更新。
    (3).PONG消息:PONG消息封装了自身状态数据。可以分为两种:第一种是在接到MEET/PING消息后回复的PONG消息;第二种是指节点向集群广播PONG消息,这样其他节点可以获知该节点的最新信息,例如故障恢复后新的主节点会广播PONG消息。
    (4).FAIL消息:当一个主节点判断另一个主节点进入FAIL状态时,会向集群广播这一FAIL消息;接收节点会将这一FAIL消息保存起来,便于后续的判断。
    (5).PUBLISH消息:节点收到PUBLISH命令后,会先执行该命令,然后向集群广播这一消息,接收节点也会执行该PUBLISH命令。

数据结构

节点需要专门的数据结构来存储集群的状态。所谓集群的状态,是一个比较大的概念,包括:集群是否处于上线状态、集群中有哪些节点、节点是否可达、节点的主从状态、槽的分布……
节点为了存储集群状态而提供的数据结构中,最关键的是clusterNode和clusterState结构:前者记录了一个节点的状态,后者记录了集群作为一个整体的状态。
集群节点(clusterNode)
clusterNode结构保存了一个节点的当前状态,包括创建时间、节点id、ip和端口号等。每个节点都会用一个clusterNode结构记录自己的状态,并为集群内所有其他节点都创建一个clusterNode结构来记录节点状态。
下面列举了clusterNode的部分字段,并说明了字段的含义和作用:

typedef struct clusterNode {
    //节点创建时间
    mstime_t ctime;
 
    //节点id
    char name[REDIS_CLUSTER_NAMELEN];
 
    //节点的ip和端口号
    char ip[REDIS_IP_STR_LEN];
    int port;
 
    //节点标识:整型,每个bit都代表了不同状态,如节点的主从状态、是否在线、是否在握手等
    int flags;
 
    //配置纪元:故障转移时起作用,类似于哨兵的配置纪元
    uint64_t configEpoch;
 
    //槽在该节点中的分布:占用16384/8个字节,16384个比特;每个比特对应一个槽:比特值为1,则该比特对应的槽在节点中;比特值为0,则该比特对应的槽不在节点中
    unsigned char slots[16384/8];
 
    //节点中槽的数量
    int numslots;
 
    …………
 
} clusterNode;

除了上述字段,clusterNode还包含节点连接、主从复制、故障发现和转移需要的信息等。

节点状态(clusterState)
clusterState结构保存了在当前节点视角下,集群所处的状态。主要字段包括:

typedef struct clusterState {
 
    //自身节点
    clusterNode *myself;
 
    //配置纪元
    uint64_t currentEpoch;
 
    //集群状态:在线还是下线
    int state;
 
    //集群中至少包含一个槽的节点数量
    int size;
 
    //哈希表,节点名称->clusterNode节点指针
    dict *nodes;
  
    //槽分布信息:数组的每个元素都是一个指向clusterNode结构的指针;如果槽还没有分配给任何节点,则为NULL
    clusterNode *slots[16384];
    …………
     
} clusterState;

除此之外,clusterState还包括故障转移、槽迁移等需要的信息。

访问集群

在集群中,数据分布在不同的节点中,客户端通过某节点访问数据时,数据可能不在该节点中;下面介绍集群是如何处理这个问题的。
redis-cli方式
当节点收到redis-cli发来的命令(如set/get)时,过程如下:

(1)计算key属于哪个槽:CRC16(key) & 16383,集群提供的cluster keyslot命令也是使用上述公式实现,如:
cluster keyslot命令
(2)判断key所在的槽是否在当前节点:假设key位于第i个槽,clusterState.slots[i]则指向了槽所在的节点,如果clusterState.slots[i]==clusterState.myself,说明槽在当前节点,可以直接在当前节点执行命令;否则,说明槽不在当前节点,则查询槽所在节点的地址(clusterState.slots[i].ip/port),并将其包装到MOVED错误中返回给redis-cli。

(3)redis-cli收到MOVED错误后,根据返回的ip和port重新发送请求。

下面的例子展示了redis-cli和集群的互动过程:在7000节点中操作key1,但key1所在的槽9189在节点7001中,因此节点返回MOVED错误(包含7001节点的ip和port)给redis-cli,redis-cli重新向7001发起请求。
MOVED错误
上例中,redis-cli通过-c指定了集群模式,如果没有指定,redis-cli无法处理MOVED错误:

Smart客户端

redis-cli这一类客户端称为Dummy客户端,因为它们在执行命令前不知道数据在哪个节点,需要借助MOVED错误重新定向。与Dummy客户端相对应的是Smart客户端。Smart客户端(以Java的JedisCluster为例)的基本原理:
(1)JedisCluster初始化时,在内部维护slot->node的缓存,方法是连接任一节点,执行cluster slots命令,该命令返回如下所示:
cluster slots命令
(2)此外,JedisCluster为每个节点创建连接池(即JedisPool)。

(3)当执行命令时,JedisCluster根据key->slot->node选择需要连接的节点,发送命令。如果成功,则命令执行完毕。如果执行失败,则会随机选择其他节点进行重试,并在出现MOVED错误时,使用cluster slots重新同步slot->node的映射关系。

下面代码演示了如何使用JedisCluster访问集群(未考虑资源释放、异常处理等):

public static void test() {
   Set<HostAndPort> nodes = new HashSet<>();
   nodes.add(new HostAndPort("hadoop09", 7000));
   nodes.add(new HostAndPort("hadoop09", 7001));
   nodes.add(new HostAndPort("hadoop09", 7002));
   nodes.add(new HostAndPort("hadoop09", 8000));
   nodes.add(new HostAndPort("1hadoop09", 8001));
   nodes.add(new HostAndPort("hadoop09", 8002));
   JedisCluster cluster = new JedisCluster(nodes);
   cluster.close();
}

说明如下:
(1)JedisCluster中已经包含所有节点的连接池,因此JedisCluster要使用单例。

(2)客户端维护了slot->node映射关系以及为每个节点创建了连接池,当节点数量较多时,应注意客户端内存资源和连接资源的消耗。

(3)Jedis较新版本针对JedisCluster做了一些性能方面的优化,如cluster slots缓存更新和锁阻塞等方面的优化,应尽量使用2.8.2及以上版本的Jedis。

集群实践

1.集群伸缩
实践中常常需要对集群进行伸缩,如访问量增大时的扩容操作。Redis集群可以在不影响对外服务的情况下实现伸缩;伸缩的核心是槽迁移:修改槽与节点的对应关系,实现槽(即数据)在节点之间的移动。例如,如果槽均匀分布在集群的3个节点中,此时增加一个节点,则需要从3个节点中分别拿出一部分槽给新节点,从而实现槽在4个节点中的均匀分布。

  • 增加节点
    假设要增加7003和8003节点,其中8003是7003的从节点;步骤如下:

(1)启动节点:方法参见集群搭建

(2)节点握手:可以使用cluster meet命令,但在生产环境中建议使用redis-trib.rb的add-node工具,其原理也是cluster meet,但它会先检查新节点是否已加入其它集群或者存在数据,避免加入到集群后带来混乱。

redis-trib.rb add-node hadoop09:7003 hadoop09 7000
redis-trib.rb add-node hadoop09:8003 hadoop09 7000

(3)迁移槽:推荐使用redis-trib.rb的reshard工具实现。reshard自动化程度很高,只需要输入redis-trib.rb reshard ip:port (ip和port可以是集群中的任一节点),然后按照提示输入以下信息,槽迁移会自动完成:
1.待迁移的槽数量:16384个槽均分给4个节点,每个节点4096个槽,因此待迁移槽数量为4096
2.目标节点id:7003节点的id
3.源节点的id:7000/7001/7002节点的id

(4)指定主从关系:方法参见集群搭建

  • 减少节点
    假设要下线7000/8000节点,可以分为两步:
    (1)迁移槽:使用reshard将7000节点中的槽均匀迁移到7001/7002/7003节点
    (2)下线节点:使用redis-trib.rb del-node工具;应先下线从节点再下线主节点,因为若主节点先下线,从节点会被指向其他主节点,造成不必要的全量复制。
redis-trib.rb del-node hadoop09:7001 {节点8000的id}
redis-trib.rb del-node hadoop09:7001 {节点7000的id}
  • ASK错误
    集群伸缩的核心是槽迁移。在槽迁移过程中,如果客户端向源节点发送命令,源节点执行流程如下:
    槽迁移过程

2.故障转移
集群的实现与哨兵思路类似:通过定时任务发送PING消息检测其他节点状态;节点下线分为主观下线和客观下线;客观下线后选取从节点进行故障转移。

与哨兵一样,集群只实现了主节点的故障转移;从节点故障时只会被下线,不会进行故障转移。因此,使用集群时,应谨慎使用读写分离技术,因为从节点故障会导致读服务不可用,可用性变差。

这里不再详细介绍故障转移的细节,只对重要事项进行说明:

节点数量:在故障转移阶段,需要由主节点投票选出哪个从节点成为新的主节点;从节点选举胜出需要的票数为N/2+1;其中N为主节点数量(包括故障主节点),但故障主节点实际上不能投票。因此为了能够在故障发生时顺利选出从节点,集群中至少需要3个主节点(且部署在不同的物理机上)。

故障转移时间:从主节点故障发生到完成转移,所需要的时间主要消耗在主观下线识别、主观下线传播、选举延迟等几个环节;具体时间与参数cluster-node-timeout有关,一般来说:

故障转移时间(毫秒) ≤ 1.5 * cluster-node-timeout + 1000

cluster-node-timeout的默认值为15000ms(15s),因此故障转移时间会在20s量级。

3.集群的限制及应对方法
由于集群中的数据分布在不同节点中,导致一些功能受限,包括:

(1)key批量操作受限:例如mget、mset操作,只有当操作的key都位于一个槽时,才能进行。针对该问题,一种思路是在客户端记录槽与key的信息,每次针对特定槽执行mget/mset;另外一种思路是使用Hash Tag,将在下一小节介绍。

(2)keys/flushall等操作:keys/flushall等操作可以在任一节点执行,但是结果只针对当前节点,例如keys操作只返回当前节点的所有键。针对该问题,可以在客户端使用cluster nodes获取所有节点信息,并对其中的所有主节点执行keys/flushall等操作。

(3)事务/Lua脚本:集群支持事务及Lua脚本,但前提条件是所涉及的key必须在同一个节点。Hash Tag可以解决该问题。

(4)数据库:单机Redis节点可以支持16个数据库,集群模式下只支持一个,即db0。

(5)复制结构:只支持一层复制结构,不支持嵌套。

4. 参数优化

  • cluster_node_timeout
    cluster_node_timeout参数在前面已经初步介绍;它的默认值是15s,影响包括:
    (1)影响PING消息接收节点的选择:值越大对延迟容忍度越高,选择的接收节点越少,可以降低带宽,但会降低收敛速度;应根据带宽情况和应用要求进行调整。
    (2)影响故障转移的判定和时间:值越大,越不容易误判,但完成转移消耗时间越长;应根据网络状况和应用要求进行调整。

  • cluster-require-full-coverage
    前面提到,只有当16384个槽全部分配完毕时,集群才能上线。这样做是为了保证集群的完整性,但同时也带来了新的问题:当主节点发生故障而故障转移尚未完成,原主节点中的槽不在任何节点中,此时会集群处于下线状态,无法响应客户端的请求。
    cluster-require-full-coverage参数可以改变这一设定:如果设置为no,则当槽没有完全分配时,集群仍可以上线。参数默认值为yes,如果应用对可用性要求较高,可以修改为no,但需要自己保证槽全部分配。

  • redis-trib.rb
    redis-trib.rb提供了众多实用工具:创建集群、增减节点、槽迁移、检查完整性、数据重新平衡等;通过help命令可以查看详细信息。在实践中如果能使用redis-trib.rb工具则尽量使用,不但方便快捷,还可以大大降低出错概率。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值