集群简介
-redis集群架构设计

  • cluster集群架构搭建

现状问题
业务发展过程中遇到的峰值瓶颈

  • redis提供的服务ops可以达到10万/秒,当前业务ops已经达到20万/秒
  • 内存单机容量达到256G,当前业务需求内存容量1T

集群作用

  • 分散单台服务器的访问压力,实现负载均衡
  • 分散单台服务器的存储压力,实现可扩展性
  • 降低单台服务器宕机带来的业务灾难

三版本系列redis开始支持集群

redis集群搭建及原理

以下摘抄于官网
http://www.redis.cn/topics/cluster-tutorial.html
Redis集群介绍
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:

自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
Redis 集群的数据分片
Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

Redis 集群的主从复制模型
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.

然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了

不过当B和B1 都失败后,集群是不可用的.

Redis 一致性保证
Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作.

第一个原因是因为集群是用了异步复制. 写操作过程:

客户端向主节点B写入一条命令.
主节点B向客户端回复命令状态.
主节点将写操作复制给他得从节点 B1, B2 和 B3.
主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。 注意:Redis 集群可能会在将来提供同步写的方法。 Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。

举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1 假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .

Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.

注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项:

redis集群结构设计

数据存储设计
redis集群搭建及原理

redis集群搭建及原理

当增加新的机器的时候,会将其他一部分机器的哈希槽分配一部分给新的机器,机器减少同样道理,会把老机器哈希槽分配给其他机器,然后移掉减少的机器

redis集群搭建及原理

当一台计算机需要通过一个key寻找相应的数据,则会通过key经过他的crc算法及取模找到应的槽位置,如果命中则直接返回,如果没有,该哈希槽会告知你具体位置,则最多两次即可命中数据,即一次命中直接返回,一次未命中,告知具体位置

集群搭建
环境准备,单机多实例,三主三从
1、解压reis到/opt/redis/,创建conf目录,创建redis.conf文件

[root@CombCloud-2020110836 conf]# pwd
/opt/redis-5.0.9/conf
[root@CombCloud-2020110836 conf]# ll
total 4
-rw-r--r-- 1 root yanght 287 Jun 10 06:57 redis-6379.conf
[root@CombCloud-2020110836 conf]# cat redis-6379.conf 
port 6379
daemonize no
dir "/data/redis/data"
dbfilename "dump-6379.rdb"
rdbcompression yes
rdbchecksum yes
save 10 2
appendonly yes
appendfsync always
appendfilename "appendonly-6379.aof"
bind 127.0.0.1
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 10000

cluster-enabled yes 设置加入cluster,成为期中的节点
cluster-config-file redis cluster配置文件名,该文件属于自动生成,仅用于快速查找文件并查询文件内容
cluster-node-time 节点响应服务超时时间,用于判定该节点是否下线或切换为从节点
cluster-migration-barrier master连接的slave最小数量


[root@CombCloud-2020110836 conf]# sed "s/6379/6380/g" redis-6379.conf > redis-6380.conf    
[root@CombCloud-2020110836 conf]# sed "s/6379/6381/g" redis-6379.conf > redis-6381.conf 
[root@CombCloud-2020110836 conf]# sed "s/6379/6382/g" redis-6379.conf > redis-6382.conf 
[root@CombCloud-2020110836 conf]# sed "s/6379/6383/g" redis-6379.conf > redis-6383.conf  
[root@CombCloud-2020110836 conf]# sed "s/6379/6384/g" redis-6379.conf > redis-6384.conf 

2、启动集群

[root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6379.conf 
[root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6380.conf 
[root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6381.conf 
[root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6382.conf [root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6383.conf [root@CombCloud-2020110836 conf]# /opt/redis-5.0.9/src/redis-server /opt/redis-5.0.9/conf/redis-6384.conf 

3、查看进程状态变为集群状态
redis集群搭建及原理

4、查看已生成集配置文件
redis集群搭建及原理

5、创建redis集群
以前版本的是用redis-trib创建集群,redis-trib.rb是ruby程序写的,需要安装ruby和gem
本人用的是5.0.4,所以是使用redis-cli来创建集群
./redis-cli --cluster 创建集群命令参数
create --cluster-replicas 1 后面跟着的1是指1个主带几个从,举例:如果写了3,即1主3从
最后面输入主机及IP,最前面三位是Master,最后面三位是slave,即前面master,后面slave

[root@CombCloud-2020110836 src]# pwd
/opt/redis-5.0.9/src
[root@CombCloud-2020110836 src]# ./redis-cli --cluster create --cluster-replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384

Performing hash slots allocation on 6 nodes... # 在6个节点上分配哈希插槽分.
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922 # 给三个maste分配哈希槽位置
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:6383 to 127.0.0.1:6379
Adding replica 127.0.0.1:6384 to 127.0.0.1:6380 # 添加主从,前面从后面主
Adding replica 127.0.0.1:6382 to 127.0.0.1:6381
Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 702431a6121e2b6337955b6013790e6c6a33e172 127.0.0.1:6379 # 第一位M即为master,后面为ID号
slots:[0-5460] (5461 slots) master # 给master分配的哈希槽
M: 8e60df355d1ad7bb9efedda4160089d41ba7ee87 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
M: 9e093e46c3111fc1d3776347efeaab47b4a97da0 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
S: eb7371b52e7a08159b83d8883fcaf4c346621438 127.0.0.1:6382 # s代表slave,后面跟着的是id号,
replicates 9e093e46c3111fc1d3776347efeaab47b4a97da0 # slave没有哈希槽
S: 2b1154e7b108d895439f14a97db5e9e5eb1ceffc 127.0.0.1:6383
replicates 702431a6121e2b6337955b6013790e6c6a33e172
S: dbeb3765fdee8644f14548d1c754e640275ef867 127.0.0.1:6384
replicates 8e60df355d1ad7bb9efedda4160089d41ba7ee87
Can I set the above configuration? (type 'yes' to accept): yes
Nodes configuration updated
Assign a different config epoch to each node
Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
Performing Cluster Check (using node 127.0.0.1:6379) # 以下为把节点配置加入集群
M: 702431a6121e2b6337955b6013790e6c6a33e172 127.0.0.1:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 2b1154e7b108d895439f14a97db5e9e5eb1ceffc 127.0.0.1:6383
slots: (0 slots) slave
replicates 702431a6121e2b6337955b6013790e6c6a33e172
S: eb7371b52e7a08159b83d8883fcaf4c346621438 127.0.0.1:6382
slots: (0 slots) slave
replicates 9e093e46c3111fc1d3776347efeaab47b4a97da0
S: dbeb3765fdee8644f14548d1c754e640275ef867 127.0.0.1:6384
slots: (0 slots) slave
replicates 8e60df355d1ad7bb9efedda4160089d41ba7ee87
M: 9e093e46c3111fc1d3776347efeaab47b4a97da0 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 8e60df355d1ad7bb9efedda4160089d41ba7ee87 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
Check for open slots...
Check slots coverage...
[OK] All 16384 slots covered. # 16384个槽已经分配覆盖完毕

6、查看集群配置文件

[root@CombCloud-2020110836 data]# pwd
/data/redis/data
[root@CombCloud-2020110836 data]# cat nodes-6379.conf 
702431a6121e2b6337955b6013790e6c6a33e172 127.0.0.1:6379@16379 myself,master - 0 1591793969000 1 connected 0-5460 # myself表示他自已,分配了0-5460个槽
2b1154e7b108d895439f14a97db5e9e5eb1ceffc 127.0.0.1:6383@16383 slave 702431a6121e2b6337955b6013790e6c6a33e172 0 1591793968000 5 connected
eb7371b52e7a08159b83d8883fcaf4c346621438 127.0.0.1:6382@16382 slave 9e093e46c3111fc1d3776347efeaab47b4a97da0 0 1591793969000 4 connected
dbeb3765fdee8644f14548d1c754e640275ef867 127.0.0.1:6384@16384 slave 8e60df355d1ad7bb9efedda4160089d41ba7ee87 0 1591793968000 6 connected
9e093e46c3111fc1d3776347efeaab47b4a97da0 127.0.0.1:6381@16381 master - 0 1591793967705 3 connected 10923-16383
8e60df355d1ad7bb9efedda4160089d41ba7ee87 127.0.0.1:6380@16380 master - 0 1591793969709 2 connected 5461-10922  # 第二个主槽的分配情况
vars currentEpoch 6 lastVoteEpoch 0
[root@CombCloud-2020110836 data]# cat nodes-6380.conf   
8e60df355d1ad7bb9efedda4160089d41ba7ee87 127.0.0.1:6380@16380 myself,master - 0 1591793969000 2 connected 5461-10922
9e093e46c3111fc1d3776347efeaab47b4a97da0 127.0.0.1:6381@16381 master - 0 1591793972000 3 connected 10923-16383
eb7371b52e7a08159b83d8883fcaf4c346621438 127.0.0.1:6382@16382 slave 9e093e46c3111fc1d3776347efeaab47b4a97da0 0 1591793971583 3 connected
2b1154e7b108d895439f14a97db5e9e5eb1ceffc 127.0.0.1:6383@16383 slave 702431a6121e2b6337955b6013790e6c6a33e172 0 1591793970000 1 connected
dbeb3765fdee8644f14548d1c754e640275ef867 127.0.0.1:6384@16384 slave 8e60df355d1ad7bb9efedda4160089d41ba7ee87 0 1591793972584 6 connected
702431a6121e2b6337955b6013790e6c6a33e172 127.0.0.1:6379@16379 master - 0 1591793971000 1 connected 0-5460
vars currentEpoch 6 lastVoteEpoch 0
[root@CombCloud-2020110836 data]# cat nodes-6383.conf  
2b1154e7b108d895439f14a97db5e9e5eb1ceffc 127.0.0.1:6383@16383 myself,slave  702431a6121e2b6337955b6013790e6c6a33e172 0 1591793968000 5 connected
9e093e46c3111fc1d3776347efeaab47b4a97da0 127.0.0.1:6381@16381 master - 0 1591793967000 3 connected 10923-16383
8e60df355d1ad7bb9efedda4160089d41ba7ee87 127.0.0.1:6380@16380 master - 0 1591793969000 2 connected 5461-10922
702431a6121e2b6337955b6013790e6c6a33e172 127.0.0.1:6379@16379 master - 0 1591793969000 1 connected 0-5460
dbeb3765fdee8644f14548d1c754e640275ef867 127.0.0.1:6384@16384 slave 8e60df355d1ad7bb9efedda4160089d41ba7ee87 0 1591793968000 6 connected
eb7371b52e7a08159b83d8883fcaf4c346621438 127.0.0.1:6382@16382 slave 9e093e46c3111fc1d3776347efeaab47b4a97da0 0 1591793969412 4 connected

7、再次查看redis6379实例启动日志
redis集群搭建及原理

8、再查看6383实例的redis日志输出可看到在连master6379
redis集群搭建及原理

9、集群客户端交互需要加-c参数
redis集群搭建及原理
可看到重定现到6380实例的5798槽

redis集群搭建及原理
在6384实例登陆,get可查看到重定到6380查询

故障转移过程 演示
关闭从6384端口
redis集群搭建及原理

查看主标记断开连接
redis集群搭建及原理

从新启动从断开主
redis集群搭建及原理
可以看到从数据库日志输出
同步失败消记录,还有集群状态从失败到正常

登陆交互式查看集群状态
redis集群搭建及原理
6381是一个已经失败的集群状态
6382成为master

再次启动6381看到在连接6382master
redis集群搭建及原理
查看集群节点6381已成为从
redis集群搭建及原理

cluster节点操作命令
查看集群节点信息
cluster nodes
进入一个从节点redis,切换其主节点
cluster replicate <master-id>
发现一个新节点,新增主点点
cluster meet ip:port
忽略一个没有solf的节点
cluster forget <id>
手动故障转移
cluster failover