Redis布满式集群搭建

Redis集群架构图

 图片 1

 

上海教室天蓝为redis集群的节点。

节点之间通过ping命令来测试连接是不是正规,节点之间未有主区分,连接受别的一个节点进行操作时,都可能会转化到其余节点。

1. redis介绍

壹、Redis的容错机制

节点之间会定期的彼此发送ping命令,测试节点的例行状态,当节点接受到ping命令后,会重返多少个pong字符串。

投票机制:若是1个节点A给节点B发送ping未有收获pong再次来到,会通告别的节点再一次给B发送ping,要是集群中有超常四分之二的节点收不B节点的pong。那么就感觉B节点挂了。一般会为每一个节点提供2个备份节点,尽管挂掉会切换成备份节点。

1.1. 什么是redis

Redis是用C语言开垦的3个开源的高性能键值对(key-value)数据库。它通过提供各种键值数据类型来适应差异场景下的储存必要,近日截止Redis接济的键值数据类型如

下:

字符串类型

散列类型

列表类型

集结类型

1如既往聚焦类型。

2、Redis集群存款和储蓄原理

Redis对于每一种存放的key会进行hash操作,生成三个[0-16384]的hash值(先进行

crc 算法再对163八4取余)。

集群的意况下,即是把[0-16384]的间隔进行拆分,放到不一样的redis中。

 

1.2. redis的施用场景

缓存(数据查询、短连接、音信内容、商品内容等等)。(最多采用)

分布式集群架构中的session分离。

聊天室的在线好友列表。

义务队列。(秒杀、抢购、1230六之类)

使用排名榜。

网址访问总结。

数量过期管理(能够准确到纳秒)

 

叁、Redis的持久化

Snapshotting:按期的将Redis内部存储器中的数码保存到硬盘中

AOF:将有着的command操作保存到aof中,AOP的共同频率相当高,数据正是丢失,粒度也非常的小,但会在性质上产生影响。

 

1.3. Redis的安装

redis是C语言开荒,提出在linux上运营,本课程使用Centos陆.四作为安装情况。

安装redis需求先大校方网址下载的源码实行编写翻译,编写翻译依赖gcc景况,借使未有gcc情形,须求安装gcc:yum install gcc-c++

n 版本表明

本学科使用redis3.0版本。三.0本子首要增添了redis集群作用。

n 源码下载

从官方网站下载

http://download.redis.io/releases/redis-3.0.0.tar.gz

将redis-3.0.0.tar.gz拷贝到/usr/local下

n 解压源码

   tar -zxvf redis-3.0.0.tar.gz  

n 进入解压后的目录实行编写翻译

cd /usr/local/redis-3.0.0

make

n 安装到内定目录,如 /usr/local/redis

cd /usr/local/redis-3.0.0 

make PREFIX=/usr/local/redis install

 

n redis.conf

redis.conf是redis的陈设文件,redis.conf在redis源码目录。

小心修改port作为redis进度的端口,port默许637玖。

 

 

n 拷贝配置文件到安装目录下

进去源码目录,里面有1份配置文件
redis.conf,然后将其拷贝到安装路线下

cd /usr/local/redis

mkdir conf

cp /usr/local/redis-3.0.0/redis.conf  /usr/local/redis/bin

 

 

n 安装目录bin下的文件列表

 

 

 

 

 

redis三.0新扩充的redis-sentinel是redis集群管理工具可实现高可用。

 

 

布局文件目录:

 

 

 

 

二、Redis集群筹划干活

1.4. redis启动

Redis安装

源码下载

下载地址https://pan.baidu.com/s/1bCcLv4
 密码i5k6

解压源码

   tar -zxvf redis-3.0.0.tar.gz  

跻身解压后的目录进行编写翻译

cd /usr/local/redis-3.0.0

make

设置到钦点目录,如 /usr/local/redis

cd /usr/local/redis-3.0.0

make PREFIX=/usr/local/redis install

 

