设为首页 加入收藏

TOP

《Redis设计与实现》学习笔记-集群(一)
2015-11-21 02:00:49 来源: 作者: 【 】 浏览:2
Tags:Redis 设计 实现 学习 笔记 集群

Redis也可通过集群来实现分布式,通过分片进行数据共享,并提供复制和故障转移。当前Redis版本的集群功能还没有正式发布,目前只是一个不稳定的分支,据说快要正式发布了。

添加集群节点

服务器节点通过执行CLUSTER MEET 命令把指定的服务器添加到当前集群中,通过CLUSTER NODES来查询当前集群中的所有节点信息,当cluster-enabled配置选项设成yes时,说明该服务器开启了集群模式,开启集群模式的节点才能被添加到集群。
在执行serverCron函数时,集群节点比单击节点多执行一个clusterCron函数,redis使用clusterNode、clusterLink、clusterState等结构来记录集群信息。
CLUSTER MEET命令实现:

在节点B向节点A发送CLUSTER MEET命令时,节点A服务器通过参数解析出目标服务器B的ip和端口。A为指定的ip和端口节点B创建一个clusterNode结构并且添加到clusterState.nodes字典中,并且发送一条MEET消息到B。B接收到A的MEET消息之后为A创建一个clusterNode结构并把它添加到clusterState.nodes字典中,并且回复PONG消息通知A已经收到了MEET消息。A收到PONG消息之后回复一条PING通知B已经收到了PONG回复,至此握手结束。之后节点A将节点B的消息通过Gossip协议传播给集群中其它节点,让其它节点和B进行握手,最终节点B会被集群中所有节点认识。

键槽

Redis集群通过分片的方式来保存 数据库(集群节点只能使用0号数据库)中的键值对:整个数据库被分成16384(2的14次方)个槽,每个键都属于其中某个槽的一个,计算键所在的槽,通过计算键的CRC-16校验和,把校验和和16383做与运算。当所有槽都有节点处理时,集群处于上线状态(ok),否则处于下线状态(fail)。
clusterNode结构中的slots属性记录了节点处理了哪些槽,numslot属性记录了节点处理槽的个数。slots是一个长度16384的二进制数组,数组中的第i为为1表示i号槽被当前节点处理,为0表示i号不是该节点处理,对该数组的取值和设值复杂度都是O(1)。节点会把slots数组传播给集群中其它节点告知当前节点负责处理的槽。
clusterState.slots记录了集群中所有槽的指派信息,该数组是一个存储clusterNode指针的数组如果slots[i]指向NULL说明该槽尚未被指派给任何节点,如果指向一个clusterNode结构,说明i号槽被指派给了当前clusterNode结构代表的节点。
同时存储clusterNode.slots和clusterState.slots的原因是为了提高某些场景的查询效率,如果不存储clusterNode.slots,那么在把当前节点所处理的槽传播给其它节点时只能挨个遍历clusterState.slots,同样地,如果不存储clusterState.slots,当想知道某个槽被那个节点处理时需要遍历clusterState.nodes所有结构并检查它们的slots数组。
同时clusterState结构中有一个跳跃表属性slots_to_keys来保存槽和键的映射关系,通过这个属性可以很方便实现CLUSTER GETKEYSINSLOT 命令,返回最多count个属于slot的数据库键。
通过执行CLUSTER ADDSLOTS 命令指派槽给当前节点,这个命令接受一个或多个槽作为参数,将所有输入的槽指派给接受该命令的节点负责,这个命令的实现如下:
1、检查参数中的槽是否存在已经被其它节点处理的,如果存在直接返回错误。
2、对i号槽,clusterState.slots[i]设成当前节点对应的clusterNode,并且更新clusterNode的slots数组。

集群中执行命令

1、如果键所在的槽被指派给了当前节点,节点直接执行命令。
2、如果键所在的槽没有指派给当前节点,节点给客户端返回一个MOVED错误,指引客户端转向正确的结点。
3、客户端根据MOVED命令带回的ip和port参数把命令发到目标节点重试。

重新分片

集群可以通过重新分片操作将任意已指派给某个节点的槽改为指向另外一个节点,重新分片操作通过集群管理软件redis-trib负责执行,步骤如下:
redis-trib对目标节点发送CLUSTER SETSLOT IMPORTING 命令,让目标节点准备好从源节点导入属于槽slot的键值对。redis-trib对源节点发送CLUSTER SETSLOT MIGRATING 命令,让源节点准备好将属于槽slot的键值对迁移到目标节点。redis-trib向源节点发送CLUSTER GETKEYSINSLOT 命令,获得最多count个属于槽slot的键值对。对步骤3获得的每个键名,redis-trib都想源节点发送一个MIGRATE 0 命令,将被选中的键原子地从源节点迁移到目标节点。重复步骤3、4,直到源节点保存的所有属于槽slot的键值对都被迁移至目标节点为止。redis-trib向集群中任意一个节点发送CLUSTER SETSLOT NODE ,将槽slot指派给目标节点,这一指派消息会通过消息发送至整个集群,最终集群中所有节点都会直到槽slot已经指派给了目标节点。 如果重新分片涉及到多个槽,那么在redis-trib上重复上面过程。
clusterState结构中定义了clusterNode* importing_slots_from[16384]记录当前节点正在从其它节点导入的槽,如果importing_slots_from[i]为不为NULL,表示i号槽正在被当前节点导入,它指向的clusterNode代表i号槽的源节点。
clusterState结构中的clusterNode* migrating_slots_to[16384]数组记录了当前节点正在迁移至其它节点的槽,如果migrating_slots_to[i]不为NULL,说明当前节点正在迁移i号槽到目标节点,指向的clusterNode结构代表了目标节点。

ASK错误

在重新分片的过程中,当客户端向源节点发送一个数据库键有关的命令时,并且键所在的槽正在被迁移:
源节点在本节点的数据库中查找指定的键,如果找到直接执行客户端发送的命令。如果找不到,说明键已经被迁移到目标节点,源节点向客户端返回一个ASK错误,指引客户端转向目标节点。客户端执行ASKING命令道目标节点,目标节点接收到ASKING命令之后会打开REDIS_ASKING标识。客户端重新之前发送的命令道目标节点。 ASK和MOVED的区别:
MOVED错误表示当前节点不是当前键所在槽的处理节点,之后客户端每次遇到关于该槽的命令请求时应该直接将请求按发送至MOVED所指向的结点。ASK错误是临时的,客户端遇到ASK错误之后,只是本次请求临时转向ASK指定的节点,下次请求时还是继续访问最开始访问的节点。

复制与故障转移

可以给集群中的主节点设置从节点,从节点复制主节点,当主节点下线之后,集群推选出一个从节点作为新的主节点来处理槽。通过执行CLUSTER
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇2013access如何创建表和关系 下一篇SSH系列-数据库乱码

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: