Redis Cluster集群

Redis Cluster是Redis官方提供的分布式解决方案。当遇到内存、并发、流量等瓶颈时,就可以采用Cluster架构达到负载均衡目的。

一、redis-cluster集群的优势

首先redis单实例主要有单点,容量有限,流量压力上限的问题

Redis单点故障,可以通过主从复制replication,和自动故障转移sentinel哨兵机制。但Redis单Master实例提供读写服务,仍然有容量和压力问题。

并发问题

redis官方声称可以达到 10万/每秒,每秒执行10万条命令
假如业务需要每秒100万的命令执行呢?

解决方案:

正确的应该是考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力。那么一堆机器做一件事.还需要一定的机制保证数据分区,并且数据在各个主Master节点间不能混乱

总结:

redis cluster:主要是针对海量数据+高并发+高可用的场景,海量数据,如果你的数据量很大,那么建议就用redis cluster

1、redis-cluster特点

1.所有的redis节点彼此互联(PING-PONG机制)。
2.客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
3.节点的fail是通过集群中超过半数的节点检测失效时才生效。

2、redis-cluster数据分布

分布式数据分布方式为一致性hsah方式。

redis集群的hash slot方式:

Redis集群中有16384个哈希槽,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新

3、数据分布存储原理

Redis 集群使用数据分片(sharding)来实现:Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数(集群使用公式 CRC16(key) % 16384),这样每个key 都会对应一个编号在 0-16384 之间的哈希槽,那么redis就会把这个key 分配到对应范围的节点上了。同样,当连接三个节点任何一个节点想获取这个key时,也会这样的算法,然后内部跳转到存放这个key节点上获取数据。

例如三个节点:哈希槽分布的值如下:

cluster1:  0-5460
cluster2:  5461-10922
cluster3:  10923-16383

4、redis-cluster主从模式

redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉.

1.主从切换机制
选举过程是集群中所有master参与,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作.  #故障节点对应的从节点自动升级为主节点


2.什么时候整个集群就不能用了?
如果集群任意一个主节点挂掉,且当前主节点没有从节点,则集群将无法继续,因为没有办法为这个节点承担范围内的哈希槽提供服务。但是,如果这个主节点和所对应的从节点同时失败,则Redis Cluster无法继续运行。

二、集群部署

1、环境准备

  • 准备三台机器
  • 全部关闭防火墙和selinux

规划构架两种方案

  1. 单机多实例
  2. 多机器部署
    • 三台机器,每台机器上两个redis实例
    • 一个master一个slave
    • 第一列做主库,第二列做备库

记得选出控制节点

redis-cluster1 192.168.60.131   7000、7001
redis-cluster2 192.168.60.132   7002、7003
redis-cluster3 192.168.60.133   7004、7005

2、部署

1)创建文件存放目录(都做)

mkdir /data

2)安装redis需要的工具(都做)

yum install -y gcc automake autoconf litool make vim wget net-tools

3)下载redis的压缩包(都做)

这里推荐官网

wget https://download.redis.io/releases/redis-7.0.9.tar.gz

4)解压redis的压缩包到指定文件目录(都做)

tar zxvf redis-7.0.9.tar.gz -C /data/

5)移动至/data/目录下并改名(都做)

cd /data/
mv redis-7.0.9/ redis

6)进入redis/目录下,并编译(都做)

cd redis/
make

7)创建存放数据的目录(都做)

mkdir /data/redis/data

3、创建节点目录

按照规划在每台redis节点的安装目录中创建对应的目录(以端口号命名)

1)创建集群目录(都做)

mkdir cluster
cd cluster

2)创建节点目录(分开做)

  1. cluster1

    [root@redis-cluster1 cluster]# mkdir 7000 7001
    
  2. cluster2

    [root@redis-cluster2 cluster]# mkdir 7002 7003
    
  3. cluster3

    [root@redis-cluster3 cluster]# mkdir 7004 7005
    

3)拷贝配置文件到节点目录中

  1. cluster1

    [root@redis-cluster1 cluster]# cp /data/redis/redis.conf 7000/
    
    [root@redis-cluster1 cluster]# cp /data/redis/redis.conf 7001/
    
  2. cluster2

    [root@redis-cluster2 cluster]# cp /data/redis/redis.conf 7002/
    
    [root@redis-cluster2 cluster]# cp /data/redis/redis.conf 7003/
    
  3. cluster3

    [root@redis-cluster3 cluster]# cp /data/redis/redis.conf 7004/
    
    [root@redis-cluster3 cluster]# cp /data/redis/redis.conf 7005/
    