nredis.conf

redis.conf是redis的布局文件,redis.conf在redis源码目录。

注意修改port作为redis进度的端口,port暗中认可637玖。

 

拷贝配置文件到安装目录下

进入源码目录,里面有一份配置文件
redis.conf,然后将其拷贝到安装路线下

cd /usr/local/redis

mkdir conf

cp /usr/local/redis-3.0.0/redis.conf  /usr/local/redis/bin

运营:bin/redis-server  将现出下图画面:

 图片 2

 

Redis默许是前台运维的,能够修改redis.conf的daemonize yes ,将其形成后台运转。

 

1.4.1. 前者形式运行

平昔运营bin/redis-server将在此以前端格局运转,前端格局运维的缺点是ssh命令窗口关闭则redis-server程序甘休,不推荐使用此方法。如下图:

 

 

 

 

集群情形搭建

redis集群处理工科具redis-trib.rb注重ruby景况,首先必要安装ruby遇到

安装ruby

yum install ruby

yum install rubygems

安装ruby和redis的接口程序

拷贝redis-3.0.0.gem至/usr/local下

执行:

gem install /usr/local/redis-3.0.0.gem

 

1.4.2. 后端形式运营

修改redis.conf配置文件,daemonize yes现在端情势运行。

 

实行如下命令运维redis:

cd /usr/local/redis

./bin/redis-server ./redis.conf

 

redis暗许使用637玖端口。

 

也可改动redis.conf文件,修改端口号:

 

 

 

三、创建Redis集群

在一台服务器上,能够用不一致端口号来代表不一致redis服务器。

Redis集群最少要求3台服务器,而每台服务器有须求备用服务器,所以最少供给陆台服务器。端口规划如下:

主服务器:1玖二.168.100.6陆 :7001 :700二  :700叁

从服务器:1九二.16八.100.6陆 :700四 :7005  :700陆

在/usr/local 创制文件夹用来存放服务器程序

mkdir 7001 7002 7003 7004 7005 7006

假诺想让redis协理集群需求修改redis.config配置文件的cluster-enabled yes

本例中大家以端口来区分差异的redis服务,所以还须求修改redis.config的port为对应端口

修改完配置文件,将redis安装目录的bin复制到上面种种目录中。

独家进入7001/bin/ 7002/bin …..

开发银行服务./redis-server ./redis.conf

 

查阅redis进度:ps -aux|grep redis 如下图则表明运转成功

 图片 3

开创集群:

将事先解压的文书夹的redis-3.0.0/src/redis-trib.rb复制到redis-cluster目录

运行

./redis-trib.rb create –replicas 1 192.168.100.66:7001
192.168.100.66:7002 192.168.100.66:7003 192.168.100.66:7004
192.168.100.66:7005  192.168.100.66:7006

 

假使推行时报如下错误:

[ERR] Node XXXXXX is not empty. Either
the node already knows other nodes (check with CLUSTER NODES) or
contains some key in database 0

减轻情势是删除生成的配备文件nodes.conf,若是那几个则表明现行反革命创建的结点包含了旧集群的结点新闻,必要删除redis的持久化文件后再重启redis,比方:appendonly.aof、dump.rdb

设若成功最终输入如下:

 图片 4

询问集群音讯:

图片 5

说明:

./redis-cli -c -h 192.16八.十壹.三 -p 7001,当中-c表示以集群方式连接redis,-h钦命ip地址,-p钦命端口号

cluster nodes 查询集群结点音讯

cluster info 查询集群状态新闻

 图片 6

1.5. 通过jedis连接redis单机

 

hash槽重新分配

第三步:连接上集群

./redis-trib.rb reshard 19二.16捌.拾壹.3:700一(连接集群中自由叁个可用结点都行)

 

第3步:输入要分配的槽数量

 图片 7

输入 500意味着要分配500个槽

 

其三步:输入接收槽的结点id

 图片 8

 

