1、Redis Cluster的架构图。
架构细节
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
redis--cluster
(1)领着选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
b:如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
ps:当集群不可用时,所有对集群的操作做都不可用,收到((error)CLUSTERDOWN Thecluster is down)错误。
redis主从和MySQL主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口:slaveof 120.77.213.193 6379,然后启动主从,主从就搭建好了redis主从中如果主节点发生故障,不会自动切换,需要借助redis的Sentinel或者keepalive来实现主的故障转移
但是搭建集群时候已经设置过主从啦。
总结:
redis集群是一个无中心的分布式redis存储[架构],可以在多个节点之间进行数据共享,解决了redis高可用、可扩展等问题
redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
redis集群提供了以下两个好处
(1)将数据自动切分(split)到多个节点
(2)Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。所以我们在测试的时候看到set 和 get 的时候,直接跳转到了7002端口的节点。
Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。
需要注意的是:必须要3个或以上的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了。
二、集群的使用
这表示集群中的 16384 个槽都有至少一个主节点在处理, 集群运作正常。
slots:0-5460 (5461 slots) master
slots:5461-10922 (5462 slots) master
slots:10923-16383 (5461 slots) master
集群
cluster info :打印集群的信息
cluster nodes :列出集群当前已知的所有节点( node),以及这些节点的相关信息。
节点
cluster meet <ip> <port> :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster forget <node_id> :从集群中移除 node_id 指定的节点。
cluster replicate <node_id> :将当前节点设置为 node_id 指定的节点的从节点。
cluster saveconfig :将节点的配置文件保存到硬盘里面。
槽(slot)
cluster addslots <slot> [slot ...] :将一个或多个槽( slot)指派( assign)给当前节点。
cluster delslots <slot> [slot ...] :移除一个或多个槽对当前节点的指派。
cluster flushslots :移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
cluster setslot <slot> node <node_id> :将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
cluster setslot <slot> migrating <node_id> :将本节点的槽 slot 迁移到 node_id 指定的节点中。
cluster setslot <slot> importing <node_id> :从 node_id 指定的节点中导入槽 slot 到本节点。
cluster setslot <slot> stable :取消对槽 slot 的导入( import)或者迁移( migrate)。
键
cluster keyslot <key> :计算键 key 应该被放置在哪个槽上。
cluster countkeysinslot <slot> :返回槽 slot 目前包含的键值对数量。
cluster getkeysinslot <slot> <count> :返回 count 个 slot 槽中的键
增加一个主节点
redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
PS:最后面这个IP:PORT可以是集群里边儿任意一个主节点的IP和端口,下同
增加从节点
redis-trib.rb add-node --slave 127.0.0.1:7006 127.0.0.1:7000
此处的命令和添加一个主节点命令类似,此处并没有指定添加的这个从节点的主节点,这种情况下系统会在其他的复制集中的主节点中随机选取一个作为这个从节点的主节点。
指定主节点:
redis-trib.rb add-node --slave --master-id 36d53c7f1896838249c0b4afdcf680bac2f4ec2e 127.0.0.1:7008 127.0.0.1:7001
增加的节点都是空槽,若增加的是从节点
例如,要给主节点 127.0.0.1:7003添加一个从节点,该节点哈希槽的范围1423-16383, 节点 ID 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e,我们需要链接新的节点(已经是空的主节点)并执行命令:
redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
重新分片
所谓重新分片,就是重新分配各个节点拥有的slots,这里我们的主要目的是从老的节点中迁移一部分slots放到新节点中去,以便让新节点真正成为集群中的一员.同样, 还是利用redis-trib.rb 工具.
redis-trib.rb reshard 127.0.0.1:7001
//PS: 这条命令是交互的,按照提示操作即可.
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)?4096 //输入一个数,这个4096表示迁移多少个slots数
What is the receiving node ID? 36d53c7f1896838249c0b4afdcf680bac2f4ec2e //输入目标节点ID,表示迁移到哪个目标节点
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:all //输入all表示从老的所有节点进行重分配,凑够4096个slots给到新节点.
也可以输入源节点id, 可以输入多个源节点id,最后输入done.就开始从你输入的源节点id的节点进行迁移了
当然也可以采用非交互自动的进行迁移, 如:
[root@localhost redis-3.2.0]# /usr/local/redis/bin/redis-trib.rb reshard --from a2eee0ea546f2c3701b08981737c07938039857c --to 36d53c7f1896838249c0b4afdcf680bac2f4ec2e --slots 45 --yes 127.0.0.1:7001
--from a2eee0ea546f2c3701b08981737c07938039857c //表示从哪个节点进行迁移,即源节点
--to 36d53c7f1896838249c0b4afdcf680bac2f4ec2e //迁移到哪个节点,即目标节点
--slots 45 //迁移多少slot
--yes //无需输入yes确认
不过非交互的迁移就不能使用多个源节点进行迁移slots了.
移除一个节点:
只要使用 del-node 命令即可:
redis-trib del-node 127.0.0.1:7000 `<node-id>`
第一个参数是任意一个节点的地址,第二个节点是你想要移除的节点地址。
使用同样的方法移除主节点,不过在移除主节点前,需要确保这个主节点是空的. 如果不是空的,需要将这个节点的数据重新分片到其他主节点上.
替代移除主节点的方法是手动执行故障恢复,被移除的主节点会作为一个从节点存在,不过这种情况下不会减少集群节点的数量,也需要重新分片数据。