本文介绍了使用redis如何搭建集群环境。集群是指多个提供相同服务的机器联合在一起构成一个可用性更高的服务体系。可用性高指的是某台机器因故宕机后不会影响或较小的影响整体,从而能够为外部提供持续稳定的服务。
以下基于redis-6.2.1版本,系统为centos7 64位
官方文档:http://www.redis.cn/documentation.html
redis集群是基于主从的集群,集群中各个节点有主节点有它的从节点。
1、集群搭建
删除掉所有rdb,aof文件。将之前的服务都停掉。删除刚才除redis6379.conf之外的其他两个从机的配置文件。
重新编写配置文件:
redis6379.conf
include /myredis/redis.conf
daemonize yes
pidfile "/var/run/redis_6379.pid"
port 6379
dbfilename "dump6379.rdb"
appendonly no
cluster-enabled yes //开启集群模式
cluster-config-file nodes-6379.conf //当前节点的配置文件名字
cluster-node-timeout 15000 //节点失联时间(毫秒):超过该时间,集群自动进行主从切换
cp redis6379.conf redis6380.conf
cp redis6379.conf redis6381.conf
cp redis6379.conf redis6389.conf
cp redis6379.conf redis6390.conf
cp redis6379.conf redis6391.conf
替换配置文件中的值:
sed -i “s/6379/6380/g” redis6380.conf
sed -i “s/6379/6381/g” redis6381.conf
sed -i “s/6379/6389/g” redis6389.conf
sed -i “s/6379/6390/g” redis6390.conf
sed -i “s/6379/6391/g” redis6391.conf
查看配置文件是否正确。
检查是否没有redis服务在启动:ps -ef | grep redis
启动6个redis服务:
cd /myredis
redis-server redis6379.conf
redis-server redis6380.conf
redis-server redis6381.conf
redis-server redis6389.conf
redis-server redis6390.conf
redis-server redis6391.conf
检查是否成功启动,节点配置文件是否正常:
ps -ef | grep redis
将6个服务合成集群:(下面命令中的ip要使用真是ip。低版本的redis需要额外安装其他环境才能执行。)
cd /opt/redis-6.2.1/src
redis-cli --cluster create --cluster-replicas 1 192.168.44.128:6379 192.168.44.128:6380 192.168.44.128:6381 192.168.44.128:6389 192.168.44.128:6390 192.168.44.128:6391
–cluster-replicas 1:集群方式,1代表最简单的方式。一个主机一个从机。
6379、6380、6381是master
Can I set the above configuration? 是否接受这种集群配置:yes。
集群创建成功:
2、集群信息
这里的[OK] All 16384 slots covered.表明了此集群有16384 个slots。当redis集群储存Key时,会使用一个算法来计算键key属于哪个槽,相当于HashMap中使用hash算法寻找key的索引值一样。(算法:CRC16(key) % 16384,(CRC16(key) 用于计算键key的CRC16校验和。)
连接上之后可以使用cluster nodes查看集群信息,能查看到哪个是slave,哪个是master,还有当前在的机器是什么角色。相当于主从中的info replication。
上图显示的信息中,前面的是每台机器的id,中间部分表明它是主还是从,然后如果是从的话,从于哪个id的机器。如果是主的话,它储存的插槽范围是什么。
上图可以看到,第一行中6389是slave,他的主服务器id是8eb282bfabe9fac2fcdcbe3c84b7feca43d87bf1,即第二行的6380。
第三行中6391是slave,他的主是48dbe4075fbbad702d04b84de1753ba1da3a14ed,即第五行的6379
第四行的6381是当前机器,是master;最后一台机器6390是slave,它的主是f1fbd5cfb739b3b68c5aa7696750b2dc76852ad4即第四行的6381
上图也可以看到每个master后面都标了它处理的插槽(slots)范围:
节点 6379 负责处理 0 号至 5460 号插槽。
节点 6380 负责处理 5461 号至 10922 号插槽。
节点 6381 负责处理 10923 号至 16383 号插槽。
集群中的每个节点只负责处理它这一部分插槽,比如:当set key value时使用算法得出的key计算后的值为100,那就将此key-value存放在节点6379 中。
3、集群连接
redis-cli -p 6379 这样连接是普通的连接方式,使用这种方式连接上6379,那就只能向6379中存数据,当你的key计算得结果是存放在其他节点上的,那就会报错。比如下图中使用redis-cli -p 6379连接,然后set nb 11111,redis返回的是(error) MOVED 13940 192.168.44.128:6381,就是说这个key计算的结果是13940,应该在6381上存放,请移动到那个节点在进行set操作。
redis集群方式连接:redisl-cli -c -p 6379。后面的端口号写6台中的任意一台都行,因为redis集群是无中心化的。比如下图,脸上6389,然后set nv 11111,它显示重定向到6381上然后储存了,这是我们的命令行前面显示的也变成192.168.44.128:6381>
了,集群方式连接会根据你的命令自动跳到它该去的节点上。(set get命令都会,该去哪存去哪存,该去哪读取哪读)
由于redis集群slots的设计,不在一个槽中的key是无法同时操作的,即无法进行普通的mset、mget操作,因为无法确保操作的多个key都在一个槽中。
但可以通过{}来定义组(存放时根据组名计算应该将这些key存在哪个槽中)的概念,从而使key中{}内相同内容的键值对放到一个slot中去。
4、节点分配原则
一个redis集群至少要有三个节点。分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上。(保证一定的可用性)
5、其他集群操作
cluster keyslot key 计算key的slots值,比如cluster keyslot han得到1977,那么set han xu 时,就会将它存在6379中。
cluster countkeysinslot num 计算num位置的槽里有几个key。比如cluster countkeysinslot 1977返回1,1977位置就有1个key(注意:在哪台master上执行,就只能看它自己的插槽范围中的东西,看不了其他范围的。比如我在6381上执行cluster countkeysinslot 1977就会返回0,因为1977并不是6381这台机器的slots)
cluster getkeysinslot num count 返回num位置的插槽中的count个key。
6、故障恢复
主机挂掉后,从机上位;主机连上后自动变为从。
主机挂掉后,从机上位变为主机,新主机也挂掉后;主从都重新启动,新主机还是主。
主从都挂掉后,再次连上,主从关系不变。
某个master宕机
当集群中某个主服务器down调,它的从就会自动升为主服务器;当down调的机器恢复后,自动变为新主的从服务器。
例如我手动执行redis-cli -p 6379 shutdown将6379这个master挂掉,再使用其他节点连接查看集群信息(不能再使用6379连接了,连接不上):
可以看到6379已经fail了,而之前它的从机6391已结变为master。(cluster-node-timeout 节点失联时间配置的是15000毫秒,所以会有一段时间才能看到显示为fail。当6379挂掉时,就立即连不上了;只是fail的信息要过失联时间才能被检测出)
执行redis-server redis6379.conf 将6379重新启动,再查看集群信息,发现它变成了6391的从服务器。
某个master和它的slave都宕机
当某个主服务器和它的从服务器们都挂掉了,那这个集群能否使用要看配置。当cluster-require-full-coverage为yes时,整个集群都挂掉;当这个值为no时,只是这个挂掉的主服务器管理的插槽部分不能使用,其他部分还能使用。这个配置默认是no。
例如我手动将6379和6391都挂掉,redis-cli -p 6379 shutdown,redis-cli -p 6391 shutdown再查看集群信息:
6379和6391都fail了。(cluster-node-timeout 节点失联时间配置的是15000毫秒,所以会有一段时间才能看到显示为fail)
整个集群挂掉后,cluster nodes并不会显示所有节点都fail。仍然是有问题的节点fail。不过当执行命令set get等时会提示(error) CLUSTERDOWN The cluster is down
注意:
当主从都挂掉后,再次启动down调的服务时,无论先启动谁,主还是主,从还是从。比如本来6379是从,6391是主,他们都宕机后,再次将6379先启动起来,那么6379仍然是从机。6391作为master仍然是fail状态。
将主从都启动后,主从关闭保持不变。
7、jedis操作集群
package com.example.demo.redis;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
/**
* @author: HanXu
* on 2021/8/22
* Class description: jedis操作redis集群
*/
public class JedisClusterDemo {
public static void main(String[] args) {
HostAndPort hostAndPort = new HostAndPort("192.168.44.128", 6379);
JedisCluster jedisCluster = new JedisCluster(hostAndPort);
jedisCluster.set("jedisClus", "qwe123");
String s = jedisCluster.get("jedisClus");
System.out.println(s);//qwe123
jedisCluster.close();
}
}
8、总结
redis集群优点:
- 扩容
- 分摊服务器压力
- 无中心化操作简单
缺点:
- 多键操作不支持(需要分组才能用),多键事务也不支持
- Lua脚本不支持
- 出现较晚,许多公司已有解决方案;转换为redis的集群方案会比较复杂。