redis-集羣(1)

1、集羣簡介

Redis Cluster是redis3.0後正式推出的分佈式解決方案。node

以前介紹了複製和哨兵,解決了高可用問題,經過複製,讀操做能夠分發到多個節點(讀實現了負載均衡),可是寫操做依然只有一個節點,沒法實現寫操做的負載均衡,可是依然面臨單機內存和併發的瓶頸。redis

集羣就是用來解決寫操做負載均衡的問題。其核心有兩個做用shell

  1. 數據分片:這是集羣最最核心的功能,經過發片,突破了redis的單機內存限制,數據發佈到多個節點,每一個節點均可以提供讀寫操做,響應能力也獲得提升
  2. 高可用:這個和複製-哨兵同樣,每一個節點都由主從組成,同時實現了自動故障轉移。

2、Redis Cluster數據分區原理

2.1 Hash分區方案

常見哈希分區主要兩種:數據庫

  1. 節點取餘分區
  2. 一致性哈希(distributed hash table)

2.1.1節點取餘分區

\[hashCode=hash(key) mod N \]

N爲節點的數量。這種方案優勢是簡單,缺點是當有節點數量變化(擴容or縮容),數據節點映射關係須要從新計算,會致使數據從新遷移。併發

通常用於節點能夠預估不變的場景,好比數據庫分表分庫,好比訂單庫能夠分64個,orderId mod 64可獲得這個訂單數據應該寫入那個庫。負載均衡

2.1.2一致性哈希

實現思路是爲系統中的每個節點分配一個token,範圍通常爲0~2的32次方,這個這些token構成一個哈希環。分佈式

當有數據寫入時,先根據key計算出哈希值X,而後順時針尋找到第一個大於X的token的節點,而後把值存入該節點便可。下圖中:函數

  1. A存入node1
  2. B存入node2
  3. 。。。

一致性哈希分區中,若是增長或者減小節點,隻影響節點改節點相鄰的節點,其餘節點毫無影響,好比在node1以前增長一個節點,只會使得原來存儲到node1的數據一部分數據(好比A)轉移到新節點,其餘節點毫無影響。3d

一致性哈希的最大問題是,當節點比較少時,新增或者刪除節點會致使數據的分配嚴重不均衡。 在上圖中,若是刪除node1和node2:code

  1. 原有node1和node2存儲的數據會所有遷移到node3,致使node3的數據從原來的的1/6變成了1/2
  2. node(4,5,6)三個節點總共存儲1/2,嚴重不平衡。

虛擬槽分區是對一致性哈希的改進,用來解決負載均衡的問題。

2.2 Redis Cluster數據分區方案

Redis Cluster採用虛擬槽分區,槽是介於實際節點和數據之間的虛擬概念,每一個節點對應必定範圍的槽,每一個槽包含必定範圍內的哈希值,使用了虛擬槽分區後,數據的映射關係從hash-》節點變成了hash-》槽-》節點

Redis Cluster槽的範圍是16384(016383)。全部鍵基於哈希函數映射到016383整數槽內(CRC取模),計算公式:

\[slot = CRC(key) mod 16383 \]

示意圖以下:

使用虛擬槽分區後,節點的變更對系統影響較小,好比上圖中,刪除node1,只須要對0-3276的槽從新分配便可。

3、搭建集羣

搭建一個三主三從的集羣,在同一臺機器上,由端口號進行區分。

  1. 三主:7000,7001,7002
  2. 三從:8000,8001,8002

3.1 準備節點

7000節點配置以下:

#端口號
port 7000
#開啓集羣模式
cluster-enabled yes
#節點超時時間(毫秒)
cluster-node-timeout 15000
#集羣內部配置文件
cluster-config-file "nodes-7000.conf"
logfile "log-7000.log"
protected-mode no
daemonize yes

依次配置7001,7002,8000,8001,8002。

啓動6個節點:

src/redis-server redis-7000.conf 
src/redis-server redis-7001.conf 
src/redis-server redis-7002.conf 
src/redis-server redis-8000.conf 
src/redis-server redis-8001.conf 
src/redis-server redis-8002.conf

配置相關說明

上面的配置中cluster-enabled 和cluster-config-file是集羣相關的配置。

cluster-enabled 設置爲yes,表明集羣模式,默認redis是單機模式。

cluster-config-file是集羣特有的配置文件,在redis啓動的時候若是發現沒有配置文件會自動建立一個配置文件。

打開配置文件,若是集羣配置文件已經存在,則直接讀取。集羣配置文件由redis自動維護,無需手動修改。

7000首次啓動後生成的集羣配置文件以下:

877e9d061f80cea70285e823cbc4246041752149 :7000@17000 myself,master - 0 0 0 connected 5474 5798 11459 11958 12706 13735
vars currentEpoch 0 lastVoteEpoch 0

記錄了集羣的初始狀態,最重要的是第一個40位的16進制字符串,是集羣的節點ID,節點ID在集羣初始化的時候只建立一次,重啓後會加載集羣配置文件進行重用。集羣節點ID不用於redis的運行id,運行id每次重啓後都會變好。

3.2 建立集羣

直接使用redis-cli命令來建立(redis5.0以後)

輸入命令

redis-cli --cluster create 192.168.118.129:7000 192.168.118.129:7001 192.168.118.129:7002 192.168.118.129:8000 192.168.118.129:8001 192.168.118.129:8002 --cluster-replicas 1

--cluster-replicas 1表示每個主節點分配一個從節點。

(上面的warning是由於我把全部節點部署到了同一個機器)

輸入yes繼續

集羣配置成功,16384個slots分配完畢。

總體結構

Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.118.129:8001 to 192.168.118.129:7000
Adding replica 192.168.118.129:8002 to 192.168.118.129:7001
Adding replica 192.168.118.129:8000 to 192.168.118.129:7002

用上面命令建立的集羣是沒法手工指定主從關係的。

4、節點通訊原理

4.1 Gossip消息

Redis採用Gossip協議(P2P),Gossip協議的工做原理就是節點之間不斷通訊交換信息,一段時間後全部節點都會知道集羣的完整信息,相似於流言傳播,相似於下圖:

通訊過程:

  1. cluster中的每個節點都會單獨開闢一個TCP通道,用於節點之間的彼此通訊,通訊端口號是在節點基礎端口號上加10000,好比原端口號是7000,則對應的Gossip端口號則爲17000。
  2. 每一個節點在固定週期內經過特定規則選擇幾個節點發送ping消息
  3. 接收到ping消息的節點用pong消息做爲響應。

Gossip消息類型:

Gossip消息解析流程:

meet

4.2 通訊節點選擇

上面的Gossip消息中,ping/pong消息都須要攜帶當前節點的信息和部分其餘節點的信息(狀態等),這些頻繁的信息交換勢必會加劇帶寬和計算負擔。依次每次選擇多少個節點進行通訊(每次要發給多少個節點)變得特別重要:

  1. 太多:交換成本高
  2. 太少:消息交換頻率低,影響故障判斷,節點發現的速度。

具體選擇:

選擇發送節點

5個節點是指集羣內隨機找5個節點,取其中一個其餘節點發送ping。

10次:針對上一步選出來的一個節點每100毫秒掃描一次本地的節點列表,若是發現節點最近一次接受pong消息的時間大於cluster-node-timeout/2 ,則須要給該節點發送ping消息,總節點數量:

  • num(node.pong_received > cluster_node_timeout/2)

ping消息數量

自身節點數量+1/10其餘節點的數量

因而可知,節點的cluster_node_timeout和整個集羣節點的數量都會影響集羣節點之間的信息交換。

相關文章
相關標籤/搜索