当前位置: 首页 > news >正文

俄罗斯外贸常用网站无锡网站建设 app 微信

俄罗斯外贸常用网站,无锡网站建设 app 微信,网站建设公司名字,网站开发自学还是培训前言 在前面的文章中#xff0c;已经介绍了Redis的几种高可用技术#xff1a;持久化、主从复制和哨兵#xff0c;但这些方案仍有不足#xff0c;其中最主要的问题是存储能力受单机限制#xff0c;以及无法实现写操作的负载均衡。 Redis集群解决了上述问题#xff0c;实…前言 在前面的文章中已经介绍了Redis的几种高可用技术持久化、主从复制和哨兵但这些方案仍有不足其中最主要的问题是存储能力受单机限制以及无法实现写操作的负载均衡。 Redis集群解决了上述问题实现了较为完善的高可用方案。本文将详细介绍集群主要内容包括集群的作用集群的搭建方法及设计方案集群的基本原理客户端访问集群的方法以及其他实践中需要的集群知识集群扩容、故障转移、参数优化等 一、集群的作用 集群即Redis Cluster是Redis 3.0开始引入的分布式存储方案。 集群由多个节点(Node)组成Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点只有主节点负责读写请求和集群信息的维护从节点只进行主节点数据和状态信息的复制。 集群的作用可以归纳为两点 1、数据分区数据分区(或称数据分片)是集群最核心的功能。 集群将数据分散到多个节点一方面突破了Redis单机内存大小的限制存储容量大大增加另一方面每个主节点都可以对外提供读服务和写服务大大提高了集群的响应能力。 Redis单机内存大小受限问题在介绍持久化和主从复制时都有提及例如如果单机内存太大bgsave和bgrewriteaof的fork操作可能导致主进程阻塞主从环境下主机切换时可能导致从节点长时间无法提供服务全量复制阶段主节点的复制缓冲区可能溢出……。 2、高可用集群支持主从复制和主节点的自动故障转移与哨兵类似当任一节点发生故障时集群仍然可以对外提供服务。 本文内容基于Redis 3.0.6。 二、集群的搭建 这一部分我们将搭建一个简单的集群共6个节点3主3从。方便起见所有节点在同一台服务器上以端口号进行区分配置从简。3个主节点端口号7000/7001/7002对应的从节点端口号8000/8001/8002。 集群的搭建有两种方式1手动执行Redis命令一步步完成搭建2使用Ruby脚本搭建。二者搭建的原理是一样的只是Ruby脚本将Redis命令进行了打包封装在实际应用中推荐使用脚本方式简单快捷不容易出错。下面分别介绍这两种方式。 1. 执行Redis命令搭建集群 集群的搭建可以分为四步1启动节点将节点以集群模式启动此时节点是独立的并没有建立联系2节点握手让独立的节点连成一个网络3分配槽将16384个槽分配给主节点4指定主从关系为从节点指定主节点。 实际上前三步完成后集群便可以对外提供服务但指定从节点后集群才能够提供真正高可用的服务。 1启动节点 集群节点的启动仍然是使用redis-server命令但需要使用集群模式启动。下面是7000节点的配置文件只列出了节点正常工作关键配置其他配置(如开启AOF)可以参照单机节点进行 1 2 3 4 5 6 7 #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 yesRedis实例可以分为单机模式(standalone)和集群模式(cluster)cluster-enabled yes可以启动集群模式。在单机模式下启动的Redis实例如果执行info server命令可以发现redis_mode一项为standalone如下图所示 集群模式下的节点其redis_mode为cluster如下图所示 cluster-config-file该参数指定了集群配置文件的位置。每个节点在运行过程中会维护一份集群配置文件每当集群信息发生变化时如增减节点集群内所有节点会将最新信息更新到该配置文件当节点重启后会重新读取该配置文件获取集群信息可以方便的重新加入到集群中。也就是说当Redis节点以集群模式启动时会首先寻找是否有集群配置文件如果有则使用文件中的配置启动如果没有则初始化配置并将配置保存到文件中。集群配置文件由Redis节点维护不需要人工修改。 编辑好配置文件后使用redis-server命令启动该节点 1 redis-server redis-7000.conf 节点启动以后通过cluster nodes命令可以查看节点的情况如下图所示。 其中返回值第一项表示节点id由40个16进制字符串组成节点id与 主从复制 一文中提到的runId不同Redis每次启动runId都会重新创建但是节点id只在集群初始化时创建一次然后保存到集群配置文件中以后节点重新启动时会直接在集群配置文件中读取。 其他节点使用相同办法启动不再赘述。需要特别注意在启动节点阶段节点是没有主从关系的因此从节点不需要加slaveof配置。 2节点握手 节点启动以后是相互独立的并不知道其他节点存在需要进行节点握手将独立的节点组成一个网络。 节点握手使用cluster meet {ip} {port}命令实现例如在7000节点中执行cluster meet 192.168.72.128 7001可以完成7000节点和7001节点的握手注意ip使用的是局域网ip而不是localhost或127.0.0.1是为了其他机器上的节点或客户端也可以访问。此时再使用cluster nodes查看 在7001节点下也可以类似查看 同理在7000节点中使用cluster meet命令可以将所有节点加入到集群完成节点握手 1 2 3 4 cluster meet 192.168.72.128 7002 cluster meet 192.168.72.128 8000 cluster meet 192.168.72.128 8001 cluster meet 192.168.72.128 8002 执行完上述命令后可以看到7000节点已经感知到了所有其他节点 通过节点之间的通信每个节点都可以感知到所有其他节点以8000节点为例 3分配槽 在Redis集群中借助槽实现数据分区具体原理后文会介绍。集群有16384个槽槽是数据管理和迁移的基本单位。当数据库中的16384个槽都分配了节点时集群处于上线状态ok如果有任意一个槽没有分配节点则集群处于下线状态fail。 cluster info命令可以查看集群状态分配槽之前状态为fail 分配槽使用cluster addslots命令执行下面的命令将槽编号0-16383全部分配完毕 1 2 3 redis-cli -p 7000 cluster addslots {0..5461} redis-cli -p 7001 cluster addslots {5462..10922} redis-cli -p 7002 cluster addslots {10923..16383} 此时查看集群状态显示所有槽分配完毕集群进入上线状态 4指定主从关系 集群中指定主从关系不再使用slaveof命令而是使用cluster replicate命令参数使用节点id。 通过cluster nodes获得几个主节点的节点id后执行下面的命令为每个从节点指定主节点 1 2 3 redis-cli -p 8000 cluster replicate be816eba968bc16c884b963d768c945e86ac51ae redis-cli -p 8001 cluster replicate 788b361563acb175ce8232569347812a12f1fdb4 redis-cli -p 8002 cluster replicate a26f1624a3da3e5197dde267de683d61bb2dcbf1 此时执行cluster nodes查看各个节点的状态可以看到主从关系已经建立。 至此集群搭建完毕。 2. 使用Ruby脚本搭建集群 在{REDIS_HOME}/src目录下可以看到redis-trib.rb文件这是一个Ruby脚本可以实现自动化的集群搭建。 1安装Ruby环境 以Ubuntu为例如下操作即可安装Ruby环境 1 2 apt-get install ruby #安装ruby环境 gem install redis #gem是ruby的包管理工具该命令可以安装ruby-redis依赖 2启动节点 与第一种方法中的“启动节点”完全相同。 3搭建集群 redis-trib.rb脚本提供了众多命令其中create用于搭建集群使用方法如下 1 ./redis-trib.rb create --replicas 1 192.168.72.128:7000 192.168.72.128:7001 192.168.72.128:7002 192.168.72.128:8000 192.168.72.128:8001 192.168.72.128:8002 其中--replicas1表示每个主节点有1个从节点后面的多个{ip:port}表示节点地址前面的做主节点后面的做从节点。使用redis-trib.rb搭建集群时要求节点不能包含任何槽和数据。 执行创建命令后脚本会给出创建集群的计划如下图所示计划包括哪些是主节点哪些是从节点以及如何分配槽。 输入yes确认执行计划脚本便开始按照计划执行如下图所示。 至此集群搭建完毕。 3. 集群方案设计 设计集群方案时至少要考虑以下因素 1高可用要求根据故障转移的原理至少需要3个主节点才能完成故障转移且3个主节点不应在同一台物理机上每个主节点至少需要1个从节点且主从节点不应在一台物理机上因此高可用集群至少包含6个节点。 2数据量和访问量估算应用需要的数据量和总访问量(考虑业务发展留有冗余)结合每个主节点的容量和能承受的访问量(可以通过benchmark得到较准确估计)计算需要的主节点数量。 3节点数量限制Redis官方给出的节点数量限制为1000主要是考虑节点间通信带来的消耗。在实际应用中应尽量避免大集群如果节点数量不足以满足应用对Redis数据量和访问量的要求可以考虑(1)业务分割大集群分为多个小集群(2)减少不必要的数据(3)调整数据过期策略等。 4适度冗余Redis可以在不影响集群服务的情况下增加节点因此节点数量适当冗余即可不用太大。 三、集群的基本原理 上一章介绍了集群的搭建方法和设计方案下面将进一步深入介绍集群的原理。集群最核心的功能是数据分区因此首先介绍数据的分区规则然后介绍集群实现的细节通信机制和数据结构最后以cluster meet(节点握手)、cluster addslots(槽分配)为例说明节点是如何利用上述数据结构和通信机制实现集群命令的。 1. 数据分区方案 数据分区有顺序分区、哈希分区等其中哈希分区由于其天然的随机性使用广泛集群的分区方案便是哈希分区的一种。 哈希分区的基本思路是对数据的特征值如key进行哈希然后根据哈希值决定数据落在哪个节点。常见的哈希分区包括哈希取余分区、一致性哈希分区、带虚拟节点的一致性哈希分区等。 衡量数据分区方法好坏的标准有很多其中比较重要的两个因素是(1)数据分布是否均匀(2)增加或删减节点对数据分布的影响。由于哈希的随机性哈希分区基本可以保证数据分布均匀因此在比较哈希分区方案时重点要看增减节点对数据分布的影响。 1哈希取余分区 哈希取余分区思路非常简单计算key的hash值然后对节点数量进行取余从而决定数据映射到哪个节点上。该方案最大的问题是当新增或删减节点时节点数量发生变化系统中所有的数据都需要重新计算映射关系引发大规模数据迁移。 2一致性哈希分区 一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环如下图所示范围为0-2^32-1对于每个数据根据key计算hash值确定数据在环上的位置然后从此位置沿环顺时针行走找到的第一台服务器就是其应该映射到的服务器。 图片来源https://www.cnblogs.com/lpfuture/p/5796398.html 与哈希取余分区相比一致性哈希分区将增减节点的影响限制在相邻节点。以上图为例如果在node1和node2之间增加node5则只有node2中的一部分数据会迁移到node5如果去掉node2则原node2中的数据只会迁移到node4中只有node4会受影响。 一致性哈希分区的主要问题在于当节点数量较少时增加或删减节点对单个节点的影响可能很大造成数据的严重不平衡。还是以上图为例如果去掉node2node4中的数据由总数据的1/4左右变为1/2左右与其他节点相比负载过高。 3带虚拟节点的一致性哈希分区 该方案在一致性哈希分区的基础上引入了虚拟节点的概念。Redis集群使用的便是该方案其中的虚拟节点称为槽slot。槽是介于数据和实际节点之间的虚拟概念每个实际节点包含一定数量的槽每个槽包含哈希值在一定范围内的数据。引入槽以后数据的映射关系由数据hash-实际节点变成了数据hash-槽-实际节点。 在使用了槽的一致性哈希分区中槽是数据管理和迁移的基本单位。槽解耦了数据和实际节点之间的关系增加或删除节点对系统的影响很小。仍以上图为例系统中有4个实际节点假设为其分配16个槽(0-15) 槽0-3位于node14-7位于node2以此类推。如果此时删除node2只需要将槽4-7重新分配即可例如槽4-5分配给node1槽6分配给node3槽7分配给node4可以看出删除node2后数据在其他节点的分布仍然较为均衡。 槽的数量一般远小于2^32远大于实际节点的数量在Redis集群中槽的数量为16384。 下面这张图很好的总结了Redis集群将数据映射到实际节点的过程 图片修改自https://blog.csdn.net/yejingtao703/article/details/78484151 1Redis对数据的特征值一般是key计算哈希值使用的算法是CRC16。 2根据哈希值计算数据属于哪个槽。 3根据槽与节点的映射关系计算数据属于哪个节点。 2. 节点通信机制 集群要作为一个整体工作离不开节点之间的通信。 两个端口 在哨兵系统中节点分为数据节点和哨兵节点前者存储数据后者实现额外的控制功能。在集群中没有数据节点与非数据节点之分所有的节点都存储数据也都参与集群状态的维护。为此集群中的每个节点都提供了两个TCP端口 普通端口即我们在前面指定的端口(7000等)。普通端口主要用于为客户端提供服务与单机节点类似但在节点间数据迁移时也会使用。集群端口端口号是普通端口1000010000是固定值无法改变如7000节点的集群端口为17000。集群端口只用于节点之间的通信如搭建集群、增减节点、故障转移等操作时节点间的通信不要使用客户端连接集群接口。为了保证集群可以正常工作在配置防火墙时要同时开启普通端口和集群端口。 Gossip协议 节点间通信按照通信协议可以分为几种类型单对单、广播、Gossip协议等。重点是广播和Gossip的对比。 广播是指向集群内所有节点发送消息优点是集群的收敛速度快(集群收敛是指集群内所有节点获得的集群信息是一致的)缺点是每条消息都要发送给所有节点CPU、带宽等消耗较大。 Gossip协议的特点是在节点数量有限的网络中每个节点都“随机”的与部分节点通信并不是真正的随机而是根据特定的规则选择通信的节点经过一番杂乱无章的通信每个节点的状态很快会达到一致。Gossip协议的优点有负载(比广播)低、去中心化、容错性高(因为通信有冗余)等缺点主要是集群的收敛速度慢。 消息类型 集群中的节点采用固定频率每秒10次的定时任务进行通信相关的工作判断是否需要发送消息及消息类型、确定接收节点、发送消息等。如果集群状态发生了变化如增减节点、槽状态变更通过节点间的通信所有节点会很快得知整个集群的状态使集群收敛。 节点间发送的消息主要分为5种meet消息、ping消息、pong消息、fail消息、publish消息。不同的消息类型通信协议、发送的频率和时机、接收节点的选择等是不同的。 MEET消息在节点握手阶段当节点收到客户端的CLUSTER MEET命令时会向新加入的节点发送MEET消息请求新节点加入到当前集群新节点收到MEET消息后会回复一个PONG消息。PING消息集群里每个节点每秒钟会选择部分节点发送PING消息接收者收到消息后会回复一个PONG消息。PING消息的内容是自身节点和部分其他节点的状态信息作用是彼此交换信息以及检测节点是否在线。PING消息使用Gossip协议发送接收节点的选择兼顾了收敛速度和带宽成本具体规则如下(1)随机找5个节点在其中选择最久没有通信的1个节点(2)扫描节点列表选择最近一次收到PONG消息时间大于cluster_node_timeout/2的所有节点防止这些节点长时间未更新。PONG消息PONG消息封装了自身状态数据。可以分为两种第一种是在接到MEET/PING消息后回复的PONG消息第二种是指节点向集群广播PONG消息这样其他节点可以获知该节点的最新信息例如故障恢复后新的主节点会广播PONG消息。FAIL消息当一个主节点判断另一个主节点进入FAIL状态时会向集群广播这一FAIL消息接收节点会将这一FAIL消息保存起来便于后续的判断。PUBLISH消息节点收到PUBLISH命令后会先执行该命令然后向集群广播这一消息接收节点也会执行该PUBLISH命令。 3. 数据结构 节点需要专门的数据结构来存储集群的状态。所谓集群的状态是一个比较大的概念包括集群是否处于上线状态、集群中有哪些节点、节点是否可达、节点的主从状态、槽的分布…… 节点为了存储集群状态而提供的数据结构中最关键的是clusterNode和clusterState结构前者记录了一个节点的状态后者记录了集群作为一个整体的状态。 clusterNode clusterNode结构保存了一个节点的当前状态包括创建时间、节点id、ip和端口号等。每个节点都会用一个clusterNode结构记录自己的状态并为集群内所有其他节点都创建一个clusterNode结构来记录节点状态。 下面列举了clusterNode的部分字段并说明了字段的含义和作用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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结构保存了在当前节点视角下集群所处的状态。主要字段包括 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 typedef struct clusterState {     //自身节点     clusterNode *myself;     //配置纪元     uint64_t currentEpoch;     //集群状态在线还是下线     int state;     //集群中至少包含一个槽的节点数量     int size;     //哈希表节点名称-clusterNode节点指针     dict *nodes;        //槽分布信息数组的每个元素都是一个指向clusterNode结构的指针如果槽还没有分配给任何节点则为NULL     clusterNode *slots[16384];     …………       } clusterState; 除此之外clusterState还包括故障转移、槽迁移等需要的信息。 4. 集群命令的实现 这一部分将以cluster meet(节点握手)、cluster addslots(槽分配)为例说明节点是如何利用上述数据结构和通信机制实现集群命令的。 cluster meet 假设要向A节点发送cluster meet命令将B节点加入到A所在的集群则A节点收到命令后执行的操作如下 1)  A为B创建一个clusterNode结构并将其添加到clusterState的nodes字典中 2)  A向B发送MEET消息 3)  B收到MEET消息后会为A创建一个clusterNode结构并将其添加到clusterState的nodes字典中 4)  B回复A一个PONG消息 5)  A收到B的PONG消息后便知道B已经成功接收自己的MEET消息 6)  然后A向B返回一个PING消息 7)  B收到A的PING消息后便知道A已经成功接收自己的PONG消息握手完成 8)  之后A通过Gossip协议将B的信息广播给集群内其他节点其他节点也会与B握手一段时间后集群收敛B成为集群内的一个普通节点 通过上述过程可以发现集群中两个节点的握手过程与TCP类似都是三次握手A向B发送MEETB向A发送PONGA向B发送PING。 cluster addslots 集群中槽的分配信息存储在clusterNode的slots数组和clusterState的slots数组中两个数组的结构前面已做介绍二者的区别在于前者存储的是该节点中分配了哪些槽后者存储的是集群中所有槽分别分布在哪个节点。 cluster addslots命令接收一个槽或多个槽作为参数例如在A节点上执行cluster addslots {0..10}命令是将编号为0-10的槽分配给A节点具体执行过程如下 1)  遍历输入槽检查它们是否都没有分配如果有一个槽已分配命令执行失败方法是检查输入槽在clusterState.slots[]中对应的值是否为NULL。 2)  遍历输入槽将其分配给节点A方法是修改clusterNode.slots[]中对应的比特为1以及clusterState.slots[]中对应的指针指向A节点 3)  A节点执行完成后通过节点通信机制通知其他节点所有节点都会知道0-10的槽分配给了A节点 四、客户端访问集群 在集群中数据分布在不同的节点中客户端通过某节点访问数据时数据可能不在该节点中下面介绍集群是如何处理这个问题的。 1. redis-cli 当节点收到redis-cli发来的命令(如set/get)时过程如下 1计算key属于哪个槽CRC16(key) 16383 集群提供的cluster keyslot命令也是使用上述公式实现如 2判断key所在的槽是否在当前节点假设key位于第i个槽clusterState.slots[i]则指向了槽所在的节点如果clusterState.slots[i]clusterState.myself说明槽在当前节点可以直接在当前节点执行命令否则说明槽不在当前节点则查询槽所在节点的地址(clusterState.slots[i].ip/port)并将其包装到MOVED错误中返回给redis-cli。 3redis-cli收到MOVED错误后根据返回的ip和port重新发送请求。 下面的例子展示了redis-cli和集群的互动过程在7000节点中操作key1但key1所在的槽9189在节点7001中因此节点返回MOVED错误(包含7001节点的ip和port)给redis-cliredis-cli重新向7001发起请求。 上例中redis-cli通过-c指定了集群模式如果没有指定redis-cli无法处理MOVED错误 2. Smart客户端 redis-cli这一类客户端称为Dummy客户端因为它们在执行命令前不知道数据在哪个节点需要借助MOVED错误重新定向。与Dummy客户端相对应的是Smart客户端。 Smart客户端以Java的JedisCluster为例的基本原理 1JedisCluster初始化时在内部维护slot-node的缓存方法是连接任一节点执行cluster slots命令该命令返回如下所示 2此外JedisCluster为每个节点创建连接池(即JedisPool)。 3当执行命令时JedisCluster根据key-slot-node选择需要连接的节点发送命令。如果成功则命令执行完毕。如果执行失败则会随机选择其他节点进行重试并在出现MOVED错误时使用cluster slots重新同步slot-node的映射关系。 下面代码演示了如何使用JedisCluster访问集群(未考虑资源释放、异常处理等) 1 2 3 4 5 6 7 8 9 10 11 12 public static void test() {    SetHostAndPort nodes  new HashSet();    nodes.add(new HostAndPort(192.168.72.128, 7000));    nodes.add(new HostAndPort(192.168.72.128, 7001));    nodes.add(new HostAndPort(192.168.72.128, 7002));    nodes.add(new HostAndPort(192.168.72.128, 8000));    nodes.add(new HostAndPort(192.168.72.128, 8001));    nodes.add(new HostAndPort(192.168.72.128, 8002));    JedisCluster cluster  new JedisCluster(nodes);    System.out.println(cluster.get(key1));    cluster.close(); } 注意事项如下 1JedisCluster中已经包含所有节点的连接池因此JedisCluster要使用单例。 2客户端维护了slot-node映射关系以及为每个节点创建了连接池当节点数量较多时应注意客户端内存资源和连接资源的消耗。 3Jedis较新版本针对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但它会先检查新节点是否已加入其它集群或者存在数据避免加入到集群后带来混乱。 1 2 redis-trib.rb add-node 192.168.72.128:7003 192.168.72.128 7000 redis-trib.rb add-node 192.168.72.128:8003 192.168.72.128 7000 3迁移槽推荐使用redis-trib.rb的reshard工具实现。reshard自动化程度很高只需要输入redis-trib.rb reshard ip:port (ip和port可以是集群中的任一节点)然后按照提示输入以下信息槽迁移会自动完成 待迁移的槽数量16384个槽均分给4个节点每个节点4096个槽因此待迁移槽数量为4096目标节点id7003节点的id源节点的id7000/7001/7002节点的id 4指定主从关系方法参见集群搭建 减少节点 假设要下线7000/8000节点可以分为两步 1迁移槽使用reshard将7000节点中的槽均匀迁移到7001/7002/7003节点 2下线节点使用redis-trib.rb del-node工具应先下线从节点再下线主节点因为若主节点先下线从节点会被指向其他主节点造成不必要的全量复制。 1 2 redis-trib.rb del-node 192.168.72.128:7001 {节点8000的id} redis-trib.rb del-node 192.168.72.128:7001 {节点7000的id} ASK错误 集群伸缩的核心是槽迁移。在槽迁移过程中如果客户端向源节点发送命令源节点执行流程如下 图片来源《Redis设计与实现》 客户端收到ASK错误后从中读取目标节点的地址信息并向目标节点重新发送请求就像收到MOVED错误时一样。但是二者有很大区别ASK错误说明数据正在迁移不知道何时迁移完成因此重定向是临时的SMART客户端不会刷新slots缓存MOVED错误重定向则是(相对)永久的SMART客户端会刷新slots缓存。 2. 故障转移 在 哨兵 一文中介绍了哨兵实现故障发现和故障转移的原理。虽然细节上有很大不同但集群的实现与哨兵思路类似通过定时任务发送PING消息检测其他节点状态节点下线分为主观下线和客观下线客观下线后选取从节点进行故障转移。 与哨兵一样集群只实现了主节点的故障转移从节点故障时只会被下线不会进行故障转移。因此使用集群时应谨慎使用读写分离技术因为从节点故障会导致读服务不可用可用性变差。 这里不再详细介绍故障转移的细节只对重要事项进行说明 节点数量在故障转移阶段需要由主节点投票选出哪个从节点成为新的主节点从节点选举胜出需要的票数为N/21其中N为主节点数量(包括故障主节点)但故障主节点实际上不能投票。因此为了能够在故障发生时顺利选出从节点集群中至少需要3个主节点(且部署在不同的物理机上)。 故障转移时间从主节点故障发生到完成转移所需要的时间主要消耗在主观下线识别、主观下线传播、选举延迟等几个环节具体时间与参数cluster-node-timeout有关一般来说 故障转移时间(毫秒) ≤ 1.5 * cluster-node-timeout 1000 cluster-node-timeout的默认值为15000ms(15s)因此故障转移时间会在20s量级。 3. 集群的限制及应对方法 由于集群中的数据分布在不同节点中导致一些功能受限包括 1key批量操作受限例如mget、mset操作只有当操作的key都位于一个槽时才能进行。针对该问题一种思路是在客户端记录槽与key的信息每次针对特定槽执行mget/mset另外一种思路是使用Hash Tag将在下一小节介绍。 2keys/flushall等操作keys/flushall等操作可以在任一节点执行但是结果只针对当前节点例如keys操作只返回当前节点的所有键。针对该问题可以在客户端使用cluster nodes获取所有节点信息并对其中的所有主节点执行keys/flushall等操作。 3事务/Lua脚本集群支持事务及Lua脚本但前提条件是所涉及的key必须在同一个节点。Hash Tag可以解决该问题。 4数据库单机Redis节点可以支持16个数据库集群模式下只支持一个即db0。 5复制结构只支持一层复制结构不支持嵌套。 4. Hash Tag Hash Tag原理是当一个key包含 {} 的时候不对整个key做hash而仅对 {} 包括的字符串做hash。 Hash Tag可以让不同的key拥有相同的hash值从而分配在同一个槽里这样针对不同key的批量操作(mget/mset等)以及事务、Lua脚本等都可以支持。不过Hash Tag可能会带来数据分配不均的问题这时需要(1)调整不同节点中槽的数量使数据分布尽量均匀(2)避免对热点数据使用Hash Tag导致请求分布不均。 下面是使用Hash Tag的一个例子通过对product加Hash Tag可以将所有产品信息放到同一个槽中便于操作。 5. 参数优化 cluster_node_timeout cluster_node_timeout参数在前面已经初步介绍它的默认值是15s影响包括 1影响PING消息接收节点的选择值越大对延迟容忍度越高选择的接收节点越少可以降低带宽但会降低收敛速度应根据带宽情况和应用要求进行调整。 2影响故障转移的判定和时间值越大越不容易误判但完成转移消耗时间越长应根据网络状况和应用要求进行调整。 cluster-require-full-coverage 前面提到只有当16384个槽全部分配完毕时集群才能上线。这样做是为了保证集群的完整性但同时也带来了新的问题当主节点发生故障而故障转移尚未完成原主节点中的槽不在任何节点中此时会集群处于下线状态无法响应客户端的请求。 cluster-require-full-coverage参数可以改变这一设定如果设置为no则当槽没有完全分配时集群仍可以上线。参数默认值为yes如果应用对可用性要求较高可以修改为no但需要自己保证槽全部分配。 6. redis-trib.rb redis-trib.rb提供了众多实用工具创建集群、增减节点、槽迁移、检查完整性、数据重新平衡等通过help命令可以查看详细信息。在实践中如果能使用redis-trib.rb工具则尽量使用不但方便快捷还可以大大降低出错概率。
http://www.zqtcl.cn/news/120105/

相关文章:

  • 专业的大连网站建设电商网站支付方案
  • 手机如何建设网站首页株洲搜索引擎优化
  • 辉县市建设局网站制作网站站用的软件下载
  • 什么网站广告做多有没有不花钱建设网站的方法
  • 网站开发技术总监面试题五大门户网站分别是
  • 福州自助建设网站网站开发工具蜡笔小新
  • 扬州市住房和城乡建设网站html5 后台网站模板
  • 网站建设与设计意义宜兴做宠物的网站
  • 苏州建设工程人才招聘网信息网站wordpress前端库加速
  • 浙江手机版建站系统信息应用商店下载app
  • 广告投放网站动画设计模板
  • 网站发外链的好处页面跳转 英文
  • 黑链 对网站的影响网页小游戏网站有哪些
  • wordpress 网站卡做百度移动网站排名
  • 金融企业网站整站源码网站需要写哪些内容
  • 重庆做网站的网络公司河北建设厅官方网站八大员考试
  • 网站域名缴费服装企业网站建设现状
  • 南阳建设网站哪家好做金融网站
  • 挖矿网站怎么做域名注册需要多少钱?
  • 哈尔滨制作网站企业各位给推荐个网站
  • 程序员做网站类的网站犯法吗wordpress源码系统下载
  • 西安注册公司在哪个网站国际知名工程咨询公司
  • 重庆市网站备案材料做网站和做新媒体运营
  • 大岭山网站建设公司网站建设需要具备的能力
  • 网站建设接外包流程网上可以报警备案吗
  • 建筑网站接单WordPress文章数据转emlog
  • 海口网络平台网站开发wordpress on lnmp
  • 手机怎么登录自己做的网站免费注册域名网站知乎
  • 万宁市住房和城乡建设局网站网页游戏制作过程的
  • 网站建设批复意见浏览有关小城镇建设的网站 记录