🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 场景描述[](http://blog.objectspace.cn/2019/11/08/%E6%89%8B%E5%8A%A8%E6%90%AD%E5%BB%BARedis%E9%9B%86%E7%BE%A4%E5%92%8CMySQL%E4%B8%BB%E4%BB%8E%E5%90%8C%E6%AD%A5(%E9%9D%9EDocker)/#%E5%9C%BA%E6%99%AF%E6%8F%8F%E8%BF%B0) 本次会启动三台CentOS 7服务器,每台服务器上搭载三个Redis实例,一主二从,一共三个Master实例,六个Slave实例。 清单如下: > Master 1:IP:192.168.43.101 Port:7001 > > Master 2:IP:192.168.43.102 Port:7002 > > Master 3:IP:192.168.43.103 Port:7003 > > Slave 1:IP:192.168.43.101 Port:6001 > > Slave 2:IP:192.168.43.102 Port:6002 > > Slave 3:IP:192.168.43.103 Port:6003 > > Slave 4:IP:192.168.43.101 Port:6004 > > Slave 5:IP:192.168.43.102 Port:6005 > > Slave 6:IP:192.168.43.103 Port:6006 ### **修改配置文件** 熟悉Redis的应该明白,所谓Redis实例,实际上就是一个又一个的配置文件。要在服务器上启动多台不同Redis,实际上就是使用不同的配置文件来启动Redis,所以第一步我们要先对集群中的每一个Redis实例配置不一样的配置文件。 #### **绑定Redis地址** 下列三台主机上的配置文件均为Master节点配置文件(修改bind属性) ![](https://img.kancloud.cn/4a/1a/4a1a24b67d4aa7fbe1b889388c0e3983_1481x732.png) #### **修改端口号** 将端口号修改为自定义的端口号,默认为6379,修改为我们自定义的端口号。 ![](https://img.kancloud.cn/71/61/7161cb736be3b2aaee4c6d36909861ae_1612x785.png) #### **开启集群模式并设置集群配置文件** 将cluster-enabled 设置为yes,并将cluster-config-file设置为自定义的文件。 这里定义为nodes-端口号.conf ![](https://img.kancloud.cn/94/76/9476c1789cb7ce3e6a93df41abdb3b0e_1685x760.png) #### **修改集群RDB快照和AOF文件的存放位置** 修改dir属性,这里定义为/home/redis-cluster/redis-master/ ![](https://img.kancloud.cn/ad/78/ad782b9569baa23dd0bf4af50919aac3_1572x786.png) #### **修改集群密码** 修改masterauth属性为Redis(RequirePass)密码 ![](https://img.kancloud.cn/53/e7/53e731edbb379be62c823f3eef88382b_1728x415.png) #### **开启AOF持久化** 修改appendonly属性 ``` appendonly yes ``` ### **对六台Slave节点进行同样的修改配置操作** 注意:上述指定的文件夹和文件名原则上对于每个redis实例都应该是唯一的,便于区分 ### **启动Redis实例** 运行命令: ``` #第一台主机 /usr/local/bin/redis-server /home/redis-cluster/redis-master/redis-master-7001.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6001.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6004.conf #第二台主机 /usr/local/bin/redis-server /home/redis-cluster/redis-master/redis-master-7002.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6002.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6005.conf #第三台主机 /usr/local/bin/redis-server /home/redis-cluster/redis-master/redis-master-7003.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6003.conf /usr/local/bin/redis-server /home/redis-cluster/redis-slave/redis-slave-6006.conf ``` **查看进程**ps -ef | grep redis: ![](https://img.kancloud.cn/ba/d9/bad9df394abb6984024eb543755dfcdf_1698x184.png) ### **搭建集群** 输入命令: ``` /usr/local/bin/redis-cli -a Object --cluster create --cluster-replicas 2 192.168.43.101:7001 192.168.43.102:7002 192.168.43.103:7003 192.168.43.101:6001 192.168.43.102:6002 192.168.43.103:6003 192.168.43.101:6004 192.168.43.102:6005 192.168.43.103:6006 ``` 其中`--cluster-replicas 2`代表每个Master携带2个Slave,那么就是三个Master,每个Master携带两个Slave。 示意图如下: ![](https://img.kancloud.cn/cc/c6/ccc690b9fd2cee3749d589e7f52382b8_1670x662.png) 我们可以看到,Redis将三台机器连成了一个整体,Master7001的Slave指向了其它两台服务器上的Slave,而其它两台服务器的Master也同样跨服务器指向了,这就是RedisCluster高可用的策略,假设有一台服务器完整地宕机了,由于自己的Slave节点存在于别的服务器上,数据也能重新通过选举选举的方式恢复,不易引起数据的丢失。 ![](https://img.kancloud.cn/7f/9f/7f9ff9d9813b1cb7c7e91273258029b2_529x522.png) * 另外我们可以看到,我们在上文说过,Cluster集群模式将集群分为16384个槽,这里体现为0-16383,分布到了每一个Master节点上,这对我们之前的理论部分做了验证。 ## **测试** 测试环节通过客户端测试和Java程序测试,来模拟集群模式下Redis的存储策略。 #### **客户端测试** 开启客户端,随意连接一个master节点 ``` /usr/local/bin/redis-cli -c -a 密码 -h IP -p 端口 ``` ![](https://img.kancloud.cn/2e/42/2e42784d767327ac54fef1eef2c66694_543x160.png) * 我们可以看到,当我们set一个键值对的时候,Redis会自动为我们的key计算CRC16值,然后对16384取模,获取key对应的hash slot,然后通过判断该槽被那个Master所占用,帮我们重定向到那个Master节点,将键值对存入。 #### **程序测试** 在测试之前先把Redis中的数据清空。 对三个Master节点分别执行`flushall`命令 启动程序: 1. 正常存入数据时关闭某Master节点(模拟宕机): ![](https://img.kancloud.cn/fb/14/fb146a9d21a5e0e07514be55afb4651f_524x221.png) 程序打印正在选举… ![](https://img.kancloud.cn/c6/18/c61843b683852770a8e2f7f2263f3a5e_391x219.png) 2. 选举结束后继续IO ![](https://img.kancloud.cn/89/7b/897bcadf53774978658e2ec0df6ab688_425x118.png) 代码: ~~~ public class JedisDemo { public static void main(String[] args) { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.43.101",7001)); nodes.add(new HostAndPort("192.168.43.102",7002)); nodes.add(new HostAndPort("192.168.43.103",7003)); nodes.add(new HostAndPort("192.168.43.101",6001)); nodes.add(new HostAndPort("192.168.43.102",6002)); nodes.add(new HostAndPort("192.168.43.103",6003)); nodes.add(new HostAndPort("192.168.43.101",6004)); nodes.add(new HostAndPort("192.168.43.102",6005)); nodes.add(new HostAndPort("192.168.43.103",6006)); JedisCluster jedisCluster = new JedisCluster(nodes,100,1000,100,"Object","rediscluster",jedisPoolConfig,false); for(int i = 0;i<2000;i++) { try { System.out.println("存入数据:"+i); jedisCluster.set(String.valueOf(i),String.valueOf(i)); try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } String res = jedisCluster.get(String.valueOf(i)); System.out.println("取出数据:"+res); }catch(Exception e) { //出现节点宕机 System.out.println("正在选举..."); System.out.println(new Date()); continue; } } jedisCluster.close(); } } ~~~ * 注意事项 1. 在搭建集群的过程中有可能会遇到一直等待连接,但是集群无法连接成功的状况,这是因为我们在搭建集群的时候防火墙没有开启对应的端口号导致的,**我们不光要开启我们对外连接的端口号,如7001、7002、7003,还要开启对外连接端口号+10000的端口,用于集群内部相互通信,如节点端口为7001、7002、7003,那么我们还应该开启17001、17002、17003这些端口**。 2. 如果遇到搭建失败的情况,重新搭建的时候一定要到dir指向的文件夹中将快照和AOF还有node.conf文件删干净,否则无法重新搭建。 ### **搭建完毕** 至此我们已经完成了Redis集群的搭建,在私下实践的时候可以试试使用Redis客户端直接操作集群时手动关闭某个Master,会出现什么样的状况,这个是文章中没有提到的内容。