此处希图给7007分配槽,通过cluster nodes查看7007结点id为一伍b80九eadae8895伍e3陆bcdbb814四f陆一bbbaf3八fb

输入:15b809eadae88955e36bcdbb8144f61bbbaf38fb

 

第伍步:输入源结点id

 图片 9

此处输入all

第6步:输入yes起初运动槽到目的结点id

 图片 10

1.5.1. jar包

pom坐标:

<dependency>

     <groupId>redis.clients</groupId>

     <artifactId>jedis</artifactId>

     <version>2.7.0</version>

</dependency>

 

jar包如下:

 

累加从节点

 

集群成立成功后方可向集群中增多节点,上面是增加三个slave从节点。

增加700八从结点,将7008看成700柒的从结点。

 

./redis-trib.rb add-node –slave –master-id 主节点id 增多节点的ip和端口 集群中已存在节点ip和端口

 

 

试行如下命令:

./redis-trib.rb add-node –slave –master-id
cad9f7413ec6842c971dbcc2c48b4ca959eb5db4
 192.168.101.3:7008 192.168.101.3:7001

cad9f7413ec6842c971dbcc2c48b4ca959eb5db4  是7007结点的id,可通过cluster nodes查看。

 图片 11

小心:假若原本该结点在集群中的配置新闻已经生成cluster-config-file钦赐的布局文件中(假诺cluster-config-file未有点名则默感觉nodes.conf),那时恐怕会报错:

[ERR] Node XXXXXX is not empty. Either the node already knows other
nodes (check with CLUSTER NODES) or contains some key in database 0

斩草除根办法是删除生成的布置文件nodes.conf,删除后再实行./redis-trib.rb
add-node
指令

查看集群中的结点,刚增添的7008为700七的从节点:

 图片 12

1.5.2. 单实例连接

经过创办单实例jedis对象连接redis服务,如下代码:

// 单实例连接redis

@Test

public void testJedisSingle() {

 

Jedis jedis = new Jedis(“192.168.101.3”, 6379);

jedis.set(“name”,”bar”);

String name = jedis.get(“name”);

System.out.println(name);

jedis.close();

 

}

1.1. 剔除结点:

 

./redis-trib.rb del-node 127.0.0.1:7005
4b45eb75c8b428fbd77ab979b85080146a9bc017

 

除去已经攻下hash槽的结点会失败,报错如下:

[ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try
again.

 

亟需将该结点占用的hash槽分配出去(参考hash槽重新分配章节)。

测试:

Maven:

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.7.0</version>
    </dependency>
    <!– https://mvnrepository.com/artifact/junit/junit –>
    
<dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!–
https://mvnrepository.com/artifact/org.springframework/spring-test
–>
    
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.3.10.RELEASE</version>
        <scope>test</scope>
    </dependency>
</dependencies>

 

 

常常测试:

@Test
public void redisClusterTest1(){
    JedisPoolConfig config=new JedisPoolConfig();
    config.setMaxTotal(30);
    config.setMaxIdle(2);

    Set<HostAndPort> jedisNode=new
HashSet<HostAndPort>();
    jedisNode.add(new HostAndPort(“192.168.100.66”,7001));
    jedisNode.add(new HostAndPort(“192.168.100.66”,7002));
    jedisNode.add(new HostAndPort(“192.168.100.66”,7003));
    jedisNode.add(new HostAndPort(“192.168.100.66”,7004));
    jedisNode.add(new HostAndPort(“192.168.100.66”,7005));
    jedisNode.add(new HostAndPort(“192.168.100.66”,7006));

    JedisCluster jc=new JedisCluster(jedisNode,config);
    jc.set(“name”,“老王”);
    String value=jc.get(“name”);
    System.out.println(value);
}

Spring测试:

配置文件:

<?**xml version=”1.0″ encoding=”UTF-8″?> <beans xmlns=”http://www.springframework.org/schema/beans
       xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance
       xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"**&gt;
    <!– 连接池配置 –>
    
<bean id=”jedisPoolConfig”
class=”redis.clients.jedis.JedisPoolConfig”>
        <!– 最地拉那接数 –>
        
<property name=”maxTotal” value=”30″ />
        <!– 最大空闲连接数 –>
        
<property name=”maxIdle” value=”10″ />
        <!– 每一遍释放连接的最大数量 –>
        
<property name=”numTestsPerEvictionRun”
value=”1024″ />
        <!– 释放连接的扫视间隔(微秒) –>
        
<property name=”timeBetweenEvictionRunsMillis”
value=”30000″ />
        <!– 连接最小空闲时间 –>
        
<property name=”minEvictableIdleTimeMillis”
value=”1800000″ />
        <!– 连接空闲多短时间后获释, 当空闲时间>该值 且
空闲连接>最大空闲连接数 时直接出狱 –>
        
<property name=”softMinEvictableIdleTimeMillis”
value=”10000″ />
        <!–
获取连接时的最大等待微秒数,小于零:阻塞不鲜明的年华,暗许-一 –>
        
<property name=”maxWaitMillis” value=”1500″
/>
        <!– 在获得连接的时等候检查查有效性, 暗中认可false –>
        
<property name=”testOnBorrow” value=”true”
/>
        <!– 在悠闲时检查有效性, 默许false –>
        
<property name=”testWhileIdle” value=”true”
/>
        <!– 连接耗尽时是或不是封堵, false报十分,ture阻塞直到超时,
暗中认可true –>
        
<property name=”blockWhenExhausted”
value=”false” />
    </bean>
    <!– redis集群 –>
    
<bean id=”jedisCluster”
class=”redis.clients.jedis.JedisCluster”>
        <constructor-arg index=”0″>
            <set>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7001″></constructor-arg>
                </bean>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7002″></constructor-arg>
                </bean>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7003″></constructor-arg>
                </bean>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7004″></constructor-arg>
                </bean>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7005″></constructor-arg>
                </bean>
                <bean
class=”redis.clients.jedis.HostAndPort”>
                    <constructor-arg index=”0″
value=”192.168.100.66″></constructor-arg>
                    <constructor-arg index=”1″
value=”7006″></constructor-arg>
                </bean>
            </set>
        </constructor-arg>
        <constructor-arg index=”1″
ref=”jedisPoolConfig”></constructor-arg>
    </bean>
</beans>

 

测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({“classpath:spring-config.xml”})
public class RedisClusterTest {
    @Autowired
    private JedisCluster jedisCluster;
    @Test
    public void redisClusterTest2(){
        jedisCluster.set(“username”,“小明啦啦”);
        String name=jedisCluster.get(“username”);
        System.out.println(name);
    }
}

 

1. 外部连接不上redis的消除措施

鉴于linux防火墙私下认可开启,redis的劳动端口637九并不在开放规则之内,全数要求将此端口开放访问依然关闭防火墙。

关门防火墙命令:sevice iptables
stop

假若是修改防火墙规则,可以修改:/etc/sysconfig/iptables文件

1.5.3. 利用连接池连接

经过单实例连接redis不可能对redis连接举办共享,能够动用连接池对redis连接实行共享,升高财富利用率,使用jedisPool连接redis服务,如下代码:

 

@Test

public void pool() {

JedisPoolConfig config = new JedisPoolConfig();

//最亚松森接数

config.setMaxTotal(30);

//最达累斯萨拉姆接空闲数

config.setMaxIdle(2);

JedisPool pool = new JedisPool(config,”192.168.101.3″, 6379);

Jedis jedis = null;

 

try  {

jedis = pool.getResource();

jedis.set(“name”,”lisi”);

String name = jedis.get(“name”);

System.out.println(name);

}catch(Exception ex){

ex.printStackTrace();

}finally{

if(jedis !=null){

//关闭连接

jedis.close();

}

}

}

 

详见的连接池配置参数参考下节jedis和spring整合中applicationContext.xml的配置内容。

 

1.5.4. jedis与spring整合

布置spring配置文件applicationContext.xml

 

<?xml version=”1.0″
encoding=”UTF-8″?>

<beans
xmlns=”http://www.springframework.org/schema/beans

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance
xmlns:mvc=”http://www.springframework.org/schema/mvc

xmlns:context=”http://www.springframework.org/schema/context

xmlns:aop=”http://www.springframework.org/schema/aop
xmlns:tx=”http://www.springframework.org/schema/tx

xsi:schemaLocation=”http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.2.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
“>

 

<!– 连接池配置 –>

<bean id=“jedisPoolConfig” class=“redis.clients.jedis.JedisPoolConfig”>

<!– 最浦那接数 –>

<property name=“maxTotal” value=“30” />

<!– 最大空闲连接数 –>

<property name=“maxIdle” value=“10” />

<!– 每一趟释放连接的最大数量 –>

<property name=“numTestsPerEvictionRun” value=“1024” />

<!– 释放连接的扫描间隔(纳秒) –>

<property name=“timeBetweenEvictionRunsMillis” value=“30000” />

<!– 连接最小空闲时间 –>

<property name=“minEvictableIdleTimeMillis” value=“1800000” />

<!– 连接空闲多长期后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接出狱 –>

<property name=“softMinEvictableIdleTimeMillis” value=“10000” />

<!– 获取连接时的最大等待阿秒数,小于零:阻塞不明确的年月,暗中认可-一 –>

<property name=“maxWaitMillis” value=“1500” />

<!– 在获得连接的时等候检查查有效性, 私下认可false –>

<property name=“testOnBorrow” value=“true” />

<!– 在闲暇时检查有效性, 暗中同意false –>

<property name=“testWhileIdle” value=“true” />

<!– 连接耗尽时是否封堵, false报格外,ture阻塞直到超时,暗中认可true –>

<property name=“blockWhenExhausted” value=“false” />

</bean>

<!– redis单机通过连日池 –>

<bean id=“jedisPool” class=“redis.clients.jedis.JedisPool” destroy-method=”close”>

<constructor-arg name=”poolConfig” ref=”jedisPoolConfig”/>

<constructor-arg name=”host” value=”192.168.25.145″/>

<constructor-arg name=”port” value=”6379″/>

</bean>

 

测试代码:

private ApplicationContextapplicationContext;

 

@Before

public void init() {

applicationContext =new ClassPathXmlApplicationContext(

“classpath:applicationContext.xml”);

}

 

@Test

public void testJedisPool() {

JedisPool pool = (JedisPool)
applicationContext.getBean(“jedisPool”);

try  {

jedis = pool.getResource();

jedis.set(“name”,”lisi”);

String name = jedis.get(“name”);

System.out.println(name);

}catch(Exception ex){

ex.printStackTrace();

}finally{

if(jedis !=null){

//关闭连接

jedis.close();

}

}

}

 

2. redis集群

2.1. 集群原理

2.1.1. redis-cluster架构图

 

架构细节:

(一)全体的redis节点互相互联(PING-PONG机制),内部使用贰进制协议优化传输速度和带宽.

(二)节点的fail是通过集群Chinese Football Association Super League越二分一的节点检查评定失效时才生效.

(三)客户端与redis节点直连,不要求中间proxy层.客户端不需求接二连三集群具备节点,连接集群中其余1个可用节点就能够

(四)redis-cluster把具有的情理节点映射到[0-16383]slot上,cluster担当维护node<->slot<->value

Redis集群中置放了16388个哈希槽,当供给在Redis集群中放置贰个key-value时,redis先对key使用crc1陆算法算出一个结实,然后把结果对163八四求余数,那样各样key都会相应贰个号码在0-163八3中间的哈希槽,redis会依据节点数量大约均等的将哈希槽映射到不相同的节点

2.1.2. redis-cluster投票:容错

 

(一)领着投票进程是集群中拥有master参加,要是超越4/八master节点与master节点通讯超越(cluster-node-timeout),以为眼下master节点挂掉.

(二):几时任何集群不可用(cluster_state:fail)? 

    a:假使集群大四master挂掉,且当前master未有slave.集群进入fail状态,也能够领会成集群的slot映射[0-16383]不成就时进入fail状态. ps : redis-三.0.0.rc1投入cluster-require-full-coverage参数,暗许关闭,展开集群兼容部分退步.

    b:假如集群当先一大半master挂掉,无论是还是不是有slave集群进入fail状态.

  ps:当集群不可用时,全部对集群的操作做都不可用,收到((error) CLUSTEMuranoDOWN The cluster is
down)错误

 

 

2.2. ruby环境

redis集群管理工科具redis-trib.rb注重ruby景况,首先必要安装ruby情状:

 

安装ruby

yum install ruby

yum install rubygems

 

安装ruby和redis的接口程序

拷贝redis-3.0.0.gem至/usr/local下

执行:

gem install /usr/local/redis-3.0.0.gem

 

2.3. 始建集群:

2.3.1. 集群结点规划

此地在壹如既往台服务器用区别的端口表示差别的redis服务器,如下:

主节点:192.168.101.3:7001
192.168.101.3:7002 192.168.101.3:7003

从节点:192.168.101.3:7004 192.168.101.3:7005 192.168.101.3:7006

 

在/usr/local下开创redis-cluster目录,其下创办7001、700二。。700陆目录,如下:

 

 

 

将redis安装目录bin下的公文拷贝到每种700X目录内,同时将redis源码目录src下的redis-trib.rb拷贝到redis-cluster目录下。

 

修改各种700X索引下的redis.conf配置文件:

 

port XXXX

#bind 192.168.101.3

cluster-enabled yes

 

 

 

2.3.2. 起步每一种结点redis服务

 

独家进入700一、700二、…700六目录,试行:

./redis-server ./redis.conf

 

查看redis进程:

 

 

2.3.3. 实行成立集群命令

执行redis-trib.rb,此脚本是ruby脚本,它重视ruby情形。

 

./redis-trib.rb create –replicas 1 192.168.101.3:7001
192.168.101.3:7002 192.168.101.3:7003 192.168.101.3:7004
192.168.101.3:7005  192.168.101.3:7006

./redis-trib.rb create –replicas 1 192.168.131.102:7001 192.168.131.102:7002 192.168.131.102:7003 192.168.131.102:7004 192.168.131.102:7005  192.168.131.102:7006

 

说明:

redis集群至少必要三个主节点,每一种主节点有三个从节点总共五个节点

replicas内定为一意味着各类主节点有多个从节点

 

注意:

壹经执行时报如下错误:

[ERR] Node XXXXXX is not empty. Either the node already knows other
nodes (check with CLUSTER NODES) or contains some key in database 0

消除办法是删除生成的配置文件nodes.conf,假若那几个则印证现行反革命创建的结点包涵了旧集群的结点新闻,须要删除redis的持久化文件后再重启redis,例如:appendonly.aof、dump.rdb

 

 

创立集群输出如下:

>>> Creating cluster

Connecting to node 192.168.101.3:7001: OK

Connecting to node 192.168.101.3:7002: OK

Connecting to node 192.168.101.3:7003: OK

Connecting to node 192.168.101.3:7004: OK

Connecting to node 192.168.101.3:7005: OK

Connecting to node 192.168.101.3:7006: OK

>>> Performing hash slots allocation on 6 nodes…

Using 3 masters:

192.168.101.3:7001

192.168.101.3:7002

192.168.101.3:7003

Adding replica 192.168.101.3:7004 to 192.168.101.3:7001

Adding replica 192.168.101.3:7005 to 192.168.101.3:7002

Adding replica 192.168.101.3:7006 to 192.168.101.3:7003

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 192.168.101.3:7001

   slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 192.168.101.3:7002

   slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 192.168.101.3:7003

   slots:10923-16383 (5461 slots) master

S: 69d94b4963fd94f315fba2b9f12fae1278184fe8 192.168.101.3:7004

   replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

S: d2421a820cc23e17a01b597866fd0f750b698ac5 192.168.101.3:7005

   replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

S: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 192.168.101.3:7006

   replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

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.101.3:7001)

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 192.168.101.3:7001

   slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 192.168.101.3:7002

   slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 192.168.101.3:7003

   slots:10923-16383 (5461 slots) master

