大家都知道,现在互联网的发展迅速,单台服务器已经处理不了高并发等请求,内存存储有限,并发处理请求能力瓶颈,这是我们要,水平扩展,多台机器来处理高并发请求,实现读写分离,主服务器只来写数据,同步从服务数据,从服务器呢只是用来读数据,那么高可用系统有什么优点呢,主要就是减少停工时间,保持服务高度可用性,24小时不宕机,为客户长期稳定的提供服务。那怎样搭建一个高可用的redis集群呢,redis提供了哨兵模式,监视master服务器的健康状态,如果master服务器宕机了,会自动剔除,并且在从服务器中,通过选举机制,选出一台从服务器,升级为master,哨兵模式呢,有什么缺点呢,不停的对redis服务器做监视,加大网络开销,消耗机器的性能,这里呢,主要为大家推荐redis-cluster来搭建redis集群。

 

什么是redis-cluster

    redis3.0后支持redis-cluster,至少需要3(master)+3(slave),建立集群,采用无中心结构,这个概念和现在热门的区块链技术很相像,每个节点都可相互访问,,这里涉及到一个投票的概念,那怎样判断一台服务器挂掉了呢,半数以上的master节点访问这台master服务器时,访问不了,说明这台master宕机,集群会自动剔除,那又怎样判断一个redis集群失败了呢,半数以上的master挂掉了的话,无论是否有从服务器,集群进入fail状态。

    redis-cluster采用虚拟槽分区,所有的键根据哈希函数映射到0-16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。三个主master分别是A,B,C,它们可以是一台机器上三个端口,也可以是三台机器,采用哈希槽(hash slot)的方式分配这16384个slot的话,三个节点分别承担slot的区间是0-5460,5461-10922,10923-16383。

 

搭建redis-cluster集群

  • 下载配置文件

    由于docker安装的redis,没有redis.conf配置文件,我们需要手动下载,https://github.com/antirez/redis/blob/unstable/redis.conf

  • 修改redis.conf配置文件

    我们通过上边的url下载的redis.conf是个模板文件,我们按照下边的内容,修改配置文件,由于,redis-cluster集群至少3主3从的配置,我们这里准备6个redis的配置文件,分别是7000,7001,7002,7003,7004,7005。粗体部分需要按照实际端口号修改

关闭保护模式,用于公网访问

protected-mode no

port 7000

开启集群模式

cluster-enabled yes

cluster-config-file nodes-7000.conf

后台启动

daemonize no

pidfile /var/run/redis_7000.pid

logfile "7000.log"

#bind 127.0.0.1

masterauth 123456

requirepass 123456

 

启动redis各个节点

# docker run  -d -p 7000:7000 --net host --name myredis7000 -v /usr/local/redis/redis_cluster/7000/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7000/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

# docker run  -d -p 7001:7001 --net host --name myredis7001 -v /usr/local/redis/redis_cluster/7001/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7001/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

# docker run  -d -p 7002:7002 --net host --name myredis7002 -v /usr/local/redis/redis_cluster/7002/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7002/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

# docker run  -d -p 7003:7003 --net host --name myredis7003 -v /usr/local/redis/redis_cluster/7003/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7003/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

# docker run  -d -p 7004:7004 --net host --name myredis7004 -v /usr/local/redis/redis_cluster/7004/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7004/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

docker run  -d -p 7005:7005 --net host --name myredis7005 -v /usr/local/redis/redis_cluster/7005/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/redis_cluster/7005/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes

    这里需要注意的是,启动参数带上--net host,我自己环境测试的时候,不加的话,通过create --cluster命令创建集群时,创建失败,一直等待,其他的参数的话,例如-v 主机路径映射到docker的redis中路径,

 

查看redis各节点的启动状况

# ps -ef | grep redis

    出现下边的信息时,说明各个节点创建成功。

polkitd   14343  14325  0 10:14 ?        00:00:01 redis-server *:7000 [cluster]
polkitd   14447  14432  0 10:14 ?        00:00:01 redis-server *:7001 [cluster]
polkitd   14570  14552  0 10:14 ?        00:00:00 redis-server *:7002 [cluster]
polkitd   14702  14681  0 10:14 ?        00:00:00 redis-server *:7003 [cluster]
polkitd   14805  14790  0 10:14 ?        00:00:00 redis-server *:7004 [cluster]
polkitd   14905  14889  0 10:14 ?        00:00:00 redis-server *:7005 [cluster]

 

创建redis集群

# docker exec -it myredis7000 redis-cli -a 123456 --cluster create 192.168.100.103:7000 192.168.100.103:7001 192.168.100.103:7002 192.168.100.103:7003 192.168.100.103:7004 192.168.100.103:7005 --cluster-replicas 1

    上边的命令执行后,需要一个确认输入,主要的意思是,为我们创建完3主3从,以及存储数据的虚拟内存槽,可以的话,输入yes,出现下边的信息的话,说明创建成功。

>>> 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.100.103:7004 to 192.168.100.103:7000
Adding replica 192.168.100.103:7005 to 192.168.100.103:7001
Adding replica 192.168.100.103:7003 to 192.168.100.103:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: df053178fc56e3b1f8979e4009ca2d4f33bf5ff5 192.168.100.103:7000
   slots:[0-5460] (5461 slots) master
M: f98948fd80d3c2069b695ccc3715662e22c7553c 192.168.100.103:7001
   slots:[5461-10922] (5462 slots) master
M: 75663af230928253b8e52c869f877289fbe98834 192.168.100.103:7002
   slots:[10923-16383] (5461 slots) master
S: 5385962bc7c50917ab15feeb670a2a2e4776deac 192.168.100.103:7003
   replicates f98948fd80d3c2069b695ccc3715662e22c7553c
