redis分片叢集搭建與使用詳解

2022-07-21 18:00:33

推薦學習:

前言

redis可以說在實際專案開發中使用的非常頻繁,在redis常用叢集中,我們聊到了redis常用的幾種叢集方案,不同的叢集對應著不同的場景,並且詳細說明了各種叢集的優劣,本篇將以redis 分片叢集為切入點,從redis 分片叢集的搭建開始,詳細說說redis 分片叢集相關的技術點;

  • 單點故障;
  • 單機寫(高並行寫)瓶頸;
  • 單機儲存資料容量限制;
  • 叢集自動伸縮;
  • 叢集自動故障下線與轉移;

搭建叢集架構圖

前置準備

1、準備一臺(或6臺伺服器,條件允許的情況下)虛擬機器器或伺服器;

本例為演示效果準備了一臺記憶體8G的伺服器,將通過埠進行master和slave的劃分

2、提前下載好redis安裝包;

搭建步驟

1、建立6個目錄檔案,分別用於儲存各個redis範例的資料

mkdir 7001 7002 7003 8001 8002 8003

2、在當前目錄下建立一個redis.conf檔案,內容如下

port 6379
# 開啟叢集功能
cluster-enabled yes
# 叢集的組態檔名稱,不需要我們建立,由redis自己維護
cluster-config-file /usr/local/soft/redis/6379/nodes.conf
# 節點心跳失敗的超時時間
cluster-node-timeout 5000
# 持久化檔案存放目錄
dir /usr/local/soft/redis/6379
# 繫結地址
bind 0.0.0.0
# 讓redis後臺執行
daemonize yes
# 註冊的範例ip
replica-announce-ip 本機公網IP
# 保護模式
protected-mode no
# 資料庫數量
databases 1
# 紀錄檔
logfile /usr/local/soft/redis/6379/run.log

3、批次將該組態檔拷貝到各個目錄下

echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

4、修改每個目錄下redis.conf,將其中的6379修改為與所在目錄一致

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

隨機開啟某個redis.conf看看是否修改成功

4、使用下面的命令進行啟動

/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/7001/redis.conf
/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/7002/redis.conf
/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/7003/redis.conf

/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/8001/redis.conf
/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/8002/redis.conf
/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/8003/redis.conf

執行完成後,可以看到6個redis範例已經開啟

建立叢集

通過以上的步驟,就開啟了6個redis的範例,但是這些範例之間並沒有形成一個叢集,接下來就需要執行相關的命令將它們構成一個叢集

1、使用如下命令構建叢集(5.0之後的版本的命令)

redis-cli --cluster create --cluster-replicas 1 IP地址:7001 IP地址:7002 IP地址:7003 IP地址:8001 IP地址:8002 IP地址:8003

關於上面命令的說明

  • redis-cli --cluster 或者 ./redis-trib.rb:代表叢集操作命令;
  • create:代表是建立叢集;
  • –replicas 1或者–cluster-replicas 1 :指定叢集中每個master的副本個數為1,此時節點總數 ÷ (replicas + 1)得到的就是master的數量。因此節點列表中的前n個就是master,其它節點都是slave節點,隨機分配到不同master ;

也可以通過 redis-cli --cluster help 命令進行叢集命令的檢視;

執行命令後,控制檯提示將會使用哪個範例作為master,哪個作為slave;

繼續輸入yes之後,將會按照上面的策略建立一個叢集出來

通過這個輸出的紀錄檔大概可以得出如下資訊:

  • 埠號依次為7001,7002和7003的為master節點;
  • 埠號依次為8001,8002和8003的為slave節點;
  • 埠號依次為7001,7002和7003的master節點,各自分配了一定區間的槽位數,分別是:[0-5460],[5461-10922],[10923-16383],即總共分配16384個槽位;

2、檢視叢集狀態

redis-cli -p 7001 cluster nodes

通過這個命令,可以清楚的看到叢集中各個範例節點的主從狀態,範例ID(唯一身份標識),槽位區間等資訊

Redis雜湊插槽說明

其實對redis分片叢集稍有了解的同學應該知道,redis分片叢集在邏輯上將叢集中的所有節點構成了一塊完整的記憶體空間,資料寫入進來後,具體存放到哪個節點呢?所以叢集引入了一個邏輯尚的插槽概念,即將叢集劃分為16384個槽位,叢集中的每個節點佔據一部分槽位數(這個紀錄檔中可以看出來);

那麼當某個具體的key寫入的時候,叢集將會通過一定的演演算法,將要寫入的資料路由到指定的插槽上去;

這裡有個點需要注意,資料key不是與節點繫結,而是與插槽繫結。

redis叢集會根據key的有效部分計算插槽值,分兩種情況:

  • key中包含"{}",且「{}」中至少包含1個字元,「{}」中的部分是有效部分;
  • key中不包含「{}」,整個key都是有效部分;

舉例來說:key是num,那麼就根據num計算,如果是{應用名稱}num,則根據「應用名稱」計算。計算方式是利用CRC16演演算法得到一個hash值,然後對16384取餘,得到的結果就是slot值

下面不妨看下效果

通過上面的演示可以發現,經過叢集計算的key將會分配到不同的插槽上,也就是說,key是與插槽繫結,而不是與某個節點繫結,想想為什麼會這樣呢?

思考下面這個需求

如何將同一類資料固定的儲存在同一個Redis範例?

簡單來說,如果key的分配完全沒有規則的話,當涉及到某個業務類的資料對應的key隨機分配到不同的節點上面時,取值的時候就會出現像上面的重定向跨節點的問題,一定程度上提升效能;

解決辦法

這一類資料使用相同的有效部分,例如key都以{業務ID}為字首

叢集伸縮(新增節點)

reids的cluster模式下,有一個比較強的功能就是叢集的伸縮能力,即在現有的叢集基礎上,可以根據實際的業務需求,進行叢集的伸縮,下面來演示下給上面的叢集新增一個新節點的步驟;

1、在當前目錄下拷貝一個目錄

2、修改組態檔的埠

sed -i s/6379/7004/g 7004/redis.conf

3、啟動這個範例

/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/7004/redis.conf

4、使用下面的命令將7004範例假如叢集

redis-cli --cluster add-node IP:7004 IP:7001

5、再次檢視叢集狀態

redis-cli -p 7001 cluster nodes

通過上面的狀態資訊發現,7004這個節點雖然加入了叢集,併成了master,但是叢集並沒有給它分配任何的插槽

6、分配插槽

分配插槽的基本思路是,從現有的某個節點上遷移部分插槽到新的節點即可,執行下面的命令進行插槽分配

redis-cli --cluster reshard 101.34.23.80:7001

執行命令後將出現下面的提示,這裡輸入你要轉移的插槽數量

將7004對應的範例ID輸入即可

輸入yes後開始移動插槽

移動完成後,再次檢視叢集狀態,這時候7004對應的節點就分配到了從0 ~ 500的數量的插槽

故障轉移

redis的cluster模式的叢集,還具備一定的故障轉移能力,比如在上面的架構模式下,當叢集中的某個master節點宕機之後,會出現什麼情況呢?下面我們來模擬下這個過程,看看效果如何

1、使用watch命令監控下叢集的狀態

通過這個命令可以實時檢視叢集的動態紀錄檔變化

watch redis-cli -p 7001 cluster nodes

2、手動將7002範例的master宕機

redis-cli -p 7002 shutdown

從上面的監控紀錄檔不難發現,當7002掛掉後,過了一會兒與叢集以及它的從節點8003失去了聯絡,然後8003這個節點升級為master節點;

3、手動將7002範例啟動起來

/usr/local/soft/redis/redis60/src/redis-server /usr/local/soft/redis/7002/redis.conf

再次分析紀錄檔,可以看到這時候7002只能以slave的身份加入了叢集,事實上在某些情況下,我們仍然希望這個宕機的節點恢復後依然是主節點,這該怎麼辦呢?這就涉及到了手動故障轉移,主要操作步驟如下:

  • 使用redis-cli連線7002節點;
  • 執行cluster failover命令;

在上面執行之後的情況下,7002是一個slave節點

執行 CLUSTER FAILOVER 命令,觀察紀錄檔動態變化,通過紀錄檔變化,可以看到,命令執行完畢後,7002很快就變成了master,而8003成了slave;

通過以上步驟就完成了redis的cluster模式下的故障轉移的過程

使用redistemplate存取分片叢集

1、引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、將組態檔中的叢集地址修改成下面這樣即可

spring:
  redis:
    cluster:
      nodes:
       - 叢集IP:7001
       - 叢集IP:7002
       - 叢集IP:7003
       - 叢集IP:7004
       - 叢集IP:8001
       - 叢集IP:8002
       - 叢集IP:8003

至於具體的程式碼部分,可以參考下面的這個測試案例

	@Autowired
    private RedisTemplate<String,String> redisTemplate;

    //localhost:8083/set?key=b&value=123
    @GetMapping("/set")
    public void set(@RequestParam String key,@RequestParam String value){
        redisTemplate.opsForValue().set(key,value);
    }

    //localhost:8083/get?key=b
    @GetMapping("/get")
    public String get(@RequestParam String key){
        return redisTemplate.opsForValue().get(key);
    }

推薦學習:

以上就是redis分片叢集搭建與使用詳解的詳細內容,更多請關注TW511.COM其它相關文章!