一、概述
Cluster中每个节点都知道其他节点的信息,相互间可以通信(meet),知道每个节点负责哪些槽(slot)。
所有 Redis 节点之间采用 Gossip 协议进行通信,交换维护节点元数据信息。
关于gossip协议的简介请看这篇:032. redis cluster 的核心原理分析:gossip 通信、jedis smart 定位、主备切换
关于redis cluster的数据分布hash slot前面有写过【十九】redis之Cluster数据分布概述(分布式存储系统中,数据分布算法简介)
16384是redis Cluster指定的槽的数量。要为每个节点指派槽,才能正常读写。
redis Cluster有主从复制,每个主节点都有从节点,高可用,分片。
从节点默认不支持读写,如果要对从节点做读写分离需要每个连接用readonly,自己维护从节点的资源池和故障转移。
不建议在从节点做读,直接扩容操作各个主节点。
1.请求流程:
1.客户端向集群中任意一台节点发起请求
2.该节点收命令后首先计算键对应的槽,crc16(key)%16384 = 对应的槽。
3.该节点再根据槽找出所对应的节点,如果节点是自身,则处理键命令。否则回复 MOVED 重定向错误,通知客户端请求正确的节点。
4.如果客户端收到的是MOVED,则客户端自己重新去请求那台对的节点。这个叫客户端路由。
2. 节点回复的MOVED示例
GET user
-MOVED 400 127.0.0.1:6380
意思是,客户端请求了一个节点想要获取key为user的数据,而这条数据没有在这个节点上,这个节点返回MOVED告诉客户端:key为user的数据在槽400上,槽400在IP为127.0.0.1,端口为6380的机器上。
此时需要客户端向127.0.0.1:6380节点发起get user请求
3.客户端可对MOVED和ASK做缓存
1.为了提高效率,客户端可以对MOVED和ASK做缓存。比如第一次请求get user,被重定向到了127.0.0.1:6380,客户端可以记录一下,user这个key对应的槽是400,对应的节点是127.0.0.1:6380,下次再get user的时候就自己直接去请求127.0.0.1:6380机器了,不然每次都重定向一下影响效率
2.如果数据正在迁移中,节点会回复 ASK 重定向异常。格式如下: ( error ) ASK { slot } { targetIP } : { targetPort }。客户端如果收到服务端回复ASK,表示请求的槽和数据正在迁移,此时ASK中带的槽和IP就不要存了,客户端无法知道什么时候迁移完成,只是临时的重定向,客户端不要更新这个 slot 到 Redis 节点的映射缓存。
4.故障转移
1.默认情况下,16384个槽必须要全部都分配给节点,差一个槽没有分配给节点,则整个集群都不可用。执行任何命令都会返回 CLUSTERDOWN Hash slot not served
也就是说:当持有槽的主节点下线后,到它的从节点变成主节点之前,整个集群会不可用!
2.可以将配置cluster-require-full-coverage 设置为 no 。这样当node1主节点故障时只影响它负责槽的相关命令执行,不会让整个集群不可用。
二、搭建
1.原生命令安装
node1 | node2 | node3 | node4 | |
master | Y | Y | ||
slave | slaveof node1 | slaveof node3 |
1.配置开启节点 4台机器
cd /app/redis/config
touch redis-cluster-6379.conf
vi redis-cluster-6379.conf
protected-mode no
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dir /app/redis/data
dbfilename "dump-6379.rdb"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-require-full-coverage no
启动4个节点
cd /app/redis/src
./redis-server /app/redis/config/redis-cluster-6379.conf
2.meet。各节点之间相互meet建立通信
在node1中进行
cd /app/redis/src
./redis-cli -h node1 -p 6379 cluster meet 192.168.2.104 6379
./redis-cli -h node1 -p 6379 cluster meet 192.168.2.106 6379
./redis-cli -h node1 -p 6379 cluster meet 192.168.2.107 6379
3.指派槽
node1和node3是master,由他们两个平分16384个槽
node1 0-8191
node2 8192-16384
node1上执行
./redis-cli -h node1 -p 6379 cluster addslots {0..8191}
node3上执行
./redis-cli -h node3 -p 6379 cluster addslots {8192..16383}
4.主从分配
node2 slaveof node1 ,node4 slaveof node3
集群中输入命令cluster nodes查看每个节点的ID,这个ID在分配主从的时候要用
在node2上执行 那一串很长的是node1的nodeid
./redis-cli -p 6379 cluster replicate 4be5d22323fbb080172ffdeb0885f7caacc45dbd
在node4上执行 那一串很长的是node3的nodeid
./redis-cli -p 6379 cluster replicate 6500b5a2ed52ffc05a5d81ee57ecca4282e5cf5e
配置完以后再在集群中输入cluster nodes查看节点信息
./redis-cli -p 6379 cluster nodes
集群中可以输入命令cluster info查看集群信息。
cluster slots可以看到槽的分配信息。
cluster keyslot key可以查看key属于哪个槽
测试是否安装好了
./redis-cli -c -p 6379
node1设置key-value
node2获取key-value
2.官方工具安装
官方提供了ruby的安装脚本
1.首先每台机器要准备ruby的环境。
2.安装rubygem redis
cd /app
wget http://rubygems.org/downloads/redis-4.0.1.gem
gem install -l redis-4.0.1.gem
报错
ERROR: Loading command: install (LoadError)
cannot load such file -- zlib
ERROR: While executing gem ... (NoMethodError)
undefined method `invoke_with_build_args' for nil:NilClass
gem list -- check redis gem
3.安装redis-trib.rb
首先配置开启节点 4台机器
cd /app/redis/config
touch redis-cluster-6379.conf
vi redis-cluster-6379.conf
protected-mode no
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dir /app/redis/data
dbfilename "dump-6379.rdb"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-require-full-coverage no
启动4个节点
cd /app/redis/src
./redis-server /app/redis/config/redis-cluster-6379.conf
使用redis-trib.rb
cd /app/redis/src
./redis-trib.rb create --replicas 1 192.168.2.103:6379 192.168.2.106:6379 192.168.2.104:6379 192.168.2.107:6379
replicas是为每个主节点配置多少个从节点
前两个是主节点,后两个是从节点。