S: f059bca510ca725bafaf86ed1706ab7d88ff9af6 192.168.100.103:7004
   replicates 75663af230928253b8e52c869f877289fbe98834
S: aa7956bf558774a99aa71e4d592043a93743ce67 192.168.100.103:7005
   replicates df053178fc56e3b1f8979e4009ca2d4f33bf5ff5
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.100.103:7000)
M: df053178fc56e3b1f8979e4009ca2d4f33bf5ff5 192.168.100.103:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: f059bca510ca725bafaf86ed1706ab7d88ff9af6 192.168.100.103:7004
   slots: (0 slots) slave
   replicates 75663af230928253b8e52c869f877289fbe98834
M: 75663af230928253b8e52c869f877289fbe98834 192.168.100.103:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: f98948fd80d3c2069b695ccc3715662e22c7553c 192.168.100.103:7001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 5385962bc7c50917ab15feeb670a2a2e4776deac 192.168.100.103:7003
   slots: (0 slots) sl

  

进入redis集群确认主从信息以及节点信息

    走到这里,说明redis的集群已经创建成功,但是主从是怎样对应的呢,这就需要我们进入redis的集群客户端来确认,查看当前节点信息,是主,还是从,使用 info replication命令

# docker exec -it myredis7000 redis-cli -h 127.0.0.1 -c -p 7000 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:7000> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.100.103,port=7005,state=online,offset=826,lag=0
master_replid:93e8fa7aaec91fba6a2fdcf2cfc3cdc201d74452
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:826
master_repl_meaningful_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:826
127.0.0.1:7000>

    或者也可以使用 cluster nodes命令,它是以节点id来区分的,

127.0.0.1:7000> cluster nodes
f059bca510ca725bafaf86ed1706ab7d88ff9af6 192.168.100.103:7004@17004 slave 75663af230928253b8e52c869f877289fbe98834 0 1589777473584 5 connected
75663af230928253b8e52c869f877289fbe98834 192.168.100.103:7002@17002 master - 0 1589777474506 3 connected 10923-16383
df053178fc56e3b1f8979e4009ca2d4f33bf5ff5 192.168.100.103:7000@17000 myself,master - 0 1589777473000 1 connected 0-5460
f98948fd80d3c2069b695ccc3715662e22c7553c 192.168.100.103:7001@17001 master - 0 1589777473993 2 connected 5461-10922
5385962bc7c50917ab15feeb670a2a2e4776deac 192.168.100.103:7003@17003 slave f98948fd80d3c2069b695ccc3715662e22c7553c 0 1589777473000 4 connected
aa7956bf558774a99aa71e4d592043a93743ce67 192.168.100.103:7005@17005 slave df053178fc56e3b1f8979e4009ca2d4f33bf5ff5 0 1589777472971 6 connected
127.0.0.1:7000>

 

集群测试

    我的环境配置完成后,master是7000,7001,7002,所对应的从分别是7005,7003,7004,这样,就完成了集群搭建,当我们set数据是,redis会为我们将数据保存到不同端口的虚拟槽中,通过下边的命令可以看出,redis自动帮我们切换到数据存数的虚拟槽中,例如下边的-> Redirected to slot。

127.0.0.1:7000> set aa 123
OK
127.0.0.1:7000> keys *
1) "aa"
127.0.0.1:7000> get aa
"123"
127.0.0.1:7000> set bb 123
-> Redirected to slot [8620] located at 192.168.100.103:7001
OK

192.168.100.103:7001> keys *
1) "bb"
192.168.100.103:7001> get aa
-> Redirected to slot [1180] located at 192.168.100.103:7000
"123"
192.168.100.103:7000> keys *
1) "aa"
192.168.100.103:7000> get aa
"123"
192.168.100.103:7000> get bb
-> Redirected to slot [8620] located at 192.168.100.103:7001
"123"
192.168.100.103:7001> set cc 111
-> Redirected to slot [700] located at 192.168.100.103:7000
OK
192.168.100.103:7000> keys *
1) "aa"
2) "cc"
192.168.100.103:7000> get cc
"111"
192.168.100.103:7000> set dd 123
-> Redirected to slot [11212] located at 192.168.100.103:7002
OK
192.168.100.103:7002> get aa
-> Redirected to slot [1180] located at 192.168.100.103:7000
"123"
192.168.100.103:7000> get bb
-> Redirected to slot [8620] located at 192.168.100.103:7001
"123"
192.168.100.103:7001> get cc
-> Redirected to slot [700] located at 192.168.100.103:7000
"111"
192.168.100.103:7000> get dd
-> Redirected to slot [11212] located at 192.168.100.103:7002
"123"
192.168.100.103:7002> get dd
"123"
192.168.100.103:7002> get ee
-> Redirected to slot [2268] located at 192.168.100.103:7000
(nil)
192.168.100.103:7000> get aa
"123"
192.168.100.103:7000> get bb
-> Redirected to slot [8620] located at 192.168.100.103:7001
"123"
192.168.100.103:7001> keys *
1) "bb"
192.168.100.103:7001> get aa
-> Redirected to slot [1180] located at 192.168.100.103:7000
"123"
192.168.100.103:7000> keys *
1) "aa"
2) "cc"
192.168.100.103:7000> set e 1
-> Redirected to slot [15363] located at 192.168.100.103:7002
OK
192.168.100.103:7002> keys *
1) "dd"
2) "e"

    高可用的redis集群的配置就OK了, 怎么样,小伙伴们搭建的还顺利吗,中间过程肯定会有和想象中不一样的地方,我也是一边baidu,一边试,这样会加深对docker,redis,linux命令的理解以及熟练度,大家动手试试,有什么不一样的地方,或者困惑的地方,欢迎来一起交流。