M: 69d94b4963fd94f315fba2b9f12fae1278184fe8 192.168.101.3:7004

   slots: (0 slots) master

   replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

M: d2421a820cc23e17a01b597866fd0f750b698ac5 192.168.101.3:7005

   slots: (0 slots) master

   replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

M: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 192.168.101.3:7006

   slots: (0 slots) master

   replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

[OK] All nodes agree about slots configuration.

>>> Check for open slots…

>>> Check slots coverage…

[OK] All 16384 slots covered.

 

 

2.4. 查询集群音信

集群创设成功登录大4redis结点查询集群中的节点情况。

 

客户端以集群格局登录:

 

 

说明:

./redis-cli -c -h 1玖2.16八.十一.叁 -p
700一,当中-c表示以集群方式连接redis,-h钦点ip地址,-p钦命端口号

cluster nodes 查询集群结点音信

 

cluster info 查询集群状态消息

 

 

2.5. 增加主节点

集群创造成功后得以向集群中增添节点,下边是加多八个master主节点

增加7007结点,参考集群结点规划章节增多1个“700柒”目录作为新节点。

 

推行上边命令:

./redis-trib.rb add-node  192.168.101.3:7007 192.168.101.3:7001

 

 

 

翻看集群结点开采700七已增多到集群中:

 

 

 

2.5.1. hash槽重新分配

增多完主节点需求对主节点实行hash槽分配那样该主节才能够储存数据。

redis集群有163八十三个槽,集群中的各类结点分配自已槽,通过翻看集群结点能够看来槽占用情形。

 

 

 

给刚增加的700七结点分配槽:

 

 

率先步:连接上集群

./redis-trib.rb reshard 1九2.16八.拾壹.叁:700一(连接集群中专擅三个可用结点都行)

 

第一步:输入要分配的槽数量

 

 

输入 500代表要分配500个槽

 

其三步:输入接收槽的结点id

 

此间策动给700柒分配槽,通过cluster nodes查看7007结点id为一五b809eadae8895五e36bcdbb814四f6一bbbaf3八fb

输入:15b809eadae88955e36bcdbb8144f61bbbaf38fb

 

 

第5步:输入源结点id

 

此处输入all

 

 

第陆步:输入yes先导活动槽到目的结点id

 

 

 

 

2.6. 累加从节点

 

集群创制成功后方可向集群中增多节点,下边是拉长八个slave从节点。

加多700八从结点,将700八看成700七的从结点。

 

./redis-trib.rb add-node –slave –master-id 主节点id 增添节点的ip和端口 集群中已存在节点ip和端口

 

 

实施如下命令:

./redis-trib.rb add-node –slave –master-id
cad9f7413ec6842c971dbcc2c48b4ca959eb5db4
 192.168.101.3:7008 192.168.101.3:7001

cad9f7413ec6842c971dbcc2c48b4ca959eb5db4  是7007结点的id,可通过cluster nodes查看。

 

 

 

注意:若是原本该结点在集群中的配置音讯已经生成cluster-config-file钦命的陈设文件中(假如cluster-config-file没有点名则默认为nodes.conf),那时大概会报错:

[ERR] Node XXXXXX is not empty. Either the node already knows other
nodes (check with CLUSTER NODES) or contains some key in database 0

消除措施是删除生成的布局文件nodes.conf,删除后再施行./redis-trib.rb
add-node
指令

 

查看集群中的结点,刚增多的700八为7007的从节点:

 

 

 

 

2.7. 删除结点:

 

./redis-trib.rb del-node 127.0.0.1:7005
4b45eb75c8b428fbd77ab979b85080146a9bc017

 

去除已经攻克hash槽的结点会倒闭,报错如下:

[ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try
again.

 

须要将该结点占用的hash槽分配出去(参考hash槽重新分配章节)。

 

 

2.8. jedisCluster

2.8.1. 测试代码

 

// 连接redis集群

@Test

public void testJedisCluster() {

 

JedisPoolConfig config = new JedisPoolConfig();

// 最菲尼克斯接数

config.setMaxTotal(30);

// 最明斯克接空闲数

config.setMaxIdle(2);

 

//集群结点

Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7001));

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7002));

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7003));

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7004));

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7005));

