槽道原理
创建三个主节点,最终各有一个从节点的redis-cluster 的分布式高可用结构,现在各个节点之间两两互联,三个 主节点分配的槽道数分别为A(05460)B(546110922) C(10923~16383)
代码语言:javascript复制[root@10-42-63-188 redis-3.2.11]# redis-cli -c -p 8000
127.0.0.1:8000> cluster nodes
fffc2a05d33cbab2d92779c45ba10b5cd53f7111 10.42.63.188:8005 slave 8f17409bf2c15767e985ab73cbd92f0db02ee02d 0 1572956185271 6 connected
cddb2fe48090bfc02b634b8ff308c494f9e8efdb 10.42.63.188:8000 myself,master - 0 0 1 connected 0-5460
b6226b81df82ac1a129678f9a835d76cb9c47496 10.42.63.188:8003 slave cddb2fe48090bfc02b634b8ff308c494f9e8efdb 0 1572956183266 4 connected
5e45c7119410d94cd96a39e3c5a27e10c69551be 10.42.63.188:8004 slave d91b43dd7a341b312771d3010bfd2cf13da2d58e 0 1572956187275 5 connected
8f17409bf2c15767e985ab73cbd92f0db02ee02d 10.42.63.188:8002 master - 0 1572956184268 3 connected 10923-16383
d91b43dd7a341b312771d3010bfd2cf13da2d58e 10.42.63.188:8001 master - 0 1572956186273 2 connected 5461-10922
在A的客户端执行set name jiangmingyang,Key值name经过hash取模运算得到5798 5798不在A的槽道管理范围内,因为分片之间两两互联A节点上记录这B,C节点的 信息,识别5798在B的管理范围内,所以向A的客户端重定向到了B,B判断5798在自己 的槽道管理范围内将key-value保存到了B节点。
代码语言:javascript复制127.0.0.1:8000> set name jiangmingyang
-> Redirected to slot [5798] located at 10.42.63.188:8001
OK
10.42.63.188:8001>
槽道原理的两个细节:
a.每个节点获取数据key值后计算槽道号,是如何判断 所属权的?
代码语言:javascript复制每个分片对象都有一个由2048个元素组成的byte数组
的二进制序列位,也就是16384个二进制比特位,key
值经过hash取模运算得到一个0~16383之间的数字
分片对象进行移位运算拿到对应位数的数字,如果
是1,归自己管理,如果是0,根据共享的节点信息
判断结果槽道的所属分片。
例:key值name经过hash取模运算为5798,A节点在
二进制位序列中右移5797位然后与1做保真运算(&1)
得到5798位的数字为0,5798号的槽道管理权为false。
b.当节点判断所属权为false,如何获取正确的节点信息
代码语言:javascript复制集群经过通信之后,形成了一个完全一样统一的索引数组
每一个元素值都是一个记录对应槽道管理权节点的引用的
变量,当节点判断所属权为false,根据索引数组寻找对应
的节点即可。
为什么是16384个槽道?
代码语言:javascript复制byte数组元素2048个,占用内存空间,数据空间2KB;刚好是
redis通信消息头的大小,每次通信过程传输二进制值时,
只需要传一次.
模拟槽道位序列判断所属权算法
代码语言:javascript复制@Test
public void test01() {
/*
* byte a = 127; // 0111 1111 // 0123 4567
* System.out.println(Integer.toBinaryString(a)); for (int i = 0; i < 8; i ) {
* // 0右移7位 1(01)右移6位与1或运算拿到1号槽道的管理权 int result = (a >> (7 - i))&1;
* System.out.println(i "号槽道的管理权为 " (result == 1 ? true : false)); }
*/
byte[] bt = new byte[];
bt[] = ;
bt[] = ;
bt[] = ;
int count = ;
for (int i = ; i < bt.length; i ) {
for (int j = ; j < ; j ) {
int result = (bt[i] >> ( - j))&;
System.out.println(count "号槽道的管理权为 " (result == ? true : false));
}
}
}