自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一個包含10節(jié)點的Redis集群實踐案例

存儲 存儲軟件 Redis
Redis 通常不會被用作主要的數(shù)據(jù)存儲,但它在存儲和訪問可容忍丟失的臨時數(shù)據(jù)(如度量指標、會話狀態(tài)、緩存)方面卻獨有長處,并且速度非???,不僅提供了最佳性能,還內(nèi)置了一組非常有用的數(shù)據(jù)結(jié)構(gòu)。它是現(xiàn)代技術(shù)棧中最常見的主要部件之一。

Redis 通常不會被用作主要的數(shù)據(jù)存儲,但它在存儲和訪問可容忍丟失的臨時數(shù)據(jù)(如度量指標、會話狀態(tài)、緩存)方面卻獨有長處,并且速度非???,不僅提供了最佳性能,還內(nèi)置了一組非常有用的數(shù)據(jù)結(jié)構(gòu)。它是現(xiàn)代技術(shù)棧中最常見的主要部件之一。

Stripe(一家做支付的硅谷創(chuàng)業(yè)公司)的速率限定器就是基于 Redis 構(gòu)建的,這些限速器運行在一個 Redis 實例上。Redis 主服務(wù)器有一些用于失效備援的追隨者,不過在任何時候,都只有一個節(jié)點在處理讀寫操作。

各種消息來源聲稱,一個 Redis 節(jié)點每秒可以處理百萬次操作。盡管我們的操作沒有那么多,但也不會很少。每個速率限定器都需要運行多個 Redis 命令,而每個 API 請求都要通過很多個速率限定器。所以,每個節(jié)點每秒鐘需要處理數(shù)萬次到數(shù)十萬次的操作。

[[229892]]

如果節(jié)點出現(xiàn)飽和,就會不斷出現(xiàn)故障。我們的服務(wù)可以容忍 Redis 的不可用,因此大多數(shù)情況下是沒有問題的,但在某些情況下,問題的嚴重程度會升級。我們最后通過遷移到包含 10 節(jié)點的 Redis 集群來解決這個問題。對性能的影響可以忽略不計,重要的是現(xiàn)在我們可以實現(xiàn)水平可伸縮。

改造前后的錯誤率比較:

使用 Redis 集群后錯誤率明顯降低

在更換系統(tǒng)之前,應(yīng)該先了解導(dǎo)致原始故障的原因。

雖說 Redis 使用了單線程模型,但也并非那么嚴格,因為后臺還是使用了其他線程來處理一些操作,比如刪除對象,不過所有正在執(zhí)行的操作還是會阻塞在單個控制點上。

要理解這些并非難事——Redis 操作(無論是單一命令、MULTI 還是 EXEC)的原子性保證源于它一次只執(zhí)行一個操作。即便如此,Redis 還是有可能會采用并行機制,F(xiàn)AQ 中的一些內(nèi)容表明,5.0 之后的版本有可能考慮采用多線程設(shè)計。

單線程模型確實是我們的瓶頸所在,在登錄到原始節(jié)點時可以看到,單核的使用率達到了 100%。

我們發(fā)現(xiàn),即使開啟了最大容量,Redis 也會自動優(yōu)雅地降級。主要表現(xiàn)是,與 Redis 發(fā)生交互的節(jié)點的基線連接性錯誤率在增加——為了容忍發(fā)生故障的 Redis,它們受到連接和讀取超時(約 0.1 秒)方面的限制,并且無法在給定時間內(nèi)建立用于執(zhí)行操作的連接。

這種情況在大多數(shù)時候是沒有問題的。只有當合法用戶成功通過身份驗證并在底層數(shù)據(jù)庫上進行昂貴的操作時(也就是說,數(shù)量級超過允許的范圍),它才會成為問題。這種昂貴的操作是相對而言的——從列表中返回一組對象比用 401 錯誤來拒絕請求或用 429 錯誤來告知超制都要昂貴得多。這些昂貴的操作通常都是因為用戶運行高并發(fā)程序而導(dǎo)致的。

這些流量高峰會導(dǎo)致錯誤率成比例增加,并且很多流量將被允許通過限速器,因為在發(fā)生錯誤時,限速器默認允許請求通過。這會給后端數(shù)據(jù)庫帶來更大的壓力,而且這種壓力所帶來的故障不會像 Redis 的過載故障那么優(yōu)雅。我們可以看到,分區(qū)幾乎完全不可操作,并且大量請求出現(xiàn)超時。

Redis 集群的分片模型

Redis 的核心價值是速度,而 Redis 集群的分布式結(jié)構(gòu)不會對此產(chǎn)生任何影響。與其他分布式模型不同的是,Redis 集群的操作不需要通過多個節(jié)點的確認,它看起來更像是一組獨立的 Redis 實例在分擔(dān)工作負載。這就是通過犧牲可用性來換取速度——與 Redis 獨立實例相比,Redis 群集操作的額外開銷可以忽略不計。

鍵空間總共被分為 16384 個槽,槽是通過穩(wěn)定的散列函數(shù)計算出來的,所有客戶端都知道該如何使用這個散列函數(shù):

  1. HASH_SLOT = CRC16(key) mod 16384 

例如,如果我們想執(zhí)行 GET foo,會得到 foo 的槽號:

  1. HASH_SLOT = CRC16("foo") mod 16384 = 12182 

集群中的每個節(jié)點將處理 16384 個槽中的一部分,具體取決于節(jié)點數(shù)量。節(jié)點間通過彼此交互來調(diào)節(jié)槽的數(shù)量、進行可用性轉(zhuǎn)移和再均衡。

分布在集群各個節(jié)點上的槽

客戶端使用 CLUSTER 系列命令來查詢集群的狀態(tài)。CLUSTER NODES 是一個常見的操作,用于獲取槽到節(jié)點的映射,其結(jié)果通常緩存在本地。

  1. 127.0.0.1:30002 master - 0 1426238316232 2 connected 5461-10922 
  2. 127.0.0.1:30003 master - 0 1426238318243 3 connected 10923-16383 
  3. 127.0.0.1:30001 myself,master - 0 0 1 connected 0-5460 

上面的輸出經(jīng)過了簡化,最重要的部分是第一列的主機地址和最后一列的數(shù)字。5461-10922 表示該節(jié)點處理從 5461 到 10922 的槽。

MOVED重定向

如果 Redis 群集中的某個節(jié)點接收到一個無法處理的命令,并不會嘗試將該命令轉(zhuǎn)發(fā)給其他節(jié)點。相反,客戶會被告知向其他節(jié)點嘗試發(fā)送該命令。這是通過 MOVED 響應(yīng)來實現(xiàn)的,MOVED 響應(yīng)消息包含了新的目標地址:

  1. GET foo 
  2.  
  3. -MOVED 3999 127.0.0.1:6381 

在集群進行再均衡期間,槽從一個節(jié)點遷移到另一個節(jié)點,而 MOVED 是服務(wù)器用于告訴客戶端,槽到節(jié)點的映射已經(jīng)發(fā)生了變化。

一個槽從一個節(jié)點遷移到另一個節(jié)點

每個節(jié)點都知道當前的映射關(guān)系,理論上,當一個節(jié)點在接收到無法處理的操作時,可以向正確的節(jié)點請求結(jié)果,并將結(jié)果轉(zhuǎn)發(fā)回客戶端,但 MOVED 其實是一種有意的設(shè)計。它通過將一些額外的復(fù)雜性交給客戶端去實現(xiàn),以便換取更快的速度。只要客戶端的映射是最新的,請求操作總能在一個 hop 之內(nèi)完成。由于再均衡相對較少出現(xiàn),因此在群集的使用期間,花在協(xié)調(diào)上的開銷可以忽略不計。

除了 MOVED 之外,Redis 集群還有其他一些特定的機制,但為了簡潔起見,我將跳過它們。完整的規(guī)范(https://redis.io/topics/cluster-spec)是深入了解 Redis 集群工作原理的重要資源。

客戶端如何發(fā)送請求

Redis 客戶端需要一些額外的功能來支持 Redis 群集,其中最重要的是要支持鍵的散列算法和用于維護槽到節(jié)點映射的方案,這樣它們就知道往哪里發(fā)送命令。

一般來說,客戶端會這樣操作:

  1. 在啟動時,連接到一個節(jié)點并獲得一個 CLUSTER NODES 的映射表。
  2. 正常執(zhí)行命令,根據(jù)槽和槽映射定位服務(wù)器。
  3. 如果收到 MOVED,返回到第一步。

我們可以在客戶端使用多線程進行優(yōu)化,在收到 MOVED 時將映射表標記為過時,一些線程向新的服務(wù)器發(fā)送命令,同時讓后臺線程異步刷新映射表。實際上,即使發(fā)生了再均衡,大多數(shù)槽也不需要移動,因此該模型允許大多數(shù)命令在沒有額外開銷的情況下繼續(xù)執(zhí)行。

使用散列標簽本地化多鍵操作

在 Redis 中,通過 EVAL 命令和自定義 Lua 腳本來運行多鍵操作是很常見的。這是實現(xiàn)速率限定器的一個特別重要的特性,因為通過單個 EVAL 命令分派的操作是原子性的。我們因此能夠正確計算剩余配額,即使存在可能會發(fā)生沖突的并發(fā)操作。

分布式模型會讓這種多鍵操作變得十分困難。由于每個鍵對應(yīng)的槽都是通過散列來計算的,因此不能保證相關(guān)鍵都會被映射到同一個槽。比如,user123.first_name 和 user123.last_name 顯然應(yīng)該是要放在一起的,但最終可能會分布在兩個完全不同的節(jié)點上。

舉例來說,我們有一個 EVAL 操作,將姓和名連接起來組合成一個人的全名:

  1. # Gets the full name of a user 
  2. EVAL "return redis.call('GET', KEYS[1]) .. ' ' .. redis.call('GET', KEYS[2])" 
  3.     2 "user123.first_name" "user123.last_name" 

調(diào)用示例:

  1. SET "user123.first_name" William 
  2. SET "user123.last_name" Adama 
  3. > EVAL "..." 2 "user123.first_name" "user123.last_name" 
  4. "William Adama" 

如果 Redis 集群沒有提供這種方式,該腳本將無法正常運行。幸運的是,我們通過使用哈希標簽來運行腳本。

對于需要跨節(jié)點操作的 EVAL,Redis 集群會禁止它們(這樣做也是出于速度方面的考慮)。所以,用戶需要確保 EVAL 中的鍵屬于相同的槽,可以通過散列標簽來獲得鍵的散列值。散列標簽就是鍵名字中的花括號,表示只有花括號部分用于散列。

我們對鍵進行重新定義,只對 user123 進行散列處理:

  1. > EVAL "..." 2 "{user123}.first_name" "{user123}.last_name" 

計算其中一個槽:

  1. HASH_SLOT = CRC16("{user123}.first_name") mod 16384 
  2.           = CRC16("user123") mod 16384 
  3.           = 13438 

.first_name 和{user123}.last_name 現(xiàn)在映射到了相同的槽,那么就可以執(zhí)行 EVAL 操作了。這是一個簡單的例子,不過相同的概念可被用于實現(xiàn)復(fù)雜的速率限定器。

遷移到 Redis 集群非常順利,最困難的部分是如何構(gòu)建一個可用于生產(chǎn)環(huán)境的 Redis 集群客戶端。即使到了今天,Redis 客戶端的質(zhì)量也是參差不齊,可能是因為 Redis 速度足夠快,以至于大多數(shù)人直接使用單個實例。

從設(shè)計方面看,Redis 集群的設(shè)計有很多值得一提的地方——簡單但功能強大。特別是當涉及到分布式系統(tǒng)時,許多實現(xiàn)過程非常復(fù)雜,而在生產(chǎn)環(huán)境中遇到極端錯誤時,復(fù)雜程度可能是災(zāi)難性的。Redis 集群具備了可伸縮性,卻沒有那么多令人難以理解的組件,即使像我這樣的門外漢也能明白它的原理。它的設(shè)計文檔也很好理解,很接地氣。

在搭建集群之后的幾個月,盡管每時每刻都有相當大的負載,我也沒有再去碰過它。如此高質(zhì)量的集群實屬罕見。我們需要更多像 Redis 這樣的構(gòu)建塊,讓它們做它們該做的事,無需我們多作操心。

責(zé)任編輯:武曉燕 來源: 聊聊架構(gòu)
相關(guān)推薦

2022-02-14 08:33:51

Redis哨兵集群

2017-02-28 09:48:30

2011-08-12 10:58:51

Hadoop

2023-09-27 06:26:07

2019-07-26 09:20:21

ClusterShel命令Linux

2021-01-07 10:18:03

Redis數(shù)據(jù)庫環(huán)境搭建

2023-02-07 10:40:30

gRPC系統(tǒng)Mac

2013-04-24 10:47:48

Hadoop集群

2016-12-07 10:19:45

網(wǎng)易蜂巢

2022-08-02 09:42:48

混沌工程系統(tǒng)群

2018-07-04 06:13:29

物聯(lián)網(wǎng)保險業(yè)IOT

2010-09-16 15:57:00

PPPoA配置

2022-12-15 17:50:14

2016-03-03 14:29:15

2022-10-29 08:55:19

頁面react

2020-08-25 07:48:17

Kubernetes集群系統(tǒng)

2022-11-30 15:28:55

2024-09-11 20:05:56

2013-06-05 10:24:22

點贊
收藏

51CTO技術(shù)棧公眾號