Redis Cluster集群详解

Redis集群(Redis-Cluster)

1、工作原理

Redis 集群是一个提供在多个Redis节点间共享数据的程序集。下图以三个master节点和三个slave节点作为示例。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,如图中slots所示。

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有1-n个从节点。例如master-A节点不可用了,集群便会选举slave-A节点作为新的主节点继续服务。
在这里插入图片描述

2、搭建步骤

Redis5.0之后的版本放弃了 Ruby 的集群方式,改为使用 C 语言编写的redis-cli的方式,使集群的构建方式复杂度大大降低。

下载安装Redis(见主从复制模式的搭建步骤)。

创建6个Redis的配置文件,如下所示:

/usr/local/redis-5.0.4/redis-cluster-conf/7001/redis.conf
/usr/local/redis-5.0.4/redis-cluster-conf/7002/redis.conf
/usr/local/redis-5.0.4/redis-cluster-conf/7003/redis.conf
/usr/local/redis-5.0.4/redis-cluster-conf/7004/redis.conf
/usr/local/redis-5.0.4/redis-cluster-conf/7005/redis.conf
/usr/local/redis-5.0.4/redis-cluster-conf/7006/redis.conf

配置文件内容:

port 7001  # 端口,每个配置文件不同7001-7006
cluster-enabled yes # 启用集群模式
cluster-config-file nodes.conf #节点配置文件
cluster-node-timeout 5000 # 超时时间
appendonly yes # 打开aof持久化
daemonize yes # 后台运行
protected-mode no # 非保护模式
pidfile  /var/run/redis_7001.pid # 根据端口修改

启动6个Redis节点。

./src/redis-server redis-cluster-conf/7001/redis.conf
./src/redis-server redis-cluster-conf/7002/redis.conf
./src/redis-server redis-cluster-conf/7003/redis.conf
./src/redis-server redis-cluster-conf/7004/redis.conf
./src/redis-server redis-cluster-conf/7005/redis.conf
./src/redis-server redis-cluster-conf/7006/redis.conf

此时启动的6个Redis服务是相互独立运行的,通过以下命令配置集群。

./src/redis-cli --cluster create --cluster-replicas 1 
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

配置完看到如下图所示信息表示集群搭建成功:
在这里插入图片描述

从图中可以看到启动了3个master节点,3个slave节点,16384个槽点平均分配到了3个master节点上。图中很长的一串字母数字的组合(07000b3a90…)为节点的ID。后面对节点的操作中会用到。

1、集群重新分片

如果对默认的平均分配不满意,我们可以对集群进行重新分片。执行如下命令,只需要指定集群中的其中一个节点地址即可,它会自动找到集群中的其他节点。(如果设置了密码则需要加上 -a ,没有密码则不需要,后面的命令我会省略这个,设置了密码的自己加上就好)。

./src/redis-cli -a <password> --cluster reshard 127.0.0.1:7001

输入你想重新分配的哈希槽数量

How many slots do you want to move (from 1 to 16384)?

输入你想接收这些哈希槽的节点ID

What is the receiving node ID?

输入想从哪个节点移动槽点,选择all表示所有其他节点,也可以依次输入节点ID,以done结束。

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:

输入yes执行重新分片

Do you want to proceed with the proposed reshard plan (yes/no)?

2、自动故障转移

当运行中的master节点挂掉了,集群会在该master节点的slave节点中选出一个作为新的master节点。这里不做演示。

3、手动故障转移

有的时候在主节点没有任何问题的情况下强制手动故障转移也是很有必要的,比如想要升级主节点的Redis进程,我们可以通过故障转移将其转为slave再进行升级操作来避免对集群的可用性造成很大的影响

Redis集群使用 cluster failover 命令来进行故障转移,不过要在被转移的主节点的从节点上执行该命令(使用redis-cli连接slave节点并执行 cluster failover命令进行转移)。

4、添加一个主节点

按之前的方式再复制一份配置文件,并修改配置

/usr/local/redis-5.0.4/redis-cluster-conf/7007/redis.conf

然后启动该Redis服务,执行以下命令将该节点添加到集群中去

./src/redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001

第一个参数为新增加的节点的IP和端口,第二个参数为任意一个已经存在的节点的IP和端口。

