1. 为什么使用集群
在哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。我们知道只有主节点才具有写能力,那如果在一个集群中,能够配置多个主节点,是不是就可以缓解写压力了呢?这个就是redis-cluster集群模式
假设我们在一台主从机器上配置了200G内存,但是业务需求是需要500G的时候,主从结构+哨兵可以实现高可用、故障切换、冗余备份,但是并不能解决数据容量的问题,用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。
为了最大化利用内存,可以采用cluster群集,就是分布式存储。即每台redis存储不同的内容。
集群不保证数据一致性100%OK,一定会有数据丢失情况
Redis集群是一个提供在多个Redis节点间共享数据的程序集 Redis集群可以支持多个Master
Redis 分布式方案一般有以下几种:
-
客户端分区方案:优点是分区逻辑可控,缺点是需要自己处理数据路由、高可用、故障转移等问题,比如在redis2.8之前通常的做法是获取某个key的hashcode,然后取余分布到不同节点,不过这种做法无法很好的支持动态伸缩性需求,一旦节点的增或者删操作,都会导致key无法在redis中命中
-
代理方案:优点是简化客户端分布式逻辑和升级维护便利,缺点是加重架构部署复杂度和性能损耗,比如twemproxy、Codis等第三方
-
官方专有的集群方案:Redis Cluster,它非常优雅地解决了 Redis 集群方面的问题,部署方便简单,因此理解应用好 Redis Cluster 将极大地解放我们使用分布式 Redis 的工作量
2.Redis-cluster集群概念
Redis Cluster 是 Redis 的分布式解决方案,在3.0版本正式推出,有效地解决了 Redis 分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用 Cluster 架构方案达到负载均衡的目的。架构图如下:
在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点,对其进行存取和其他操作。
集群作用
-
Redis集群支持多个Master,每个Master又可以挂载多个Slave
-
由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
-
客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
-
槽位slot负责分配数据到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系
3. 集群节点复制
在Redis-Cluster集群中,可以给每一个主节点添加从节点,主节点和从节点直接遵循主从复制模型的特性。
当用户需要处理更多读请求的时候,添加从节点可以扩展系统的性能。
4. 故障转移
Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点,并对已下线的主节点进行故障转移。
集群进行故障转移的方法和Redis Sentinel进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群不必另外使用Redis Sentinel。
5. 集群分片策略
Redis-cluster分片策略,是用来解决key存储位置的
集群将整个数据库分为16384个槽位slot,所有key-value数据都存储在这些slot中的某一个上。一个slot槽位可以存放多个数据,key的槽位计算公式为:
slot_number=crc16(key)%16384
其中crc16为16位的循环冗余校验和函数
集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。
5.1 redis集群的槽位slot
Redis集群没有使用一致性hash 而是引入了哈希槽的概念
Redis集群有16384个哈希槽每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:
redis集群的分片
分片是什么 | 使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。 |
---|---|
如何找到给定key的分片 | 为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。 |
5.2 分片和槽位的优势
最大优势,方便扩缩容和数据分派查找
这种结构很容易添加或者删除节点,比如如果我想添加个节点D,我需要从节点A,B,C中得部分槽位到D上。如果我想移除节点A,需要将A中的槽移动到B和C节点上,然后将没有任何槽的节点从集群中移除即可。由于一个结点将哈希槽移动到另一个节点不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态
5.3 slot槽位映射解决方案
5.3.1 哈希取余分区(小规模)
2亿条记录就是2亿个k,v,我们单机不行,必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。
优点: 简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。
缺点: 原来规划好的节点,进行扩容或者缩容就比较麻烦,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。如果某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
5.3.2 一致性哈希算法分区
一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。
提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系
计算步骤
-
算法构建一致性哈希环
一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),这样让它逻辑上形成了一个环形空间。
它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对2^32取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1, 0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。
-
redis服务器IP节点映射
将集群中各个IP节点映射到环上的某一个位置
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:
-
key落到服务器的落键规则
当我们需要存储一个k v键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。 如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。
优点
一致性哈希算法的容错性:假设Node C宕机,可以看到此时对象A、B、D不会受到影响。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据且这些数据会转移到D进行存储。
一致性哈希算法的扩展性 : 数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那受到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。
缺点
一致性哈希算法的数据倾斜问题:一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器:
总结:
为了在节点数目发生改变时尽可能少的迁移数据,将所有的存储节点排列在首尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。 而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。
优点 : 加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。
缺点 数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果
5.3.3 哈希槽分区
哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。
HASH_SLOT = CRC16(key) mod 16384
主要解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配
多少个hash槽
一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。 集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取模,余数是几key就落入对应的槽里。HASH_SLOT = CRC16(key) mod 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
哈希槽计算
Redis 集群中内置了 16384 个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在 Redis 集群中放置一个 key-value时,redis先对key使用crc16算法算出一个结果然后用结果对16384求余数[ CRC16(key) % 16384],这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A 、B在Node2, key之C落在Node3上
为什么redis集群的最大槽数是16384个?
-
如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为16384时,这块的大小是: 16384÷8÷1024=2kb 因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽
-
redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
-
槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。
6. 集群redirect转向
由于Redis集群无中心节点,请求会随机发给任意主节点;主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误; 客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。
7集群实战
角色 | IP | 端口 | 模式 |
---|---|---|---|
主1 | 192.168.211.128 | 6379 | 集群模式 |
从1 | 192.168.211.129 | 6380 | 集群模式 |
主2 | 192.168.211.129 | 6379 | 集群模式 |
从2 | 192.168.211.130 | 6380 | 集群模式 |
主3 | 192.168.211.130 | 6379 | 集群模式 |
从3 | 192.168.211.128 | 6380 | 集群模式 |
Redis集群最少需要6个节点,3主3从,可以分布在一台或者多台主机上
开放端口
redis集群不仅需要开通redis客户端连接的端口,而且需要开通集群总线端口
集群总线端口为redis客户端连接的端口 + 10000 如redis端口为6379 则集群总线端口为16379
或者关闭防火墙 云服务器设置安全组
#开放端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --zone=public --add-port=16379/tcp --permanent# 重启
systemctl restart firewalld.service
7.1 集群配置文件
# redis.conf文件示例
bind 0.0.0.0
port 6379
daemonize yes
protected-mode no
pidfile /var/run/redis_7001.pid
dir "./" # node.conf文件保存路径
logfile "/var/log/redis/7001/redis.log"
appendonly yes
appendfsync alwayscluster-enabled yes
cluster-config-file nodes-6379.conf # 该文件中包含集群信息
cluster-node-timeout 5000# 密码设置
requirepass xxx (设置redis访问密码)
masterauth xxx (设置集群节点间访问密码,跟上面一致)# 集群是否完整才能对外提供服务
# 默认YES,现在集群架构是3主3从的redis cluster由3个master平分16384个slot,每个master的小集群负责1/3的slot,对应一部分数据。cluster-require-full-coverage:默认值yes,即需要集群完整性,方可对外提供服务通常情况,如果这3个小集群中,任何一个(1主1从)挂了,你这个集群对外可提供的数据只有2/3了,整个集群是不完整的, redis默认在这种情况下,是不会对外提供服务的。
# 如果你的诉求是,集群不完整的话也需要对外提供服务,需要将该参数设置为no,这样的话你挂了的那个小集群是不行了,但是其他的小集群仍然可以对外提供服务。
cluster-require-full-coverage yes
7.2 启动每个节点redis服务
# 每个节点运行并启动
redis-server /usr/local/redis/bin/redis.conf
7.3 执行创建集群命令
# 不配置密码
redis-cli --cluster create 192.168.211.128:6379 192.168.211.129:6379 192.168.211.130:6379 192.168.211.128:6380 192.168.211.129:6380 192.168.211.130:6380 --cluster-replicas 1 # 配置密码
redis-cli --cluster create 192.168.1.75:6379 192.168.1.77:6379 192.167.1.79:6379 192.168.1.76:6379 192.168.1.78:6379 192.1681.80:6379 --cluster-replicas 1 -a abc123456
7.4查询集群信息
# 登录redis
# -a访问服务端密码
# -c表示集群模式,集群模式一定要加
# -h ,-p 指定ip地址和端口号redis-cli -a abc123456 -c -h 192.168.1.75 -p 6379# 查询集群节点信息
cluster nodes# 查询集群状态信息
cluster info#其他查询方法
redis-cli --cluster check 192.168.1.75:6379 -a abc123456# 查看某个key该属于对应的槽位值
CLUSTER KEYSLOT k1
7.5redis cluster集群重新启动
因为集群已经创建过了,若是关机等原因关闭了redis服务,则只需要执行启动命令就会自动开启集群,因为有node.conf文件的存在
7.6 手动故障转移or节点从属调整该如何处理
如果主节点宕机,从机上位变成主节点,怎么对调
CLUSTER FAILOVER
8. 集群管理
- 添加新主节点
redis-cli -a 111111 --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id
- 检查集群情况
redis-cli -a 密码 --cluster check 真实ip地址:6381
- hash槽重新分配
添加完新节点后,需要对新添加的主节点进行hash槽重新分配,这样该主节点才能存储数据,redis共有16384个槽
redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots <args> --cluster-yes
- 添加新从节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id
- 删除节点
redis-cli --cluster del-node host:port node_id
- 集群常用命令
# 创建集群
redis-cli --cluster create host1:port1 ... hostN:portN --cluster-replicas <arg>
# 例子
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
# 例子说明
host1:port1 ... hostN:portN表示的是要添加的集群的节点IP和端口,
--cluster-replicas <arg>表示的是主从节点比例,参数1表示前三个是主节点,后三个是从节点
也就是说7001,7002,7003端口对应的节点是主节点,7004,7005,7006对应的节点是从节点# 查询集群节点信息
redis-cli -c -p 7001 cluster nodes
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564923261350 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564923263366 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564923262000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564923260000 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564923263000 1 connected 0-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564923262358 2 connected 5461-10922# 说明:以下的操作均是以上面这个为参数示例# 给集群添加一个新主节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id
# 例子
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7003 --cluster-master-id bbe8b7035bfd31c47bec7d612acc112cd2869368
# 例子说明
new_host:new_port为要新添加的主节点IP和端口,此处是127.0.0.1:7007
existing_host:existing_port表示的是已存在的最后一个主节点的IP和端口,这个可以从上述的节点信息中查看到,根据slots槽数,7003端口对应的节点槽数是10923-16383,16383表示的是最后的槽数
--cluster-master-id表示的是最后一个主节点的节点id,表示的是新添加的主节点要在这个节点后面# 再次查看集群信息
redis-cli -c -p 7001 cluster nodes
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564923261350 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564923263366 3 connected 10923-16383
7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564923260344 0 connected
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564923262000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564923260000 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564923263000 1 connected 0-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564923262358 2 connected 5461-10922
# 会发现7007端口对应的节点已经加入到集群中,是主节点,但是没有从节点,也没有分配槽数# 给新添加的主节点分配slots槽数
redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots 500 --cluster-yes
# 例子
redis-cli --cluster reshard 127.0.0.1:7007 --cluster-from 4dad696ede24995a57c5fd790faa95c72c187a22 --cluster-to 7020c8df9423686727783c60bd2f0e367634ba84 --cluster-slots 500
# 例子说明
host:port表示的是新添加的那个主节点IP和端口,此处表示的是127.0.0.1:7007
--cluster-from node_id表示的是集群第一个主节点的节点id,这个可以现有集群的slots槽数分配看出,此处表示的是7001端口对应的节点
--cluster-to node_id表示的是集群最后一个主节点的节点id,也就是新添加的那个主节点id,此处表示的是7007端口对应的节点
--cluster-slots 500表示的是给新主节点分配多少,此处500表示是分配从0-499个slots槽数,若不加上这个会让手动输入
--cluster-yes表示的是自动应答为yes,若不加上这个会让手动输入yes,表示同意此次分配# 再次查看集群信息
/redis-cli -c -p 7001 cluster nodes 7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564924042000 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564924042157 3 connected 10923-16383
7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564924040140 7 connected 0-499
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564924040000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564924041149 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564924040000 1 connected 500-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564924043166 2 connected 5461-10922
# 会发现7007端口对应的主节点已经有slots槽数了,并且是从0开始的# 给集群中某个主节点再添加一个从节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id
# 例子
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7008 --cluster-slave --cluster-master-id 7020c8df9423686727783c60bd2f0e367634ba84
# 例子说明
new_host:new_port表示的是要添加的那个从节点的IP和端口,此处表示的是127.0.0.1:7008
existing_host:existing_port表示的是要给哪个主节点添加从节点,此处表示的是127.0.0.1:7007
--cluster-slave表示的是要添加从节点,否则则是添加主节点了
--cluster-master-id node_id表示要给哪个主节点添加从节点的该主节点节点id# 再次查看集群信息
redis-cli -c -p 7001 cluster nodes 7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564924845000 7 connected 0-499
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564924843000 1 connected 500-5460
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564924845214 6 connected
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564924843195 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564924844205 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564924845000 5 connected
415db07121ba946b202bca98e15cbdffc60bc18a 127.0.0.1:7008@17008 slave 7020c8df9423686727783c60bd2f0e367634ba84 0 1564924846224 7 connected
c3e04f0e8710c25d59703374a224ee8bec776e43 :0@0 master,fail,noaddr - 1564924804548 1564924802833 0 disconnected
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564924844000 2 connected 5461-10922
# 会发现7008端口对应的节点已经是7007端口对应的从节点# 从集群中删除一个从节点
redis-cli --cluster del-node host:port node_id
# 例子
redis-cli --cluster del-node 127.0.0.1:7008 415db07121ba946b202bca98e15cbdffc60bc18a
# 例子说明
host:port表示的是要删除的那个节点的IP和端口,此处是127.0.0.1:7008
node_id表示的是删除的那个节点的节点id# 其他命令有待补充
# 1 该槽位被占用
# 0 该槽位没有被占用
CLUSTER COUNTKEYSINSLOT 槽位数字编号# 返回对应key的槽位数据,key不存在则返回0
CLUSTER KEYSLOT 键名称
9. 如何选择Redis cluster集群、replication主从复制、sentinal哨兵
如果你的数据量很少,主要是承载高并发高性能的场景,比如你的缓存一般就几个G,单机足够了。
Replication:一个mater,多个slave,要几个slave与你业务需求的读吞吐量有关系,结合sentinal集群,去保证redis主从架构的高可用性,就可以了。
redis cluster:主要是针对海量数据+高并发+高可用的场景,海量数据,如果你的数据量很大,那么建议就用redis cluster。
10. Redis集群的功能限制
-
key 批量操作支持有限:类似 mset、mget 操作,目前只支持对具有相同 slot 值的 key 执行 批量操作。对于 映射为不同 slot 值的 key 由于执行 mset、mget 等操作可能存在于多个节点上,因此不被支持
可以通过{}来定义同一个组的概念,使key中{}内相同内容的键值对放到一个slot槽位去
-
key 事务操作支持有限:只支持多key在同一节点上的事务操作,当多个key分布在不同的节点上时无法使用事务功能
-
key 作为数据分区的最小粒度:不能将一个大的键值对象如 hash、list 等映射到 不同的节点
-
不支持多数据库空间:单机下的 Redis 可以支持 16 个数据库(db0 ~ db15),集群模式下只能使用一个数据库空间,即 db0
-
复制结构只支持一层:从节点只能复制主节点,不支持嵌套树状复制结构