4)修改集群每个redis配置文件

主要是端口、ip、pid文件

用7000端口来举例(别的端口照做)

cd 7000/
vim redis.conf

修改如下:

  1. bind +ip

    bind 192.168.60.131
    
  2. port +端口

    port 7000
    
  3. protected-mode 密码保护

    protected-mode yes
    改为↓
    protected-mode no
    
  4. redis 后台运行

    daemonize no
    改为↓
    daemonize yes
    
  5. pid文件

    运行多个实例时,需要指定不同的pid文件

    pidfile /var/run/redis_7000.pid
    
  6. 日志文件位置

    运行多实例时,需要将文件修改的不同

    logfile /var/log/redis_7000.log
    
  7. 存放数据目录

    dir /data/redis/data
    
  8. 开启AOF持久化

    edis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。

    appendonly no
    改为↓
    appendonly yes
    
  9. 启用集群(为注释内容)

    cluster-enabled yes 	//把注释取消
    
  10. 集群配置文件(为注释内容)

    由redis自动更新,不需要手动配置,运行多实例时请注修改为对应端口

    cluster-config-file nodes-6379.conf		//把注释取消
    改为↓
    cluster-config-file nodes-7000.conf
    
  11. 集群节点超时时间(为注释内容)

    单位毫秒。集群节点超时时间,即集群中主从节点断开连接时间阈值,超过该值则认为主节点不可以,从节点将有可能转为master

    cluster-node-timeout 15000		//把注释取消
    改为↓
    cluster-node-timeout 5000
    
  12. 判断节点与master短线时间是否过长(为注释内容)

    在进行故障转移的时候全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间了导致数据过于陈旧,不应该被提升为master。该参数就是用来判断slave节点与master断线的时间是否过长

    cluster-replica-validity-factor 10		//把注释取消
    
  13. 主机的最小连接数(为注释内容)

    一个主机将保持连接的最小数量的从机,以便另一个从机迁移到不再被任何从机覆盖的主机

    cluster-migration-barrier 1		//把注释取消
    
  14. 集群中的所有slot(16384个)全部覆盖,才能提供服务(为注释内容)

    cluster-require-full-coverage yes		//把注释取消
    

*.所有节点配置文件全部修改切记需要修改的ip、端口、pid文件...避免冲突。确保所有机器都修改

4、启动三台机器上面的每个节点(都做)

1)移动到src目录下

cd /data/redis/src/

2)分别启动节点(每台机器分开做)

  1. cluster1

    [root@redis-cluster1 src]# ./redis-server ../cluster/7000/redis.conf
    
    [root@redis-cluster1 src]# ./redis-server ../cluster/7001/redis.conf
    
  2. cluster2

    [root@redis-cluster2 src]# ./redis-server ../cluster/7002/redis.conf  
    
    [root@redis-cluster2 src]# ./redis-server ../cluster/7003/redis.conf
    
  3. cluster3

    [root@redis-cluster3 src]# ./redis-server ../cluster/7004/redis.conf 
    
    [root@redis-cluster3 src]# ./redis-server ../cluster/7005/redis.conf
    

5、查看端口(都看)

[root@redis-cluster1 7000]# netstat -lntp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 192.168.60.131:17000    0.0.0.0:*               LISTEN      16357/../../src/red 
    tcp        0      0 192.168.60.131:17001    0.0.0.0:*               LISTEN      16350/../../src/red 
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      930/sshd            
    tcp        0      0 192.168.60.131:7000     0.0.0.0:*               LISTEN      16357/../../src/red 
    tcp        0      0 192.168.60.131:7001     0.0.0.0:*               LISTEN      16350/../../src/red 
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1143/master         
    tcp6       0      0 :::22                   :::*                    LISTEN      930/sshd            
    tcp6       0      0 ::1:25                  :::*                    LISTEN      1143/master 
