您的位置:首页 > 数据库 > Redis

CentOS 6.5 -- Redis 4.0.2架构☞集群(cluster)的搭建

2017-10-24 08:51 721 查看
       本篇意在阐述和记录整个集群搭建的过程,难免会借鉴一些现有redis集群资料里面的图和文字说明,但是整个步骤,都是亲力亲为,一方面是为了记录下这一过程,另一方面,是想通过这种记录的方式,让自己对redis的操作更加上手,对redis集群的目的性理解的更加透彻,学以复用,借鉴别人的技术发挥自己的长处。

       开车之前,先说明一下,本篇基于我的redis系列前两篇,如果前两篇没看的话,默认你可以上车了,如果上车发现有呕吐现象,请中途下车,以免晕到最后,哈哈。 本篇有点长,但是不难,好了,要开车了,大家坐稳了!

一、架构图



(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.

(2)节点的Fail是通过集群中超过半数的节点检测失效时才生效.

(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

(4)redis-cluster把所有的物理节点映射到[0-16383]slot(插槽)上,cluster
负责维护node<->slot<->value

根据上面进行扩充说明

(1)两个redis节点互联不叫集群,根据超过半数投票原则,两个人构不成半数,你投我我投你,来啊,互相伤害!

(2)集群中的redis节点都是你连我,我连你,嘿,你也连我是吧,好的,我也再连你一下....所以最后,就出现了,如果client连接集群中的某个节点,是随性的,不需要指定我要连接哪一个节点(IP:Port),为什么呢?因为,你随便找一个节点,剩下的节点通道都是打通的,就好比,条条大路通罗马,我是路痴,我不担心!

(3)什么是redis节点的物理插槽(slot)呢? 而且,还是固定的,就16383个。我是这样理解的,把redis集群看作是一个社区,redis节点(一个个redis实例)就是社区中的每户人家,而插槽就是这户人家的门啊,窗户啊,你要想往人家家中传递东西或者从人家家里取出东西,你需要借助窗户或者门这种介质,没有这个,东西你塞不进去也取不出来!而且,一户人家的窗子和门的数量不是无限的,无限的话,浪费资源,所以,我们的社区,规定,总过就16383个指标,不管社区里有多少户人家,我就按平均分配,当然,可能分给其他redis节点的插槽有部分是损坏的,就好比,一户人家分得了20个门窗指标,但是,却在构建这20个门窗的时候,发现,有5个是坏的,安不上,那么,没关系,这5个坏掉的指标就被遗弃,真正有用的就剩下15个指标了,因此,对于redis节点来说,实际有用的插槽,才是client(客户)要用到的(一个插槽,对于redis来说,就是一个int标识)。

(4)针对第三条说的,我们的redis集群(cluster)就是社区,社区有责任对每一个在社区中的redis节点进行维护!

二、准备集群前要做的事,就是先要开启集群功能

cd /usr/local/src/redis/



(1)删除dump.rdb,配置redis.conf

改三波配置文件,走一个,剩下的两个一样,改之前,分别删除6379、6380、6381实例中的持久化数据文件dump.rdb(真实场景下,不要养成这种习惯,这里我删除它,是因为,我知道它对我来说不重要,只是为了演示数据测试而已)



(2)开启redis实例

批量开启

cd 6379/ && redis-server ./redis.conf && cd ..

cd 6380/ && redis-server ./redis.conf && cd ..

cd 6381/ && redis-server ./redis.conf && cd ..



三、创建集群(将三个已经具有集群节点的redis实例,互联起来)

在我的redis系列博文第一篇中,提到过,redis集群的设置是基于
redis的src目录下面的redis-trib-rb可执行文件,该执行文件后跟一系列命令,整个集群配置的过程,是需要ruby编译环境的,因此,本篇集群的实现,首先要安装ruby环境,没安的,转到第一篇进行查看安装步骤。

补充说明:

(A)redis-trib.rb是redis官方推出的管理redis集群的工具,集成在redis的源码src目录下,是基于redis提供的集群命令封装成简单、便捷、实用的操作工具。

(B)redis-trib.rb是redis作者用ruby完成的

(1)切换到src源码目录

cd redis-4.0.2/src



(2)执行集群管理工具redis-trib.rb,查看相应功能

./redis-trib.rb



(3)执行create命令,创建集群

create命令可选参数replicas:

A.表示集群中每个节点对应的有几个slave从节点

B.redis实例有主从(master--slave)架构,同理,集群中,也有主从架构一说

C.本篇默认集群中的各个节点没有指定自己的slave,replicas后跟0

集群节点格式: host1:port1 ... hostN:portN

补充说明:

为了演示后面Java客户端(使用Jedis包),连接redis集群中的某一个节点,并进行redis读写数据的操作,需要改一下,当前三个实例的bind属性,不要bind 本机 127.0.0.1,要放开政策,让client都可以连。



改后,重新启动三个实例如下:



创建集群

./redis-trib.rb create --replicas 0 192.168.153.137:6379 192.168.153.137:6380 192.168.153.137:6381



创建ing...



创建结束



随便在集群中找个节点,进行info信息查看(注意,一个节点牵扯出其他所有在集群中的剩余节点,互联、互通!)

./redis-trib.rb info 192.168.153.137:6380



四、测试集群

随便redis-cli一个节点(默认连接的是6379这个redis实例),并set一个key-value对,注意,集群可不是按照当前连接的是哪个redis实例,就在当前实例中创建数据的,它的工作原理是:

(1)根据key计算slot的值,怎么计算,感兴趣的朋友搜一下CRC16算法

(2)拿到slot的值,去和集群中的节点拥有的插槽进行匹配

(3)如果匹配上了,且插槽是好的,就把key-value键值对的数据放在当前匹配到的节点对应的插槽中

(4)如果匹配上了,但插槽是坏的,对不起,这部分插槽中的key将不能被使用

走一波,验证一下

(由于之前我们修改了redis.conf里面的bind绑定,因此,不能直接用redis-cli连,这个直接连的是 127.0.0.1)

redis-cli -h 192.168.153.137 -p 6379



为什么呢,我们看一下插槽分配情况



name这个key是在实例6379中set的,但计算出来的插槽值是5789,而6379实例最大的插槽数量是5461,显然,这个key-value应该被放在6380这个redis实例中,因为它的插槽值范围是


那我们怎么在不知道key-value应该被集群安排到哪个节点上做set呢?

很简单,我们只需要加一个参数,-c,做一下redis节点的重定向就行,也就是,set成功后,会自动跳转到成功存储的redis实例上

redis-cli -h 192.168.153.137 -p 6379
-c



这个就很有意思了,你想想,一个key-value数据,放在集群中的一个节点上,其他节点肯定是没有这个数据的,因为插槽是唯一分配的,其他节点是怎么访问到的呢?最开始说了,集群中的节点都是互联的,你只要知道一个节点,其余节点就都可以访问,这样一来,数据的存储效率很高(不涉及节点间的数据同步),但是,你想想,这样有什么弊端呢?一个节点挂了,整个集群就挂了?是不是呢? 必须是啊,假如你挂的这个节点存放了主要的数据,其他节点就算还可以勉强撑着,也没什么意义啊,你整个集群的链路断了一条,不完整了,况且重要的数据也访问不了了,你不让集群立马停用,等着让客户骂吗?

好的,我们来模拟一下上面的情形,让其中一个实例宕掉,看看,现有的、不完整的集群还可不可以继续使用?

kill -9 11249



redis-cli -h 192.168.153.137 -p 6379 -c



所以说,这种只有master的集群架构是十分"脆弱的",解决办法,就是为集群中的每个master节点配置一个或多个slave节点(一个就够了),master的数据会同步到slave节点上,一旦master节点挂掉,其slave节点立马顶上,属性也由slave转为master(这个过程是有cluster自动检测完成的,这里我们不关心),如果后续挂掉的master节点重新活过来了,那么,它的属性将由原来的master转变为slave,作为现在主节点(以前从节点)的从节点(以前主节点),继续在集群中发挥各自的作用。
这个集群架构就不演示了,过程都是雷同的,阐述起来有点累。

将6380这个实例恢复过来,集群又可以使用了



目前集群中总过有两个数据

(1)name ----> appleyk

(2)abc    ----> 123

五、Java客户端,Jedis的使用,连接集群中的某个节点,并进行读写数据操作

聚合项目下pom.xml的jar包依赖

<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>





创建一个jedis测试类



JedisTest.java

package com.appleyk.jedis.test;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class JedisTest {

@Test
public void Test(){
Set<HostAndPort> ClusterNodes = new HashSet<HostAndPort>();
//1.随便选择集群中的一个节点
ClusterNodes.add(new HostAndPort("192.168.153.137", 6380));
JedisCluster jCluster = new JedisCluster(ClusterNodes);

//2.读取 key--value
String name = "";
name = jCluster.get("name");
System.out.println(name);

//3.设置 key--value
jCluster.set("time", "2017年10月24日13:20:47");
System.out.println(jCluster.get("time"));
}
}

JUnit方法测试,执行遇到以下错误



这种情况在我之前的Linux系列中的软件环境部署和测试使用中,发生不是一次两次了,其唯一根本的原因就是Linux防火墙阻拦了相应端口的访问,解决办法,最暴力的一种,就是干翻防火墙



然后再次执行一次就ok了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: