10、redis哨兵集群高可用


Redis的分片技術

1.1 分片介紹

1.1.1 傳統方式的問題

說明:如果采用單台redis,如果redis出現宕機現象.那么會直接影響我們的整個的服務.

1.1.2 采用分片模式

說明:由一台redis擴展到多台redis.由多台redis共同為用戶提供服務.並且每台redis中保存1/N的數據.

好處:如果一台redis出現了問題.不會影響整個redis的服務.

 

1.1.3 配置多台redis

說明:redis.conf文件拷貝3份到shard文件夾下.分別形成6379/6380/6381的文件

cp redis.conf shard/redis-6379.conf

 

 

1.1.4 修改端口

1.將端口改為6380

 

 

2.將端口號為6381

 

 

1.1.5 啟動多台redis

redis-server redis-6379.conf

redis-server redis-6380.conf

redis-server redis-6381.conf

  1. 進入客戶端

redis-cli -p 6380

  1. 關閉客戶端

redis-cli -p 6380 shutdown

 

1.1.6 分片測試

@Test
    public void test02(){
        /**
         * 定義分片的連接池
         * 參數介紹
         * 1.poolConfig 定義鏈接池的大小
         * 2.shards     表示List<Shardinfo> 表示redis的信息的集合
         * 
         * 補充知識:
         *     Jedis 引入會有線程安全性問題.所以通過線程池的方式動態獲取
         * jedis鏈接.
         */
        
        //定義鏈接池大小
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(1000);
        poolConfig.setTestOnBorrow(true);//測試鏈接是否正常,如果不正常會重新獲取
        poolConfig.setMaxIdle(30);
        //定義分片的list集合
        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
        shards.add(new JedisShardInfo("192.168.126.142",6379));
        shards.add(new JedisShardInfo("192.168.126.142",6380));
        shards.add(new JedisShardInfo("192.168.126.142",6381));
        ShardedJedisPool jedisPool = 
                new ShardedJedisPool(poolConfig, shards);
        //獲取redis的鏈接
        ShardedJedis jedis = jedisPool.getResource();
        for(int i=1;i<=20;i++){
            jedis.set("KEY"+i, ""+i);
        }
        System.out.println("redis插入操作成功!!!");
    }

 

1.2 Redis分片的算法介紹

1.2.1 哈希一致性算法

說明:根據節點的信息進行哈希計算計算的結果在0-2^32-1  的范圍內.計算完成之后能夠進行動態的節點的掛載

特點:

  1. 均衡性

a) 盡可能的讓數據均衡的落入緩存區

  1. 單調性

a) 如果數據已經進行了動態的分配.如果有新節點引入能夠進行動態的分配.

  1. 分散性

a) 由於分布式開發,用戶不能看到緩存的全部.那么數據計算的結果能位置不固定.好的哈希一致性算法應該盡可能的降低分散性

  1. 負載

a) 從另一個角度研究分散性.由於用戶不能看到緩存區的全部,經過計算后,同一個緩存區可以會有多個數據.這樣的方式不是特別的友好,所以高級的哈希算法應該盡可能降低負載.

 

1.2.2 圖示

 

 

說明:

  1. 通過節點的ip+編號通過hash運算,算出具體的位置
  2. 如果需要進行key的存儲.首先根據key值進行計算,找到位置,之后進行數據的存儲
  3. 按照順時針的方向,數據找最近的節點進行掛載.
  4. 取數據時通過node信息.獲取數據.
  5. 以上的節點(node)信息都是動態

1.2.3 均衡性

說明:由於哈希計算可能會出現節點位置較近的現象.通過均衡性中虛擬節點.盡可能的讓數據達到平均

 

 

 

1.2.4 單調性

說明:由於node節點信息可能會出現變化,數據可以動態的掛載到新的節點中.

如果節點需要刪除.那么該節點中的數據會動態的掛載到新的節點中,保證數據是有效的

 

 

 

1.2.5 分散性

 

說明:由於采用了分布式的部署,某些用戶不能夠看到全部的緩存區(node)節點信息.這時在進行數據操作時,可會出現同一key位於不同的位置.

1.2.6 負載

說明:從另外的一個角度考慮分散性.同一個位置.可以存放不同的key

要求:好的hash算法應該盡可能的降低分散性和負載.

1.3 Spring的方式整合分片

1.3.1 編輯配置文件

說明:將原有redis的配置文件改名,為了不讓Spring容器掃描解析出錯.

 

圖上的配置文件保留原有的配置前邊多加字母A.可以保證spring容器不會加載該配置

 

<!--通過線程池的方式整合單台redis  -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!--定義連接的總數  -->
        <property name="maxTotal" value="${redis.maxTotal}"/>
        <!--定義最大的空閑數量  -->
        <property name="maxIdle" value="${redis.maxIdle}"/>
        
        <!--定義最小空閑數量  -->
        <property name="minIdle" value="${redis.minIdle}"></property>
    </bean>
    
    <!--
        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
        shards.add(new JedisShardInfo("192.168.126.142",6379));
        shards.add(new JedisShardInfo("192.168.126.142",6380));
        shards.add(new JedisShardInfo("192.168.126.142",6381));
        ShardedJedisPool jedisPool = 
                new ShardedJedisPool(poolConfig, shards);
      -->
      
      <!--定義jediShardinfo對象  -->
      <bean id="host1" class="redis.clients.jedis.JedisShardInfo">
          <constructor-arg index="0" value="${redis.host1}" type="java.lang.String"/>
          <constructor-arg index="1" value="${redis.port1}" type="int"/>
      </bean>
      
      <bean id="host2" class="redis.clients.jedis.JedisShardInfo">
          <constructor-arg index="0" value="${redis.host2}" type="java.lang.String"/>
          <constructor-arg index="1" value="${redis.port2}" type="int"/>
      </bean>
      
       <bean id="host3" class="redis.clients.jedis.JedisShardInfo">
          <constructor-arg index="0" value="${redis.host3}" type="java.lang.String"/>
          <constructor-arg index="1" value="${redis.port3}" type="int"/>
      </bean>
      
    <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
        <constructor-arg index="0" ref="poolConfig" />
        <constructor-arg index="1">
            <list>
                <ref bean="host1"/>
                <ref bean="host2"/>
                <ref bean="host3"/>
            </list>
        </constructor-arg>
    </bean>

 

1.3.2 編輯redis.properties

 

 

1.3.3 編輯RedisService

 

 

1.3.4 編輯業務層Service

說明:ItemCatService中通過Spring依賴注入的形式進行賦值.所以不需要修改.

思想(面向接口編程的好處)

 

 

Redis哨兵

2.1 搭建主從結構

2.1.1 配置主從

說明:配置主從時需要啟動主從的redis節點信息.之后進行主從掛載.

2.1.2 主從掛載

  1. 復制新的配置文件,后重新啟動新的redis節點信息

 

 

  1. 查詢節點的狀態

127.0.0.1:6380> info replication

 

 實現掛載

127.0.0.1:6380> SLAVEOF 192.168.126.142 6379

 

通過該命令實現掛載

 

 

 

  1. 6381掛載到6379中

SLAVEOF 192.168.126.142 6379

2.1.3 主從測試

說明:通過6379查詢info信息.並且通過set命令為6379賦值后檢測從機中是否含有數據.

 

 

 

2.1.4 哨兵的原理

 

 

 

工作原理:

1.用戶鏈接時先通過哨兵獲取主機Master的信息

2.獲取Master的鏈接后實現redis的操作(set/get)

3.master出現宕機時,哨兵的心跳檢測發現主機長時間沒有響應.這時哨兵會進行推選.推選出新的主機完成任務.

4.當新的主機出現時,其余的全部機器都充當該主機的從機

2.1.5 哨兵的配置

 

1.將保護模式關閉

 

2.配置哨兵的監控

sentinel monitor mymaster 192.168.126.142 6379 1

mymaster:主機的名稱

192.168.126.142:主機的IP

6379 :表示主機的端口號

1:表示有幾個哨兵選舉后生效

3修改時間

說明:10秒后主機沒有響應則選舉新的主機

 

 

 

4.修改推選時間

 

 

2.1.6 啟動哨兵

說明:當啟動哨兵后,由於沒有后台啟動所以需要重新開啟連接進行測試

redis-sentinel sentinel-6379.conf

 

 

 

redis主機宕機后檢測哨兵是否工作

測試結果.redis主機宕機后,哨兵自動選舉出新的主機

 

 

檢測6380是否為主機 info replication

 

 

2.1.7 多台哨兵測試

1.哨兵編譯后的文件

 

cp sentinel-6379.conf sentinel-6380.conf

   

  1. 修改端口

 

 

  1. 修改序列號

說明:由於哨兵啟動時會自動的生成序列號.序列號相同時哨兵不能相互通訊.所以修改為不同的

 

 

  1. 修改哨兵的個數

 

 

 

2.1.8  多台哨兵測試

說明:關閉redis主機后,檢測哨兵是否能夠生效,選舉新的主機.如果能夠選舉新的主機表示多台哨兵搭建完成.

 

2.1.9 測試報錯

說明:由於配置了哨兵,redis中配置了主從結構.所以從機不能進行寫庫操作,.如需測試分片需要關閉redis重新開啟分片的redis

 

 

 

2.2 Spring整合哨兵

2.2.1 測試用例

//哨兵的測試
    @Test
    public void test03(){
        //創建哨兵的連接池
        //String類型表示的是哨兵的IP:端口號
        Set<String> sentinels = new HashSet<String>();
        
        String msg = new HostAndPort("192.168.126.142",26379).toString();
        
        System.out.println("通過對象輸出哨兵的信息格式:"+msg);
        
        //為set集合賦值 保存全部的哨兵信息
        sentinels.add(new HostAndPort("192.168.126.142",26379).toString());
        sentinels.add(new HostAndPort("192.168.126.142",26380).toString());
        sentinels.add(new HostAndPort("192.168.126.142",26381).toString());
        
        /**
         * 參數介紹
         * 1.masterName 表示鏈接哨兵的主機的名稱一般是字符串mymaster
         * 2.sentinels 哨兵的集合Set<>
         */
        JedisSentinelPool sentinelPool = 
                new JedisSentinelPool("mymaster", sentinels);
        
        Jedis jedis = sentinelPool.getResource();
        
        jedis.set("name", "tom");
        System.out.println("獲取數據:"+jedis.get("name"));
    }

 

 

2.3 Spring整合哨兵

2.3.1 編輯配置文件

<bean id="jedisSentinelPool" class="redis.clients.jedis.JedisSentinelPool">
        <constructor-arg index="0" value="${redis.masterName}"/>
        <constructor-arg index="1">
            <set>
                <value>${redis.sentinel.host1}</value>
                <value>${redis.sentinel.host2}</value>
                <value>${redis.sentinel.host3}</value>
            </set>
        </constructor-arg>
    </bean>

 

2.3.2 配置哨兵的配置文件

 

 

2.3.3 編輯工具類代碼

說明:在工具類中定義方法.之后測試查看效果

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM