Redis Cluster采用虚拟槽分区,所有的key根据哈希函数映射到0~16383槽内,计算公式:
slot = CRC16(key) & 16383
每个节点负责维护一部分槽以及槽所映射的键值对。
Redis虚拟槽分区的特点,解耦数据与节点之间的关系,简化了节点扩容和收缩难度。但其存在如下限制:
1. key批量操作支持有限。只支持具有相同slot值的key执行批量操作。
2. 事务操作支持有限。只支持同一个节点上的多个key的事务操作。
3. key是数据分区的最小粒度,因为不能讲一个大的键值对象,如hash,list等映射到不同的节点上。
4. 不支持多数据库,单机下的Redis可以支持16个数据库,但集群之只能使用一个数据库空间,即db 0。
5. 复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。
如何手动创建一个Redis Cluster
创建三个目录,分别用于存放数据,配置文件和日志。
mkdir -p /opt/redis/data/
mkdir -p /opt/redis/conf/
mkdir -p /opt/redis/log
编辑配置文件
vim redis_6379.conf
port 6379
daemonize yes
pidfile "/opt/redis/data/redis_6379.pid"
loglevel notice
logfile "/opt/redis/log/redis_6379.log"
dbfilename "dump_6379.rdb"
dir "/opt/redis/data"
appendonly yes
appendfilename "appendonly_6379.aof"
cluster-enabled yes
cluster-config-file /opt/redis/conf/nodes-6379.conf
cluster-node-timeout 15000
为简化起见,这里只贴出了redis的几个关键参数,其中,后面三个参数与Cluster有关。
cp redis_6379.conf redis_6380.conf
cp redis_6379.conf redis_6381.conf
cp redis_6379.conf redis_6382.conf
cp redis_6379.conf redis_6383.conf
cp redis_6379.conf redis_6384.conf
sed -i 's/6379/6380/g' redis_6380.conf
sed -i 's/6379/6381/g' redis_6381.conf
sed -i 's/6379/6382/g' redis_6382.conf
sed -i 's/6379/6383/g' redis_6383.conf
sed -i 's/6379/6384/g' redis_6384.conf
启动所有节点
cd /opt/redis/conf
redis-server redis_6379.conf
redis-server redis_6380.conf
redis-server redis_6381.conf
redis-server redis_6382.conf
redis-server redis_6383.conf
redis-server redis_6384.conf
节点启动后,会在conf目录下创建nodes-xxxx.conf文件,文件中记录了节点ID。
[root@slowtech conf]# ls
nodes-6379.conf nodes-6381.conf nodes-6383.conf redis_6379.conf redis_6381.conf redis_6383.conf
nodes-6380.conf nodes-6382.conf nodes-6384.conf redis_6380.conf redis_6382.conf redis_6384.conf
[root@slowtech conf]# cat nodes-6379.conf
260a27a4afd7be954f7cb4fe12be10641f379746 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
将节点加入到集群中
redis-cli -p 6379 cluster meet 127.0.0.1 6380
redis-cli -p 6379 cluster meet 127.0.0.1 6381
redis-cli -p 6379 cluster meet 127.0.0.1 6382
redis-cli -p 6379 cluster meet 127.0.0.1 6383
redis-cli -p 6379 cluster meet 127.0.0.1 6384
cluster meet命令的流程,以第一条命令为例。
1. 6379节点在收到命令后,会为6380节点创建一个clusterNode结构,并将其添加到自己的clusterState.nodes字典里。接着,6379节点向6380节点发送一条MEET消息。
2. 6380节点在收到6379节点的meet消息后,也会为6379节点创建一个clusterNode结构,并将其添加到自己的clusterSta.nodes字典里。并向6379节点返回一条PONG消息。
3. 6379节点在收到这条PONG消息后,会向6380节点返回一个PING消息。
4 . 6380节点收到6379节点返回的PING消息,知道6379节点已经收到自己返回的PONG消息,握手完成。
之后,6379会将6380的消息通过Gossip协议传播给集群中的其它节点,让其它节点也同6380节点握手,最终,6380节点会被集群中的所有节点认识。
查看当前集群的节点信息
127.0.0.1:6379> cluster nodes
260a27a4afd7be954f7cb4fe12be10641f379746 127.0.0.1:6379@16379 myself,master - 0 1539088861000 1 connected
645438fcdb241603fbc92770ef08fa6d2d4c7ffc 127.0.0.1:6380@16380 master - 0 1539088860000 2 connected
bf1aa1e626988a5a35bc2a837c3923d472e49a4c 127.0.0.1:6381@16381 master - 0 1539088860730 0 connected
5350673149500f4c2fd8b87a8ec1b01651572fae 127.0.0.1:6383@16383 master - 0 1539088861000 4 connected
7dd5f5cc8d96d08f35ff395d05eb30ac199f7568 127.0.0.1:6382@16382 master - 0 1539088862745 3 connected
8679f302610e9ea9a464c247f70924e34cd20512 127.0.0.1:6384@16384 master - 0 1539088862000 5 connected
虽然六个节点已经加入到集群中了,但此时集群仍处于下线状态。
127.0.0.1:6379> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_ping_sent:799
cluster_stats_messages_pong_sent:826
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:1630
cluster_stats_messages_ping_received:826
cluster_stats_messages_pong_received:804
cluster_stats_messages_received:1630
分配槽
将16384个slot平均分配给6379,6380,6381三个节点。
redis-cli -p 6379 cluster addslots {0..5461}
redis-cli -p 6380 cluster addslots {5462..10922}
redis-cli -p 6381 cluster addslots {10923..16383}