开始之前我们提出几个问题:
keyHashSlot 函数用来计算给定键应该被分配到哪个槽采用分片取模算法实现节点分配,节点数据存储。
/* --------------cluster.c--------------------------------------------------------------- * Key space handling * -------------------------------------------------------------------------- */ /* We have 16384 hash slots. The hash slot of a given key is obtained * as the least significant 14 bits of the crc16 of the key. * * However if the key contains the {...} pattern, only the part between * { and } is hashed. This may be useful in the future to force certain * keys to be in the same node (assuming no resharding is in progress). */ //我们有16384个哈希槽,将会用crc16得到的最小有效14位作为给定key的哈希槽。 //但是,如果键包含‘{...}’这样的字段,只有在"{“和“}”之间的才会被哈希。这在将来可能有助于将某些键强制放在同一个节点中(假设没有进行重新分片 // 计算给定键应该被分配到哪个槽 unsigned int keyHashSlot(char *key, int keylen) { int s, e; /* start-end indexes of { and } */ for (s = 0; s < keylen; s++) if (key[s] == '{') break; /* No '{' ? Hash the whole key. This is the base case. */ //0x3FFF转化成十进制就是16383 if (s == keylen) return crc16(key,keylen) & 0x3FFF; /* '{' found? Check if we have the corresponding '}'. */ for (e = s+1; e < keylen; e++) if (key[e] == '}') break; /* No '}' or nothing betweeen {} ? Hash the whole key. */ if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF; /* If we are here there is both a { and a } on its right. Hash * what is in the middle between { and }. */ return crc16(key+s+1,e-s-1) & 0x3FFF;
1,可以实现动态节点扩容,缩容。
2,高可用,节点挂掉过后自动选举,数据迁移到存活节点的redis节点。
1,节点数据不同步。
2,端口ip通讯连接失败。
服务器三台配置6381 为主,6382 为从:
服务器 | 192.168.192.138 | 192.168.192.137 | 192.168.192.140 |
端口 | 6381 | 6381 | 6381 |
6382 | 6382 | 6382 |
对应数据存储路径:/data/6381/ /data/6382/
data目录为文件映射卷自动生成的数据。
#端口 port 6381 #设置外部网络连接redis服务 protected-mode no #开启守护进程模式。在该模式下,redis会在后台运行 daemonize yes #pid 标识 pidfile /var/run/redis_6381.pid #开启持久化 appendonly yes #开启集群 cluster-enabled yes #集群节点配置 cluster-config-file nodes-6381.conf #节点超时时间 cluster-node-timeout 15000
#端口 port 6382 #设置外部网络连接redis服务 protected-mode no #开启守护进程模式。在该模式下,redis会在后台运行 daemonize yes #pid 标识 pidfile /var/run/redis_6382.pid #开启持久化 appendonly yes #开启集群 cluster-enabled yes #集群节点配置 cluster-config-file nodes-6382.conf #节点超时时间 cluster-node-timeout 15000
docker run -v /data/6382/data/:/data -v /data/6382/redis.conf:/etc/redis/redis.conf --privileged=true --net host --name redis-6382 -d redis:latest redis-server /etc/redis/redis.conf docker run -v /data/6381/data/:/data -v /data/6381/redis.conf:/etc/redis/redis.conf --privileged=true --net host --name redis-6381 -d redis:latest redis-server /etc/redis/redis.conf
进入到任意一台容器,启动redis命令。
docker exec -it redis-6381 /bin/bash
执行命令:
redis-cli --cluster create 192.168.192.140:6382 192.168.192.140:6381 192.168.192.138:6382 192.168.192.138:6381 192.168.192.137:6382 192.168.192.137:6381 --cluster-replicas 1
报错了:Could not connect to Redis at 192.168.192.139:6381: No route to host 这个问题一般是节点连接不通,查看对应服务器节点主从。
这个错是主机端口没有开放,关闭防火墙搞定
Could not connect to Redis at 192.168.192.140:6381: No route to host
[ERR] Node 192.168.192.140:6381 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
节点数据不同步,删除节点的数据,并且从新flushdb redis库。
清出docker映射卷的配置,重新启动redis 即可。
/data/6381/data
/data/6382/data
看到这个过后说明你的集群是启动成功了,我们写入默认crc64 分片取模算法。16384个卡槽,3台服务器 分别根据卡槽存放数据。数据写入缓存可以实现同步到指定节点,从而实现了redis高可。
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
我在140写了一个 xy_cesi Key 我通过其他服务器查询是拿取到了,写入的缓存数据会自动同步到其他节点上面,如果你发现没有数据实际是正常的情况。
下面是一个真实生产缓存的redis 集群。
docker redis cluster 高可用集群搭建就结束了,后面分享微服务集成redis 高可用集群,创作不易感谢支持!!!