[root@redis-cluster2 7002]# netstat -lntp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 192.168.60.132:17002    0.0.0.0:*               LISTEN      22895/./redis-serve 
    tcp        0      0 192.168.60.132:17003    0.0.0.0:*               LISTEN      22901/./redis-serve 
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      942/sshd            
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1302/master         
    tcp        0      0 192.168.60.132:7002     0.0.0.0:*               LISTEN      22895/./redis-serve 
    tcp        0      0 192.168.60.132:7003     0.0.0.0:*               LISTEN      22901/./redis-serve 
    tcp6       0      0 :::22                   :::*                    LISTEN      942/sshd            
    tcp6       0      0 ::1:25                  :::*                    LISTEN      1302/master  
[root@redis-cluster3 7004]# netstat -lntp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 192.168.60.133:17004    0.0.0.0:*               LISTEN      6031/./redis-server 
    tcp        0      0 192.168.60.133:17005    0.0.0.0:*               LISTEN      6037/./redis-server 
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      934/sshd            
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1138/master         
    tcp        0      0 192.168.60.133:7004     0.0.0.0:*               LISTEN      6031/./redis-server 
    tcp        0      0 192.168.60.133:7005     0.0.0.0:*               LISTEN      6037/./redis-server 
    tcp6       0      0 :::22                   :::*                    LISTEN      934/sshd            
    tcp6       0      0 ::1:25                  :::*                    LISTEN      1138/master     

6、创建集群

在其中一个节点操作就可以

redis节点搭建起来后,需要完成redis cluster集群搭建,搭建集群过程中,需要保证6个redis实例都是运行状态。
Redis是根据IP和Port的顺序,确定master和slave的,所以要排好序,再执行

这里用cluster1举例

1)移动至src目录下

cd /data/redis/src/

2)根据参数填相应的数据

参数:

--cluster-replicas 1:表示为集群中的每个主节点创建一个从节点.书写流程:主节点ip+port 对应一个从节点ip+port(正常是前面三个节点为主节点,后面的为从节点)
./redis-cli --cluster create --cluster-replicas 1 192.168.60.131:7000 192.168.60.131:7001 192.168.60.132:7002 192.168.60.132:7003 192.168.60.133:7004 192.168.60.133:7005

会出现以下内容:

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.60.132:7003 to 192.168.60.131:7000
Adding replica 192.168.60.133:7005 to 192.168.60.132:7002
Adding replica 192.168.60.131:7001 to 192.168.60.133:7004
M: f42afc454500dd6e6cc68c9c1da6e2ce49061d3e 192.168.60.131:7000
   slots:[0-5460] (5461 slots) master
S: f3a4308dc2e5c3f182a7febd8ac1ec21d9e713c8 192.168.60.131:7001
   replicates e31a162eb524471ff6212db22f1f9b3e45e66a9a
M: 80f4a03041ef8de3144bc54375febb829197ec6e 192.168.60.132:7002
   slots:[5461-10922] (5462 slots) master
S: 995f45852ae984b852c1248be947f493bf772de2 192.168.60.132:7003
   replicates f42afc454500dd6e6cc68c9c1da6e2ce49061d3e
M: e31a162eb524471ff6212db22f1f9b3e45e66a9a 192.168.60.133:7004
   slots:[10923-16383] (5461 slots) master
S: d8efef936ffd10b6c24638dd4bccead0f1389a53 192.168.60.133:7005
   replicates 80f4a03041ef8de3144bc54375febb829197ec6e
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 192.168.60.131:7000)
M: f42afc454500dd6e6cc68c9c1da6e2ce49061d3e 192.168.60.131:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: d8efef936ffd10b6c24638dd4bccead0f1389a53 192.168.60.133:7005
   slots: (0 slots) slave
   replicates 80f4a03041ef8de3144bc54375febb829197ec6e
M: 80f4a03041ef8de3144bc54375febb829197ec6e 192.168.60.132:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: e31a162eb524471ff6212db22f1f9b3e45e66a9a 192.168.60.133:7004
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: f3a4308dc2e5c3f182a7febd8ac1ec21d9e713c8 192.168.60.131:7001
   slots: (0 slots) slave
   replicates e31a162eb524471ff6212db22f1f9b3e45e66a9a
S: 995f45852ae984b852c1248be947f493bf772de2 192.168.60.132:7003
   slots: (0 slots) slave
   replicates f42afc454500dd6e6cc68c9c1da6e2ce49061d3e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

创建集群完成

7、查看集群连接集群中任一节点

这里连接192.168.60.131:7000

1)登录集群客户端,-c标识以集群方式登录

[root@redis-cluster1 src]# ./redis-cli -h 192.168.60.131 -c -p 7000

2)查看集群信息

