首頁 > 資料庫 > Redis > 主體

redis分散式叢集建置介紹

發布: 2019-12-12 17:18:08
轉載
3463 人瀏覽過

redis分散式叢集建置介紹

Redis叢集架構圖

redis分散式叢集建置介紹

#上圖藍色為redis集群的節點。

節點之間透過ping指令來測試連線是否正常,節點之間沒有主區分,當連接到任何一個節點進行操作時,都可能會轉送到其他節點。

1、Redis的容錯機制

節點之間會定時的互相發送ping指令,測試節點的健康狀態,當節點接受到ping指令後,會傳回一個pong字串。

投票機制:如果一個節點A給節點B發送ping沒有得到pong返回,會通知其他節點再次給B發送ping,如果集群中有超過一半的節點收不B節點的pong。那就認為B節點掛了。一般會為每個節點提供一個備份節點,如果掛掉會切換到備份節點。

2、Redis叢集儲存原理

Redis對於每個存放的key會進行hash操作,產生一個[0-16384]的hash值(先進行

crc 演算法再對16384取餘)。

集群的情況下,就是把[0-16384]的區間進行拆分,放到不同的redis中。

3、Redis的持久化

Snapshotting:定時的將Redis記憶體中的資料保存到硬碟中

AOF:將所有的command操作保存到aof中,AOP的同步頻率很高,資料即使遺失,粒度也很小,但會在效能上造成影響。

二、叢集環境建置

#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
登入後複製

三、建立Redis叢集

在一台伺服器上,可以用不同連接埠號來表示不同redis伺服器。

Redis叢集最少需要三台伺服器,而每台伺服器有需要備用伺服器,所以最少需要6台伺服器。連接埠規劃如下:

主伺服器:192.168.100.66 :7001  :7002  :7003

從伺服器:192.168.100.66 :7004  :7005 168.100.66 :7004  :7005 168.100.66 :7004  :7005 106/#o#o#o#-#>70#>702/#> 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 如下圖說明啟動成功

redis分散式叢集建置介紹建立叢集:

將先前解壓縮的資料夾的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

如果成功最終輸入如下:

redis分散式叢集建置介紹查詢叢集資訊:

redis分散式叢集建置介紹#說明:

./redis-cli -c - h 192.168.101.3 -p 7001 ,其中-c表示以叢集方式連接redis,-h指定ip位址,-p指定連接埠號碼

cluster nodes 查詢叢集結點資訊

cluster info查詢叢集狀態資訊

redis分散式叢集建置介紹

hash槽重新指派

第一步:連線上叢集

./ redis-trib.rb reshard 192.168.101.3:7001(連接群集中任一可用結點都行)

第二步:輸入要指派的槽數

redis分散式叢集建置介紹#輸入 500表示要分配500個槽

第三個步驟:輸入接收槽的結點id​​

这里准备给7007分配槽,通过cluster nodes查看7007结点id为15b809eadae88955e36bcdbb8144f61bbbaf38fb

输入:15b809eadae88955e36bcdbb8144f61bbbaf38fb

第四步:输入源结点id

redis分散式叢集建置介紹

这里输入all

第五步:输入yes开始移动槽到目标结点id

redis分散式叢集建置介紹

添加从节点

集群创建成功后可以向集群中添加节点,下面是添加一个slave从节点。

添加7008从结点,将7008作为7007的从结点。

./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查看。

redis分散式叢集建置介紹

注意:如果原来该结点在集群中的配置信息已经生成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为7007的从节点:

1redis分散式叢集建置介紹

删除结点:

./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">
    <!-- 连接池配置 -->
    <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" />
        <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
        <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);
    }
}
登入後複製

更多redis知识请关注redis数据库教程栏目。

以上是redis分散式叢集建置介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:cnblogs.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!