day13 一致性hash演算法(快取擴容) redis哨兵機制(高可用) redis叢集(高可用,快取擴容)

Alex-box發表於2020-12-15

Redis分片機制說明

1.1 一致性hash演算法

1.1.1 一致性hash演算法介紹

一致性雜湊演算法是一種特殊的雜湊演算法,目的是為了解決分散式快取的問題。在移除或者新增一個伺服器的時候,能夠儘可能小的改變已存在的服務請求與處理請求伺服器之間的對映關係。一致性雜湊解決了簡單雜湊演算法在分散式雜湊表中存在的動態伸縮問題。

1.1.2 一致性Hash原理說明

常識:
1. 對相同的資料hash得到的結果相同
2. 常見的hash值 8位十六進位制數 2^32種可能性

雜湊環: 在雜湊環上存放著快取伺服器中的多個節點,伺服器的節點存放位置是根據伺服器的節點得到的雜湊值來確定的,當進行快取資料儲存的時候,對key值進行hash計算,獲取到hash值,判斷在hash環上的位置,根據key的雜湊值所在雜湊環的位置,根據順時針進行伺服器選取,將資料儲存到快取伺服器中.
在這裡插入圖片描述

1.1.3 平衡性說明

說明: 平衡性是指hash的結果應該平均分配到各個節點,這樣從演算法上解決
了負載均衡問題,如果發現資料分部不均勻,則採用虛擬節點的方式,實現資料的平衡,如果一次平衡不能達到目標則多次生成虛擬節點,但是資料平衡沒有辦法做到絕對的平均
在這裡插入圖片描述

1.1.4 單調性

是指分散式快取在新增或刪減節點時,不影響系統的正常執行
如果是新增或者刪減節點時,儘可能不改變原有的資料結構

1.1.4 分散性

分散性是指快取中的資料應該分散的存放在分散式叢集的各個快取節點中,不必每個節點都儲存所有的資料,(每個節點都有其自己的備份)[其實也就是快取擴容的結果將多個節點看做是一個大的快取伺服器]

2. redis哨兵機制(sentinel: 哨兵)

相當於是tomcat伺服器的代理伺服器nginx,實現伺服器的高可用(使用代理管理多臺tomcat伺服器的請求分發,緩解單個伺服器訪問壓力),在資料庫伺服器中也要實現資料庫的高可用,高可用的前提是實現資料庫之間的主從掛載,同樣使用代理伺服器mycat完成對多臺伺服器之間的的高可用配置,使用mycat管理的主從伺服器之間想要實現資料庫高可用,還需要考慮資料庫安全問題,如果主機發生當機現象,由從機代理執行主機功能,所以單一的主從掛載不足以滿足次要求,需要設定主從伺服器之間的資料同步,方便主機同步從機資料(也就是資料庫的互為主從掛載)

redis實現伺服器高可用功能的前提是redis伺服器的主從掛載,但是僅僅是前提,實現高可用的主要操作還是要依賴於redis的哨兵機制,哨兵機制其實就是一個針對多個redis主從伺服器的管理伺服器,通過對主機狀態的監控,當主機遇到異常當機時使用哨兵進行選取一個從機當做主機繼續提供服務,實現伺服器的高可用

2.1 redis分片機制問題

說明: 如果redis分片中有一個節點當機,則可能影響整個伺服器執行,redis分片並沒有實現高可用(僅僅是實現了redis快取的擴容)

2.2 redis實現主從結構構建

2.2.1 賦值配置檔案(建立多個redis伺服器,直接複製多個conf配置檔案即可)

在這裡插入圖片描述

2.2.2 準備三臺redis

在這裡插入圖片描述
###2.2.3
命令1: info replication

role角色: 表示該伺服器是主機還是從機,master表示該伺服器是主機,slave表示是從機,slave: 是奴隸的意思,現在顯示連結從機數是0
命令2; slaveof IP PORT 主從掛載命令(在從機中執行此命令,表示向指定ip地址埠號的伺服器設定為自己的主機)
在從機中設定掛載主機
檢查主機狀態
role角色為slave表示該伺服器為從機,主機的ip(host),埠號port
檢查充當從機的主從掛載狀態,從機連線數為2,表示掛載了兩個從機,從機slave
關於主從結構說明:
主和從都知道,當前的主從的狀態,並且只有主機可以進行寫操作,從機只能進行讀操作(如果在從機中進行寫操作,控制檯會直接報錯,表示該伺服器是一個從機不能進行寫操作)

2.2 redis哨兵機制工作原理

  1. 當哨兵啟動時,首先會監控主機,從主機中獲取當前所有的節點的狀態,同時哨兵開啟心跳檢測機制

  2. 當主機發生當機的現象時,由於哨兵有PING-PONG機制,發現主機當機,則哨兵進行選舉
    PING-PONG機制,也就是哨兵ping一下主機,主機給出響應,如果主機連續三次心跳檢測,也就是哨兵ping三次,主機沒有任何響應,說明此時主機已經遭遇不測,哨兵開始選取新的主機

  3. 當選舉成功之後,新的主機當選之後,其他的節點當新主機的從機(原先的主機恢復後,並不像資料庫伺服器主機修復之後,同步從機資料繼續當主機,而是充當新主機的從機進行工作)

在這裡插入圖片描述

2.3 編輯哨兵配置檔案

在這裡插入圖片描述

  1. 關閉保護模式
    預設該設定在配置檔案中被註釋表示預設保護模式是開啟的我們使用遠端方式訪問需要關閉其保護模式
  2. 開啟後臺執行
    在這裡插入圖片描述
  3. 編輯監控配置
    哨兵監控我的主機: ip地址 埠號 哨兵選取生效票數,如果有三個哨兵,該值應該設定為2,表示兩票贊成即通過
    注意事項: mymaster為配置的主機名,主機名可以自己定義
  4. 修改選舉時間
    哨兵選舉主機時間限制,為10秒鐘
    從機被選舉為主機後設定超時時間,如果在指定時間內沒有上任主機的位置,就重新選取其他的從機當做主機,超時時間預設為三分鐘

2.4 啟動哨兵服務

命令: redis-sentinel sentinel.conf
所謂的哨兵服務其實就是一個特別的redis服務,依舊需要使用配置檔案開啟服務,與一般的redis快取伺服器相同,只不過是設計的時候加入了一些特有的功能,讓其成為了一個redis哨兵伺服器
在這裡插入圖片描述
高可用檢查:
1. 先關閉主機,等待10秒鐘檢查是否進行選舉(10s為設定的哨兵選取新的主機時限)
2. 啟動6379,檢查是否當選新主機的從機
在這裡插入圖片描述
哨兵機制設定出現問題解決方案:
重新複製主從伺服器的配置檔案,不能使用之前配置未生效的伺服器的配置檔案,因為在哨兵機制中哨兵伺服器啟動時,就會對其他快取伺服器的配置檔案進行控制,也就是雖然哨兵沒有生效但是已經對管理的快取伺服器配置檔案作出了修改,所以如果還是用原先的配置檔案啟動伺服器,有可能還是會出現問題,所以最直接的方法就是完整的重新配置哨兵機制需要一切檔案

2.5 哨兵測試API

 /**
     * 測試redis哨兵機制:
     *  此時的哨兵管理著多個redis伺服器,但是使用的時候還是將主從掛載的多個伺服器當做一個伺服器進行使用
     *  使用時還需要使用一個哨兵池物件,獲取到一個哨兵物件,因為一個哨兵物件其實就相當於是一個redis伺服器物件
     */
    @Test
    void testSentinel(){
        Set<String> set=new HashSet<>();
        set.add("192.168.126.129:26379");//建立哨兵池物件時需要傳遞一個set集合,集合中儲存的是找到對應哨兵伺服器的ip地址及埠號,
        JedisPoolConfig poolConfig = new JedisPoolConfig();//這是一個配置物件,配置的是哨兵池的配置屬性,當
        //建立哨兵池物件的時候,需要此配置物件引數
        poolConfig.setMaxTotal(1000);//設定哨兵池的最大連線數
        poolConfig.setMaxIdle(40);//設定哨兵池最大閒置哨兵數
        poolConfig.setMinIdle(10);//設定哨兵池最小閒置哨兵數
        JedisSentinelPool sentinelPool=new JedisSentinelPool("mymaster", set, poolConfig);
        //從池中取出一個哨兵物件,實際上取出的是哨兵選取出來的redis伺服器物件
        Jedis jedis = sentinelPool.getResource();
        jedis.set("sentinel", "哨兵機制測試");
        String sentinel = jedis.get("sentinel");
        System.out.println(sentinel);
        //因為是從池中獲取到的redis伺服器物件,使用完畢之後,需要歸還連線(使用close()歸還連線)
        jedis.close();
    }

2.6 Springboot整合哨兵機制

2.6.1 編輯Pro配置檔案

這裡配置的連線redis伺服器是連線的redis哨兵伺服器,由哨兵伺服器選舉主機,也就是由哨兵伺服器管理redis實現高可用的主從掛載伺服器

2.6.2 編輯配置類

在這裡插入圖片描述

2.6.3 編輯CacheAOP

在這裡插入圖片描述

2.6.4 關於分片/哨兵總結

  1. redis分片主要的作用實現記憶體的擴容,缺點: 沒有實現高可用(快取資料高可用是在主從掛載伺服器的基礎上使用哨兵機制對主從掛載的快取伺服器進行管理控制,減少伺服器不能提供服務的時間)
  2. redis哨兵主要的作用就是實現了redis節點高可用,缺點: 沒有實現快取擴容(因為哨兵控制的多臺伺服器只能當做一臺伺服器進行使用,不能同時進行工作,但如果提供多個哨兵的話,不好實現,以為本來哨兵伺服器就是一個三級快取伺服器(引入的第三方監控),充當使用者和快取伺服器之間的媒介,使用多個哨兵伺服器不合適)

redis哨兵機制實際上就是引入第三方的監控,但是需要保證第三方的高可用,就必須引入更多的資源

3. Redis叢集

參見京淘新版本資料

3.1 叢集搭建錯誤解決方案

注意事項: redis叢集搭建要求節點的資料必須為null

  1. 將所有的redis節點服務全部關閉 sh stop.sh (使用設計好的shall命零)

  2. 刪除多餘的檔案(伺服器執行產生的nodes.conf和持久化檔案dump.rdb檔案)
    在這裡插入圖片描述

  3. 然後重啟redis叢集

 redis-cli --cluster create --cluster-replicas 1 192.168.126.129:7000 192.168.126.129:7001 192.168.126.129:7002 192.168.126.129:7003 192.168.126.129:7004 192.168.126.129:7005


3.2 Redis叢集入門案例

 /**
     * 測試redis叢集: 使用的api為
     */
    @Test
    void testCluster(){
        Set<HostAndPort> set=new HashSet<>();
        set.add(new HostAndPort("192.168.126.129", 7000));
        set.add(new HostAndPort("192.168.126.129", 7001));
        set.add(new HostAndPort("192.168.126.129", 7002));
        set.add(new HostAndPort("192.168.126.129", 7003));
        set.add(new HostAndPort("192.168.126.129", 7004));
        set.add(new HostAndPort("192.168.126.129", 7005));
        JedisPoolConfig config=new JedisPoolConfig();//使用jedis池配置類配置叢集中節點的最大連線數(因為jedis池物件中預設的最大連線數為8,我們需要建立
        //叢集物件的時候傳遞一個叢集中池配置物件 )
        config.setMaxTotal(1000);//配置最大連線節點數為1000
        config.setMaxIdle(40);
        config.setMinIdle(10);
        JedisCluster jedisCluster=new JedisCluster(set,config);
        //叢集物件可以自動的對快取資料庫進行管理,我們只需要操作叢集物件操作快取資料庫即可,其實也就相當於一種反向代理,處理請求的方式,使用者不知道訪問的是哪個redis快取伺服器
        jedisCluster.set("cluster", "測試redis叢集配置");
        String cluster = jedisCluster.get("cluster");
        System.out.println(cluster);
    }

3.3 redis叢集面試題

  1. redis叢集中一共可以儲存16384個資料?
    不對: redis中儲存多少資料完全有記憶體決定(只不過是因為redis叢集中對節點存放資料採用的是hash槽演算法,將redis叢集分為16384個槽位,每個節點管理多少個槽位,並不是只能儲存這些個資料,而是經過hash計算屬於某些槽位的資料交給相應的節點進行儲存)
  2. redis叢集中最多可以有多少個redis主機?
    redis叢集中的主機數是由hash槽的數量決定的一個redis註解至少管理一個槽位的資料,所以叢集中最多可以有16384個redis主機(但如果是叢集中最多有多少個伺服器,從機也算叢集管理的伺服器)

3.4 SpringBoot整合redis叢集

3.4.1 編輯pro配置檔案

#配置單臺redis
#redis.host=192.168.126.129
#redis.port=6379

#配置redis分片機制
#redis.nodes=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381

#配置redis哨兵機制
#redis.node=192.168.126.129:26379

#配置redis叢集
redis.nodes=192.168.126.129:7000,192.168.126.129:7001,192.168.126.129:7002,192.168.126.129:7003,192.168.126.129:7004,192.168.126.129:7005


3.4.2 編輯配置類

@Configuration  //標識我是一個配置類   一般與@Bean註解聯用
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {

    @Value("${redis.nodes}")
    private String nodes;   //node,node,node

    @Bean
    public JedisCluster jedisCluster(){
        Set<HostAndPort> nodesSet = new HashSet<>();
        String[] nodeArray = nodes.split(",");
        for (String node : nodeArray){  //host:port
            String host = node.split(":")[0];
            int port = Integer.parseInt(node.split(":")[1]);
            HostAndPort hostAndPort = new HostAndPort(host, port);
            nodesSet.add(hostAndPort);
        }
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(1000);
        config.setMaxIdle(60);
        config.setMinIdle(20);
        return new JedisCluster(nodesSet,config);
    }
    }

3.4.3 編輯CacheAOP

在這裡插入圖片描述

相關文章