Redis集群介绍
redis主从,解决了redis单点问题,但是没有实现redis状态监控及故障自动切换,于是后来又引入了sentinel(哨兵)解决此问题。但是依然没能解决数据的一个并发读写的问题,那么Redis 集群就是来解决此问题的,它是一个提供在多个Redis节点间共享数据的程序集。Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下可以继续处理命令。
Redis 集群的优势
自动分割数据到不同的节点上。整个集群的部分节点失败或者不可达的情况下能够继续处理命令。要让集群正常运作至少需要三个主节点,为了实现主节点的高可用, 强烈建议使用六个节点: 其中三个为主节点, 而其余三个则是各个主节点的从节点。
Redis集群的工作原理
Redis 集群没有使用一致性hash,而是引入了 哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点那么:
节点 A 包含 0 到 5460号哈希槽
节点 B 包含5461到10922号哈希槽
节点 C 包含10923到16383号哈希槽
这种结构很容易添加或者删除节点,比如如果我想新添加个节点D,我需要从节点 A, B, C中得部分槽到D上。如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态
Redis 集群的主从复制模型
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品。
在上面具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5461到10922这个范围的槽而不可用。
然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了,不过当B和B1 都失败后,集群是不可用的。
集群环境
6台机器,每台机器上跑一个redis实例
server1 | 192.168.179.99 | redis1 |
server2 | 192.168.179.100 | redis2 |
server3 | 192.168.179.101 | redis3 |
server4 | 192.168.179.102 | redis4 |
server5 | 192.168.179.103 | redis5 |
server6 | 192.168.179.104 | redis6 |
Redis bind配置 ,首先说结论:
(0)bind 127.0.0.1, 只能在本地机器连接
(1)bind 127.0.0.1 192.168.2.14,可以通过 redis-cli -p 127.0.0.1 或 redis-cli -p 192.168.2.14 链接,就是说127.0.0.1只能是本地使用,所以bind 127.0.0.1仅支持本机,而bind 192.168.2.14 所有可以通过192.168.2.14访问到 192.168.2.14这个服务器的机器,都可以通过 redis-cli -p 192.168.2.14链接redis
(2)bind 0.0.0.0 配置成0.0.0.0 这个redis所在的服务器支持几个ip来连接,就可以通过这几个ip来连接redis(举例说明:假设A服务器 通过 ip addr 查看这个服务器的ip有三个,分别是127.0.0.1,192.168.2.14,336.334.224.1,那么就意味着你可以通过这三个ip来连接redis,你能通过哪个ip可以链接到A服务器,你就可以通过这个ip来连接redis)
(3)如果不填 ,效果和 bind 0.0.0.0一样
通过上面也大概能猜到,bind 配置就是通过你配置的ip来访问 redis服务的(就是通过127.0.0.1或192.168.2.14来连接,谁能访问到 bind 后面配置的ip,谁就可以通过这个ip来连接redis)
[apps@redis-6.0.6]$ /apps/svr/redis-6.0.6/src/redis-cli -a Ztredis123! -p 7000 -h 10.196.42.155
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
10.196.42.155:7000> exit
配置集群
配置redis配置文件
[root@localhost redis]# vim 6379.conf --在192.168.179.99-192.168.179.104每个redis实例的配置文件中,开启如下参数,让redis处于集群模式下
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
appendonly yes
重启查看相关信息
#重启redis服务
[root@localhost ~]# ps -ef | grep redis | grep -v grep
root 1320 1 0 22:40 ? 00:00:04 /usr/local/redis/bin/redis-server 0.0.0.0:6379 [cluster]
[root@localhost 6379]# ll /usr/local/redis/6379
total 8
-rw-r--r-- 1 root root 0 Apr 7 09:13 appendonly.aof
-rw-r--r-- 1 root root 92 Apr 7 09:13 dump.rdb
-rw-r--r-- 1 root root 114 Apr 7 09:13 nodes-6379.conf
192.168.179.99上查看:
[root@localhost ~]# cat /usr/local/redis/6379/nodes-6379.conf
c283d9be56672a6d130c93d81c1c72cef399211e :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
192.168.179.100上查看:
[root@localhost ~]# cat /usr/local/redis/6379/nodes-6379.conf
f57640f43774b1383e4965206a4142e066507864 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
搭建集群
现在已经有了六个正在运行中的 Redis 实例, 接下来就可以直接使用这些实例来创建集群, 并为每个节点编写配置文件。如果使用的是Redis 5的版本,可以直接使用redis-cli命令创建新集群,检查或重新硬化现有集群等等。对于Redis版本3或4,使用redis-trib.rb创建集群,它是一个Ruby程序。可以在Redis源代码的src目录下找到它。
(1)如果6个节点全部在一台机器上使用如下方法,只做参考不细说
首先可以选择创建一个新的 redis-cluster 目录,并在此目录中创建六个以端口号为名字的子目录,稍后我们在将每个目录中运行一个 Redis 实例, 命令如下:
# 创建redis-cluster目录:
mkdir /usr/local/redis-cluster/
cd /usr/local/redis-cluster/
# 创建六个实例目录:
mkdir 7000 7001 7002 7003 7004 7005
# 用初始化脚本,快速创建实例配置文件,日志目录:
/usr/src/redis-stable/utils/install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis serv
Selected config:
Port : 7000
Config file : /usr/local/redis-cluster/7000/7000.conf
Log file : /usr/local/redis-cluster/7000/7000.log
Data dir : /usr/local/redis-cluster/7000/
Executable : /usr/local/redis/bin/redis-server
Cli Executable : /usr/local/redis/bin/redis-cli
Copied /tmp/7000.conf => /etc/init.d/redis_7000
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
用相同方式连接创建余下5个redis实例。
创建集群:
/usr/local/redis/bin/redis-cli --cluster create 127.0.0.1:7000 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 \
--cluster-replicas 1
(2)六个节点在不同的机器上使用下面方法
不带密码认证
/usr/local/redis/bin/redis-cli --cluster create 192.168.179.99:6379 192.168.179.100:6379
192.168.179.101:6379 192.168.179.102:6379 192.168.179.103:6379 192.168.179.104:6379
--cluster-replicas 1
如果带有密码使用下面:
[apps@WXKYPL196042156 redis-6.0.6]$ cat redis.conf | grep require
#requirepass配置可以让用户使用AUTH命令来认证密码,才能使用其他命令
requirepass Ztredis123!
#如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。[apps@WXKYPL196042155 redis-6.0.6]$ sudo /apps/svr/redis-6.0.6/src/redis-cli --cluster create 10.196.42.155:7000 10.196.42.156:7000 10.196.42.157:7000 10.196.42.158:7000 10.196.42.159:7000 10.196.42.160:7000 --cluster-replicas 1 -a Ztredis123!
--会自动为我们指定哪些是主节点,哪些是从节点,不需要我们一个一个去指定,--cluster-replicas 1表示为集群中的每个主节点创建一个从节点。
[root@localhost ~]# /usr/local/redis/bin/redis-cli --cluster create 192.168.179.99:6379 192.168.179.100:6379 192.168.179.101:6379 192.168.179.102:6379 192.168.179.103:6379 192.168.179.104:6379 --cluster-replicas 1
#给主节点分配散列槽
>>> 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.179.103:6379 to 192.168.179.99:6379
Adding replica 192.168.179.104:6379 to 192.168.179.100:6379
Adding replica 192.168.179.102:6379 to 192.168.179.101:6379
#显示主从节点的ID和散列槽分配情况以及主从关系
M: c283d9be56672a6d130c93d81c1c72cef399211e 192.168.179.99:6379
slots:[0-5460] (5461 slots) master
M: f57640f43774b1383e4965206a4142e066507864 192.168.179.100:6379
slots:[5461-10922] (5462 slots) master
M: 16d6060e148a4279ed60f884302b7bc500203c7a 192.168.179.101:6379
slots:[10923-16383] (5461 slots) master
S: bff10167c57f975b59d7be6b484101144f274b7d 192.168.179.102:6379
replicates 16d6060e148a4279ed60f884302b7bc500203c7a
S: e60ecdef02c8e89b2cbdd1c2eabd3bd8a828a691 192.168.179.103:6379
replicates c283d9be56672a6d130c93d81c1c72cef399211e
S: ea7e259588114e3ca0838d6d1a6cf31d6ec32a5e 192.168.179.104:6379
replicates f57640f43774b1383e4965206a4142e066507864
#输入yes
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.179.99:6379)
M: c283d9be56672a6d130c93d81c1c72cef399211e 192.168.179.99:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 16d6060e148a4279ed60f884302b7bc500203c7a 192.168.179.101:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: bff10167c57f975b59d7be6b484101144f274b7d 192.168.179.102:6379
slots: (0 slots) slave
replicates 16d6060e148a4279ed60f884302b7bc500203c7a
M: f57640f43774b1383e4965206a4142e066507864 192.168.179.100:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: ea7e259588114e3ca0838d6d1a6cf31d6ec32a5e 192.168.179.104:6379
slots: (0 slots) slave
replicates f57640f43774b1383e4965206a4142e066507864
S: e60ecdef02c8e89b2cbdd1c2eabd3bd8a828a691 192.168.179.103:6379
slots: (0 slots) slave
replicates c283d9be56672a6d130c93d81c1c72cef399211e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
#可以看到192.168.179.99节点为master并且散列槽范围为[0-5460] 同理其他master节点
M: c283d9be56672a6d130c93d81c1c72cef399211e 192.168.179.99:6379
slots:[0-5460] (5461 slots) master
M: f57640f43774b1383e4965206a4142e066507864 192.168.179.100:6379
slots:[5461-10922] (5462 slots) master
M: 16d6060e148a4279ed60f884302b7bc500203c7a 192.168.179.101:6379
slots:[10923-16383] (5461 slots) master
#可以看到192.168.179.102为从节点,其主节点是16d6060e148a4279ed60f884302b7bc500203c7a即为
# 192.168.179.101节点 192.168.179.102------》192.168.179.101
S: bff10167c57f975b59d7be6b484101144f274b7d 192.168.179.102:6379
slots: (0 slots) slave
replicates 16d6060e148a4279ed60f884302b7bc500203c7a
#可以看到192.168.179.104为从节点,其主节点f57640f43774b1383e4965206a4142e066507864即为
#192.168.179.100节点 192.168.179.104------》192.168.179.100
S: ea7e259588114e3ca0838d6d1a6cf31d6ec32a5e 192.168.179.104:6379
slots: (0 slots) slave
replicates f57640f43774b1383e4965206a4142e066507864
#可以看到192.168.179.103为从节点,其主节点c283d9be56672a6d130c93d81c1c72cef399211e即为
#192.168.179.99节点 192.168.179.103------》192.168.179.99
S: e60ecdef02c8e89b2cbdd1c2eabd3bd8a828a691 192.168.179.103:6379
slots: (0 slots) slave
replicates c283d9be56672a6d130c93d81c1c72cef399211e
从节点--------------》主节点
192.168.179.103------》192.168.179.99
192.168.179.104------》192.168.179.100
192.168.179.102------》192.168.179.101
集群信息查看(其实和上面一样,只不过节点ID看的眼花缭乱而已)
[root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379 cluster nodes
16d6060e148a4279ed60f884302b7bc500203c7a 192.168.179.101:6379@16379 master - 0 1592410380504 3 connected 10923-16383
c283d9be56672a6d130c93d81c1c72cef399211e 192.168.179.99:6379@16379 myself,master - 0 1592410380000 1 connected 0-5460
bff10167c57f975b59d7be6b484101144f274b7d 192.168.179.102:6379@16379 slave 16d6060e148a4279ed60f884302b7bc500203c7a 0 1592410380504 4 connected
f57640f43774b1383e4965206a4142e066507864 192.168.179.100:6379@16379 master - 0 1592410381510 2 connected 5461-10922
ea7e259588114e3ca0838d6d1a6cf31d6ec32a5e 192.168.179.104:6379@16379 slave f57640f43774b1383e4965206a4142e066507864 0 1592410381107 6 connected
e60ecdef02c8e89b2cbdd1c2eabd3bd8a828a691 192.168.179.103:6379@16379 slave c283d9be56672a6d130c93d81c1c72cef399211e 0 1592410381510 5 connected
集群状态查看
[root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379 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:1953
cluster_stats_messages_pong_sent:1876
cluster_stats_messages_sent:3829
cluster_stats_messages_ping_received:1871
cluster_stats_messages_pong_received:1953
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:3829
散列槽和数据同步测试
通常情况下,如果客户端请求的数据不在节点上,节点会回复 MOVED 重定向信息,客户端根据该信息再请求正确的节点。对于正在迁移的slot数据,保证客户端仍然能正常访问的设计如下:
192.168.179.102
[root@localhost ~]# /usr/local/redis/bin/redis-cli
127.0.0.1:6379> set key values
(error) MOVED 12539 192.168.179.101:6379
# 可以看到不能在该散列槽创建,要在101上创建,在插入数据的时候根据散列值来决定存放在哪台redis上面
192.168.179.101
[root@localhost ~]# /usr/local/redis/bin/redis-cli
127.0.0.1:6379> set key values;
OK
127.0.0.1:6379> role
1) "master"
2) (integer) 2234
3) 1) 1) "192.168.179.102"
2) "6379"
3) "2234"
#可以看到192.168.179.101是master节点其从节点是192.168.179.102
#来到192.168.179.102上,可以看到已经同步了主节点192.168.179.101的数据了
127.0.0.1:6379> role
1) "slave"
2) "192.168.179.101"
3) (integer) 6379
4) "connected"
5) (integer) 2276
127.0.0.1:6379> keys*
(error) ERR unknown command `keys*`, with args beginning with:
127.0.0.1:6379> keys *
1) "key"
故障测试
[root@localhost ~]# /usr/local/redis/bin/redis-cli --cluster check 192.168.179.99:6379
192.168.179.99:6379 (c283d9be...) -> 0 keys | 5461 slots | 1 slaves.
192.168.179.101:6379 (16d6060e...) -> 1 keys | 5461 slots | 1 slaves.
192.168.179.100:6379 (f57640f4...) -> 0 keys | 5462 slots | 1 slaves.
#将192.168.179.99的redis pkill
#下面结果可以看到192.168.179.99节点由master变为slave了,其从节点192.168.179.103变为主节点了
[root@localhost ~]# pkill redis
[root@localhost ~]# /usr/local/redis/bin/redis-cli --cluster check 192.168.179.99:6379
Could not connect to Redis at 192.168.179.99:6379: Connection refused
[root@localhost ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@localhost ~]# /usr/local/redis/bin/redis-cli --cluster check 192.168.179.99:6379
192.168.179.101:6379 (16d6060e...) -> 1 keys | 5461 slots | 1 slaves.
192.168.179.100:6379 (f57640f4...) -> 0 keys | 5462 slots | 1 slaves.
192.168.179.103:6379 (e60ecdef...) -> 0 keys | 5461 slots | 1 slaves.