此时该新节点已经成为集群的一份子

127.0.0.1:7007> cluster nodes
90c78386c39c8258435b5b61f49a623b358ec8a6 127.0.0.1:7007@17007 myself,master - 0 1553239975877 10 connected
c4180e02149e2d853a80683433773ef4bceffc78 127.0.0.1:7001@17001 master - 0 1553240017595 11 connected 0-5544 10923-11004
b6584514edbf57331a65f367304f33ad1bd0903e 192.168.1.164:7005@17005 slave 3bdbc4ac0d5902dcf8a5ebbfb88db8fad224c066 0 1553240016992 2 connected
07000b3a905df0ab0c86361adcb2774a487ce650 192.168.1.164:7004@17004 slave c4180e02149e2d853a80683433773ef4bceffc78 0 1553240016000 11 connected
28fa7bbf6b2a46991c7a5fe8eec53db1a5f1e9f6 192.168.1.164:7003@17003 master - 0 1553240017595 3 connected 11005-16383
3bdbc4ac0d5902dcf8a5ebbfb88db8fad224c066 192.168.1.164:7002@17002 master - 0 1553240017000 2 connected 5545-10922
fd9cba359d94ba6c9beecc91fbd491f9cf7a39ca 192.168.1.164:7006@17006 slave 28fa7bbf6b2a46991c7a5fe8eec53db1a5f1e9f6 0 1553240016000 3 connected

但是该节点没有包含任何的哈希槽,所以没有数据会存到该主节点。我们可以通过上面的集群重新分片给该节点分配哈希槽,那么该节点就成为了一个真正的主节点了。

5、添加一个从节点

跟添加主节点一样添加一个节点7008,然后连接上该节点并执行如下命令

cluster replicate <nodeId>

这样就可以指定该节点成为哪个节点的从节点。

6、节点的移除

可以使用如下命令来移除节点

./src/redis-cli --cluster del-node 127.0.0.1:7001 <nodeId>

第一个参数是任意一个节点的地址,第二个参数是你想要移除的节点ID。如果是移除主节点,需要确保这个节点是空的,如果不是空的则需要将这个节点上的数据重新分配到其他节点上。

7、程序中使用

SpringBoot中连接Redis集群配置

spring:
  redis:
    cluster:
      nodes: 192.168.1.164:7001,192.168.1.164:7002,192.168.1.164:7003,192.168.1.164:7004,192.168.1.164:7005,192.168.1.164:7006
    database: 0
    password: <password>

参考文档

http://www.redis.cn/topics/cluster-tutorial.html

3、Redis常见数据丢失情况分析及解决

情况分析

(1)异步复制导致的数据丢失
在这里插入图片描述
因为master->slave的数据同步是异步的,所以可能存在部分数据还没有同步到slave,master就宕机了,此时这部分数据就丢失了。

(2)脑裂导致的数据丢失
在这里插入图片描述

当master所在的机器突然脱离的正常的网络,与其他slave、sentinel失去了连接,但是master还在运行着。此时sentinel就会认为master宕机了,会开始选举把slave提升为新的master,这个时候集群中就会出现两个master,也就是所谓的脑裂。

此时虽然产生了新的master节点,但是客户端可能还没来得及切换到新的master,会继续向旧的master写入数据。

当网络恢复正常时,旧的master会变成新的master的从节点,自己的数据会清空,重新从新的master上复制数据。

解决方案

Redis提供了这两个配置用来降低数据丢失的可能性

min-slaves-to-write 1 
min-slaves-max-lag 10

上面两行配置的意思是,要求至少有1个slave,数据复制和同步的延迟不能超过10秒,如果不符合这个条件,那么master将不会接收任何请求。

(1)减少异步复制的数据丢失

有了min-slaves-max-lag这个配置,就可以确保,一旦slave复制数据和ack延时太长,就认为master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低到可控范围内。

(2)减少脑裂的数据丢失

如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求

这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失。

Redis并不能保证数据的强一致性,看官方文档的说明
在这里插入图片描述

作者:haoyanbing
链接:https://www.jianshu.com/p/7d5fbf90bcd7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发布了78 篇原创文章 · 获赞 53 · 访问量 8170

猜你喜欢

转载自blog.csdn.net/qqq3117004957/article/details/104809341