Redis cluster集群模式
Redis Cluster设计的核心思想:数据拆分、去中心化
Redis cluster基础概念 Redis群集TCP端口 每个Redis群集节点都需要打开两个TCP连接。用于服务客户端的常规Redis TCP端口,例如6379,再加上将数据端口加10000所获得的端口,因此在示例中为16379。
第二个高端口用于群集总线,即使用二进制协议的节点到节点通信通道。节点将群集总线用于故障检测,配置更新,故障转移授权等。
Redis Cluster data sharding Redis Cluster将所有数据按照hash slot算法分布到16384[0-16383]个哈希槽上面,哈希槽分布在各节点上,各节点维护自己的哈希槽。
hash slot算法如下:
1 HASH_SLOT = CRC16(key) mod 16384
Redis Cluster主从模型 为了在主节点的子集出现故障或无法与大多数节点通信时保持可用,Redis Cluster使用主从模型,其中每个哈希槽具有从1(主节点本身)到N个副本(N个) -1个其他从属节点)。
在具有节点A,B,C的示例集群中,如果节点B失败,则集群将无法继续,因为我们不再有办法为5501-11000范围内的哈希槽提供服务。
但是,在创建集群(或稍后)时,我们向每个主节点添加一个从属节点,以便最终集群由作为主节点的A,B,C和作为从属节点的A1,B1,C1组成,如果节点B发生故障,系统将能够继续。
节点B1复制B,并且B发生故障,群集会将节点B1提升为新的主节点,并将继续正常运行。
但是请注意,如果节点B和B1同时失败,则Redis Cluster无法继续运行。
Redis集群一致性保证 Redis Cluster无法保证强一致性。实际上,这意味着在某些情况下,Redis Cluster可能会丢失系统认可给客户端的写入。
Redis Cluster可能丢失写入的第一个原因是因为它使用异步复制。这意味着在写入期间会发生以下情况:
您的客户写信给主B。
主B向您的客户答复OK。
主机B将写操作传播到其从机B1,B2和B3。
如您所见,B在回复客户端之前不会等待B1,B2,B3的确认,因为这会对Redis造成延迟,因此,如果您的客户端写了一些东西,B会确认写,但是在能够将写操作发送到其从属服务器之前崩溃,因此一个从属服务器(未接收到写操作)可以升级为主服务器,从而永远丢失该写操作。
Redis cluster和Redis Sentinel的区别 Redis cluster:
是为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器,内存/QPS不受限于单机,可受益于分布式集群高扩展性。
cluster做了sharding,一个key通过hash算法分配到不同的槽(slot)上,所有不同节点存储的数据是不一样的。
集群模式提高并发量
Redis Sentinel:
Dokcer部署 安装 创建工作目录,后面所有操作均在此目录下完成
1 mkdir cluster-test && cd cluster-test
准备镜像和网络
1 2 3 4 5 6 7 8 docker pull redis:4.0.14 docker pull ruby docker network create redis-net docker network inspect redis-net | grep "Gateway" | grep --color=auto -P '(\d{1,3}.){3}\d{1,3}' -o
redis-trib
帮助镜像准备Dockerfile
1 2 3 4 5 6 FROM ruby WORKDIR /redis RUN gem install redis RUN wget https://raw.githubusercontent.com/antirez/redis/4.0/src/redis-trib.rb -P /redis
初始化脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 export GATE_IP=$(docker network inspect redis-net | grep "Gateway" | grep --color=auto -P '(\d{1,3}.){3}\d{1,3}' -o)cat > redis.tmpl << EOF ##节点端口 port \${PORT} ##cluster集群模式 cluster-enabled yes ##集群配置名 cluster-config-file nodes.conf ##超时时间 cluster-node-timeout 5000 ##实际为各节点网卡分配ip 先用上网关ip代替 cluster-announce-ip $GATE_IP ##节点映射端口 cluster-announce-port \${PORT} ##节点总线端 cluster-announce-bus-port 1\${PORT} ##持久化模式 appendonly yes EOF echo "======================================" echo "Redis Cluster Cleaner." echo "======================================" for i in `seq 7000 7005`;do docker rm -f redis-$i ;done echo "======================================" echo "Redis Cluster Conf Init." echo "======================================" for port in `seq 7000 7005`; do \mkdir -p ./${port} \ && mkdir -p ./${port} /data \ && PORT=${port} envsubst < ./redis.tmpl > ./${port} /redis.conf; \ done echo "======================================" echo "Redis Cluster Start." echo "======================================" for port in `seq 7000 7005`; do \docker run -d -ti -p ${port} :${port} -p 1${port} :1${port} \ -v $PWD /${port} /redis.conf:/usr/local /etc/redis/redis.conf \ -v $PWD /${port} /data:/data \ --restart always --name redis-${port} --net redis-net \ --sysctl net.core.somaxconn=1024 redis:4.0.14 redis-server /usr/local /etc/redis/redis.conf; \ done echo "======================================" echo "Redis Cluster Conf Replace." echo "======================================" matches="" for port in `seq 7000 7005`; do \hello=$(docker inspect redis-$port |grep "IPAddress" |grep --color=auto -P '(\d{1,3}.){3}\d{1,3}' -o) &&\ sed -i "s/$GATE_IP /$hello /g" ${port} /redis.conf &&\ docker restart redis-${port} matches=$matches " " $hello ":" $port done echo $matches echo "======================================" echo "Redis Cluster Start Up." echo "======================================" docker run -it --rm --net redis-net redis-trib ruby redis-trib.rb create --replicas 1 $matches
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $redis -cli -c -h 127.0.0.1 -p 7000127.0.0.1:7000> set a a -> Redirected to slot [15495] located at 172.18.0.4:7002 OK 172.18.0.4:7002> set bb bb -> Redirected to slot [8620] located at 172.18.0.3:7001 OK 172.18.0.3:7001> set cc cc -> Redirected to slot [700] located at 172.18.0.2:7000 OK 172.18.0.2:7000>
参考 Redis cluster tutorial
Redis Cluster Specification
【译】Redis集群规范 (Redis Cluster Specification)
redis.conf
Redis的高可用详解:Redis哨兵、复制、集群的设计原理,以及区别
Redis Cluster 原理分析
docker redis 集群(cluster)搭建