jedisClusterNode.add(new HostAndPort(“192.168.101.3”, 7006));

JedisCluster jc = new JedisCluster(jedisClusterNode,
config);

JedisCluster jcd = new JedisCluster(jedisClusterNode);

jcd.set(“name”,”zhangsan”);

String value = jcd.get(“name”);

System.out.println(value);

}

 

 

2.8.2. 使用spring

 

配置applicationContext.xml

 

<!– 连接池配置 –>

<bean id=“jedisPoolConfig” class=“redis.clients.jedis.JedisPoolConfig”>

<!– 最明斯克接数 –>

<property name=“maxTotal” value=“30” />

<!– 最大空闲连接数 –>

<property name=“maxIdle” value=“10” />

<!– 每趟释放连接的最大数目 –>

<property name=“numTestsPerEvictionRun” value=“1024” />

<!– 释放连接的扫视间隔(纳秒) –>

<property name=“timeBetweenEvictionRunsMillis” value=“30000” />

<!– 连接最小空闲时间 –>

<property name=“minEvictableIdleTimeMillis” value=“1800000” />

<!– 连接空闲多长时间后刑释, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时间接出狱 –>

<property name=“softMinEvictableIdleTimeMillis” value=“10000” />

<!– 获取连接时的最大等待阿秒数,小于零:阻塞不分明的年月,默许-一 –>

<property name=“maxWaitMillis” value=“1500” />

<!– 在赢得连接的时等候检查查有效性, 暗中认可false –>

<property name=“testOnBorrow” value=“true” />

<!– 在清闲时检查有效性, 私下认可false –>

<property name=“testWhileIdle” value=“true” />

<!– 连接耗尽时是还是不是封堵, false报至极,ture阻塞直到超时,私下认可true –>

<property name=“blockWhenExhausted” value=“false” />

</bean>

<!– redis集群 –>

<bean id=“jedisCluster” class=“redis.clients.jedis.JedisCluster”>

<constructor-arg index=“0”>

<set>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7001”></constructor-arg>

</bean>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7002”></constructor-arg>

</bean>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7003”></constructor-arg>

</bean>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7004”></constructor-arg>

</bean>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7005”></constructor-arg>

</bean>

<bean class=“redis.clients.jedis.HostAndPort”>

<constructor-arg index=“0” value=“192.168.101.3”></constructor-arg>

<constructor-arg index=“1” value=“7006”></constructor-arg>

</bean>

</set>

</constructor-arg>

<constructor-arg index=“1” ref=“jedisPoolConfig”></constructor-arg>

</bean>

 

测试代码

private ApplicationContextapplicationContext;

 

@Before

public void init() {

applicationContext =new ClassPathXmlApplicationContext(

“classpath:applicationContext.xml”);

}

 

//redis集群

@Test

public void testJedisCluster() {

JedisCluster jedisCluster = (JedisCluster)applicationContext

.getBean(“jedisCluster”);

jedisCluster.set(“name”,”zhangsan”);

String value =
jedisCluster.get(“name”);

System.out.println(value);

}