Nuclear是一个分布式的Key-Value存储系统,那么key对应的数据分布在什么节点上,需要遵守一定的规则。熟悉MemecachedClient的同学一定清楚一致性Hash的应用,没错,HashRing就是我们的不二选择。在Nuclear中,数据分布在0~2的HashRing上,Nuclear集群初始化的时候,根据节点数均分整个Hash Ring。
在N=3时,A,B,C三个节点的配置就是系统需要的最少节点了。Nuclear中,顺时针的开始值和结束值确定一个分区管理的数据范围,同时规定分区的范围左开右闭。因此,如上图,我们记录A,B,C分别管理的分区范围是:
A {[c,a],[b, c],[a,b]}
B {[a,b],[c,a],[b,c]}
C {[b,c],[a,b],[c,a]}
可以看出,A处理管理自己的分区数据外,还会把自己管理的数据顺时针往前复制到2(N-1)个节点中。
Nuclear增加节点时需要制定目标节点的名称,即增加的节点是用来分担目标节点的负载的。这点不同于Dynamo的分区策略,节点增加的时候会均衡的从现有的节点窃取分区,Nuclear中增加的节点只会影响到邻近的三个节点。
记录N,A,B,C管理的分区如下:
N {[c,n],[b,c],[a,b]}
A {[n,a],[c,n],[b,c]}
B {[a,b],[n,a],[c,n]}
C {[b,c],[a,b],[n,a]}
Nuclear的分区管理模块将自动的计算出需要同步到N上的数据:
A [a,b] => N
B [b,c] => N
C [c,n] => N
不难明白,其实就是把A,B,C不再需要的数据挪给新的节点了。删、替换节点原理大同小异,不再冗述。
Nuclear提供服务器端路由策略,Client的请求随机落在Node节点上,由接收到请求的节点处理后续的逻辑。相对于Client端路由来说,优点是Client无需知道Nuclear集群元数据,易于维护;缺点是会造成一定程度的延时,不过我们的测试结果显示延时在可接受范围之内。
两个设计上的Tips贡献给大家: