首頁>技術>

Redis系列

第1篇

Redis是目前使用最廣泛的快取程式之一,也被應用於多種場景,例如資料快取、分散式鎖等,Redis官方提供了多種部署架構,以滿足不同應用場景下對於高可用和擴充套件性的要求。

01

單節點(single)

單節點的部署是最簡單的,只要啟動一個redis程序就可以了,但是不具備高可用性,一般生產環境不建議使用,其主要有以下問題:

單節點,一旦出問題,服務將會不可用【1】單節點讀能力有限,無法擴充套件【2】單節點寫能力有限,無法擴充套件【3】單節點的儲存能力受到單機的限制【4】

02

主從複製(master-slave)

由於單節點服務不可用問題【1】,Redis提供了主從複製的功能,使用主從複製模式,一旦主節點服務不可用,則可以啟用從節點,儘量保證資料量不丟失(Redis主從複製提供的是最終一致性)。另外一方面從節點可以擴充套件主節點的讀能力,分擔大併發量的讀操作【2】。

redis主從複製每從節點只能有一個主節點,而主節點可以同時具備多個從節點,複製流量只能是單向的,只能從主節點流向從節點。配置Master-Slave有三種方式:

在redis配置檔案中增加配置:slaveof {masterHost} {masterPort}

在啟動redis-server的命令列後新增:--slaveof {masterHost} {masterPort}

啟動redis-server以後登陸redis-server終端輸入命令:slaveof {masterHost} {masterPort}

注意:如果主節點配置了requirepass,則需要從節點配masterauth引數。

如何檢視節點是否已經成功配置了Master-Slave配置呢?可以在節點上執行命令info replication,這個命令在master節點和slave節點上展示的內容不一樣,可以看到各自的角色資訊master/role,主節點或者從節點IP和埠資訊。

主節點127.0.0.1:6379>info replication

127.0.0.1:6379>info replication# Replicationrole:masterconnected_slaves:1slave0:ip=127.0.0.1,port=6380,state=online,......

從節點127.0.0.1:6380>info replication

127.0.0.1:6380>info replication# Replicationrole:slavemaster_host:127.0.0.1master_port:6379master_link_status:upmaster_last_io_seconds_ago:5master_sync_in_progress:0...

一個節點可以使用slaveof {masterHost} {masterPort}變成一個從節點,也可以使用slaveof no one斷開復制,重新變成一個主節點。

另外,從節點還可以實現切換主節點的功能,將當前從接待你對主節點的複製切換到對另外一個新的主節點的複製,只需要操作命令:slaveof {newMasterHost} {newMasterPort}

切換主節點涉及流程如下:

斷開與當前主節點的複製關係與新的主節點建立複製關係刪除從節點當前的所有資料(特別注意,一旦操作失誤,原來的資料將會被全部清空)從新的主節點複製資料

Redis主從複製解決了單節點的第【1】【2】問題,但是【3】【4】問題仍然無法解決,並且引入了新的問題:

主節點服務不可用,需要手工介入啟用從節點升級為主節點,並且需要通知應用方修改主節點的地址,需要人工介入【5】

03

哨兵模式(redis sentinel)

為了解決第【5】個問題,Redis官方提供了哨兵sentinel模式,保證主從複製模式下從節點升級為主節點的過程全部自動化,sentinel有完善的不可達檢測機制,主節點選舉機制,以及主節點更換通知機制,從而實現了真正的高可用。

Redis sentinel有若干個sentinel節點和資料節點組成,sentinel節點定期會對所有節點的狀態進行監控。當sentinel叢集判斷某個節點不可達時,會選擇其中一個sentinel節點執行故障轉移任務,並通知到呼叫的客戶端。以一主兩從三哨兵為例:

故障轉移過程如下:

主節點故障,兩個從節點與主節點失去連線,主從複製失敗sentinel節點透過監控發現主節點的故障,多個sentinel達成一致以後,選擇了其中一個sentinel節點作為leader sentinel

leader sentinel選擇其中一個slave,傳送slaveof no one命令給這個從節點,使其成為新的主節點。

sentinel通知應用端新的主節點資訊sentinel傳送命令給另外的slave,讓其去複製新的master節點等舊的主節點恢復以後讓其以slave的身份去複製新的master節點

注意事項

sentinel模式本質上還是主從模式,但是具備了故障的自動轉移的功能。sentinel節點本身也會有單點的問題,至少兩個節點才能解決單節點問題,但還是建議至少三個節點,多個節點可以有效防止誤判。sentinel叢集可以配置同時監控多個主節點,也即監控多個主從叢集,每個叢集只能有一個master,但是slave可以有多個。

04

叢集模式(redis cluster)

以上分析我們知道,即便使用了哨兵模式,但是還是存在【3】【4】問題,本質上是原來的架構寫擴充套件能力受限,當遇到大併發、大流量、記憶體不足等情況,就會出現瓶頸。典型的解決方案有:

客戶端分割槽 由客戶端對資料進行分割槽處理,部署多套叢集,不同的資料依據不同的邏輯轉發到不同的叢集,需要客戶端自行處理資料路由,需要維護多套redis,成本較高。使用代理搭建redis客戶端代理,簡化客戶端的訪問,資料路由等由代理實現。但是這引入了新的元件,部署架構更加複雜,並且還涉及代理本身的高可用問題。

為了解決以上的不足,官方終於提供了分散式叢集方案,這就是Redis Cluster。如下圖所示,Redis Cluster至少要求6個節點才能組成一個高可用的叢集,6個節點是三主三從。這有兩個方面的原因,一方面要求至少3個主節點,是為了避免網路分割槽的情況導致的腦裂問題,所以判斷節點是否可聽過服務需要至少過半數的節點的同意才行。另外一方面,每個節點至少需要有一個slave節點,當master故障時可以提升為主節點繼續提供服務。

要理解Redis Cluster架構,我們需要理解其資料分佈原理、節點通訊原理、請求路由、擴縮容的方案。

資料分佈原理

由於叢集中有多個master節點,所以使用者的資料需要依據某種規則被存放在某個節點下,當查詢的時候也要知道資料從哪個節點去取,這就是資料分佈方案要解決的問題。

Redis-Cluster使用了虛擬槽分割槽的方案來完成資料對映。首先,定義了一個整數集合,命名為槽slot,其範圍為0~16383,然後使用雜湊函式slot=CRC16(key)&16383將資料對映到某個槽上,再將槽分配給不同的節點,每個節點負責一定數量的槽,這樣子達到了將資料分配到節點的目的。槽是redis cluster資料管理和遷移的基本單位。

節點通訊原理

分散式系統一般都會涉及儲存叢集元資料資訊的功能,對應到redis叢集則是例如資料槽分配給哪個節點,節點的IP和埠等資訊是多少等資訊。一般來說有兩種方案:集中式和P2P方式。集中式一般會選出一個leader節點或者master節點,由此節點來進行元資料管理,P2P方式則是透過資料交換,最終使得叢集的所有節點都獲得叢集的元資料資訊,節點間的地位是平等的。redis cluster選擇的是P2P的方式。

每個redis節點都會單獨開闢一個TCP埠用於節點的通訊,採用Gossip協議進行互動,以ping訊息為例流程如下:

1、每個節點開啟用於叢集內通訊的TCP埠,用於叢集通訊。

2、每個節點配置幾個種子節點,傳送ping訊息。

3、接收到ping訊息的節點回復pong訊息響應每個節點可能知道叢集的全部節點資訊,也可能只知道一部分,但是當進行一段時間的ping/pong訊息互動以後,最終會達成每個節點都獲得叢集全部狀態的效果。

Gossip協議定義了多種訊息格式:ping、pong、meet、fail等,作用各不相同。

請求路由

上面說到所有的master節點都是平等的,客戶端連線時是不知道請求的資料是應該落在哪個節點上的,那麼應該如何進行請求的路由呢?

這裡可能會有疑問,為何不適用代理的方式呢,可以完全與redis節點解耦合。我的理解是增加了一層代理以後引入了新的元件,架構會更加複雜,且效能會有損耗,所以官方選擇直連redis節點的方案。

redis任意節點都可以接收客戶端的請求,收到請求以後會根據雜湊函式計算出資料對應的槽,而槽分配在哪個節點經過節點通訊以後是節點本身是清楚的,於是,如果發現槽分配的是自己,則進行請求處理,如果發現是在其他節點,則返回MOVED重定向,表示資料在其他的節點,由客戶端重定向後去請求其他的節點。

19
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 前端人必看!2020JavaScript調查報告新鮮出爐