192.168.60.131:7000> cluster info
    cluster_state:ok		//集群状态
    cluster_slots_assigned:16384	//分配的槽
    cluster_slots_ok:16384
    cluster_slots_pfail:0
    cluster_slots_fail:0
    cluster_known_nodes:6		//集群实例数
    cluster_size:3
    cluster_current_epoch:6
    cluster_my_epoch:1
    cluster_stats_messages_ping_sent:645
    cluster_stats_messages_pong_sent:641
    cluster_stats_messages_sent:1286
    cluster_stats_messages_ping_received:636
    cluster_stats_messages_pong_received:645
    cluster_stats_messages_meet_received:5
    cluster_stats_messages_received:1286
    total_cluster_links_buffer_limit_exceeded:0
192.168.60.131:7000> CLUSTER NODES		//查看集群实例
    d8efef936ffd10b6c24638dd4bccead0f1389a53 192.168.60.133:7005@17005 slave 80f4a03041ef8de3144bc54375febb829197ec6e 0 1702398918178 3 connected
    80f4a03041ef8de3144bc54375febb829197ec6e 192.168.60.132:7002@17002 master - 0 1702398920196 3 connected 5461-10922
    f42afc454500dd6e6cc68c9c1da6e2ce49061d3e 192.168.60.131:7000@17000 myself,master - 0 1702398919000 1 connected 0-5460
    e31a162eb524471ff6212db22f1f9b3e45e66a9a 192.168.60.133:7004@17004 master - 0 1702398919000 5 connected 10923-16383
    f3a4308dc2e5c3f182a7febd8ac1ec21d9e713c8 192.168.60.131:7001@17001 slave e31a162eb524471ff6212db22f1f9b3e45e66a9a 0 1702398918000 5 connected
    995f45852ae984b852c1248be947f493bf772de2 192.168.60.132:7003@17003 slave f42afc454500dd6e6cc68c9c1da6e2ce49061d3e 0 1702398919188 1 connected

参数解释:

runid: 该行描述的节点的id。
ip:prot: 该行描述的节点的ip和port
flags: 分隔的标记位,可能的值有:
1.master: 该行描述的节点是master
2.slave: 该行描述的节点是slave
3.fail?:该行描述的节点可能不可用
4.fail:该行描述的节点不可用(故障)
master_runid: 该行描述的节点的master的id,如果本身是master则显示-
ping-sent: 最近一次发送ping的Unix时间戳,0表示未发送过
pong-recv:最近一次收到pong的Unix时间戳,0表示未收到过
config-epoch: 主从切换的次数
link-state: 连接状态,connnected 和 disconnected
hash slot: 该行描述的master中存储的key的hash的范围

三、集群操作

客户端登录

测试链接redis,存取数据(链接集群中任意一台机器就可以。

存:

[root@redis-cluster1 src]# ./redis-cli -h 192.168.60.131 -c -p 7000
192.168.60.131:7000> PING
PONG
192.168.60.131:7000> SET name zhangsan
-> Redirected to slot [5798] located at 192.168.60.132:7002
OK
192.168.60.132:7002>		//可以发现前面的IP变了

读:

[root@redis-cluster3 src]# ./redis-cli -h 192.168.60.133 -c -p 7004
192.168.60.133:7004> PING
PONG
192.168.60.133:7004> GET name
-> Redirected to slot [5798] located at 192.168.60.132:7002
"zhangsan"
192.168.60.132:7002>		//发现IP还是变成之前的IP
192.168.60.132:7002> exists name		//查看某一个key是否存在
(integer) 1

四、主从复制

测试:

将节点cluster1的主节点7000端口的redis关掉

[root@redis-cluster1 src]# ps -ef |grep redis
root      16350      1  0 00:00 ?        00:00:07 ../../src/redis-server 192.168.60.131:7001 [cluster]
root      16357      1  0 00:00 ?        00:00:07 ../../src/redis-server 192.168.60.131:7000 [cluster]
root      16390   1593  0 00:53 pts/0    00:00:00 grep --color=auto redis
[root@redis-cluster1 src]# kill -9 16357

redis_cluster001.png

可以看到7000端口这个redis已经是fail失败的了。

将该节点的7000端口redis启动在查看

./redis-server ../cluster/7000/redis.conf 
192.168.60.133:7004> CLUSTER nodes

redis_cluster001.png

可以看见已经主从切换了