單個節點的緩存容量達到上限 Hash算法一致性

場景

?

單個節點的緩存容量達到上限,無法繼續單點增加內存,如何解決?

單個節點支撐的QPS達到上限,如何解決??

初步方案

?

增加N個緩存節點,為了保證緩存數據的均勻,一般情況會采用對key值hash,然后取模的方式,然后根據結果,確認數據落到哪臺節點上:如下:

hash(key)%N?

很好,這個的確解決了上面的問題,實現了初步的分布式緩存,數據均勻分散到了各個節點上,流量請求也均勻的分散到了各個節點。

但是如果出現以下情況,會帶來什么問題?

1、某臺服務器突然宕機。緩存服務器從N變為N-1臺。

2、緩存容量達到上限或者請求處理達到上限,需要增加緩存服務器,假定增加1臺,則緩存服務器從N變為N+1

上面的情況帶來的問題:

增加或者刪除緩存服務器的時候,意味著大部分的緩存都會失效。這個是比較致命的一點,緩存失效,如果業務為緩存不命中,查詢DB的話,會導致一瞬間DB的壓力陡增。可能會導致整個服務不可用。?

換種描述方式,我們需要解決怎么樣的問題?或者需求是怎樣的?

?????增刪機器時,希望大部分key依舊在原有的緩存服務器上保持不變。舉例來說:key1,key2,key3原先再Cache1機器上,現在增加一臺緩存服務器,希望key1,key2,key3依舊在Cache1機器上,而不是在Cache2機器上。?

?

改進方案(一致性Hash)

?

一致性哈希算法的簡單背景介紹 (此段內容來自網絡)

一致性哈希算法在1997年由麻省理工學院提出的一種分布式哈希(DHT)實現算法,設計目標是為了解決因特網中的熱點(Hot spot)問題,初衷和CARP十分類似。一致性哈希修正了CARP使用的簡單哈希算法帶來的問題,使得分布式哈希(DHT)可以在P2P環境中真正得到應用。?

一致性hash算法提出了在動態變化的Cache環境中,判定哈希算法好壞的四個定義:(來自百度百科

  1. 平衡性(Balance):平衡性是指哈希的結果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。很多哈希算法都能夠滿足這一條件。

  2. 單調性(Monotonicity):單調性是指如果已經有一些內容通過哈希分派到了相應的緩沖中,又有新的緩沖加入到系統中。哈希的結果應能夠保證原有已分配的內容可以被映射到原有的或者新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。?

  3. 分散性(Spread):在分布式環境中,終端有可能看不到所有的緩沖,而是只能看到其中的一部分。當終端希望通過哈希過程將內容映射到緩沖上時,由于不同終端所見的緩沖范圍有可能不同,從而導致哈希的結果不一致,最終的結果是相同的內容被不同的終端映射到不同的緩沖區中。這種情況顯然是應該避免的,因為它導致相同內容被存儲到不同緩沖中去,降低了系統存儲的效率。分散性的定義就是上述情況發生的嚴重程度。好的哈希算法應能夠盡量避免不一致的情況發生,也就是盡量降低分散性。?

  4. 負載(Load):負載問題實際上是從另一個角度看待分散性問題。既然不同的終端可能將相同的內容映射到不同的緩沖區中,那么對于一個特定的緩沖區而言,也可能被不同的用戶映射為不同 的內容。與分散性一樣,這種情況也是應當避免的,因此好的哈希算法應能夠盡量降低緩沖的負荷。

所以通過上面的定義可以看到,簡單的hash(key)%N的方式,違背了?單調性?的這個原則。原因如上面提到的,增刪機器的時候,原有的緩存大部分會失效,也就違背了單調性的原則。

?

介紹:

? ? 大部分文章都提到環形的hash空間,但是沒有講為什么是環形的。后面我會聊下我的想法。?

? ? 使用常見的hash算法可以把一個key值哈希到一個具有2^32個桶的空間中。也可以理解成,將key值哈希到 [0, 2^32) 的一個數字空間中。 我們假設這個是個首尾連接的環形空間。如下圖:

blob.png

? 假設我們現在有key1,key2,key3,key4 4個key值,我們通過一定的hash算法,將其對應到上面的環形hash空間中。

? ?k1=hash(key1);

? ?k2=hash(key2);

? ?k3=hash(key3);

? ?k4=hash(key4);

blob.png

同樣的,假設我們有3臺cache服務器,把緩存服務器通過hash算法,加入到上述的環中。一般情況下是根據機器的IP地址或者唯一的計算機別名進行哈希。

c1=hash(cache1);

c2=hash(cache2);

c3=hash(cache3);

blob.png

接下來就是數據如何存儲到cache服務器上了,key值哈希之后的結果順時針找上述環形hash空間中,距離自己最近的機器節點,然后將數據存儲到上面, 如上圖所示,k1 存儲到 c3 服務器上, k4,k3存儲到c1服務器上, k2存儲在c2服務器上。用圖表示如下:

blob.png

增刪機器的情況

假設cache3服務器宕機,這時候需要從集群中將其摘除。那么,之前存儲再c3上的k1,將會順時針尋找距離它最近的一個節點,也就是c1節點,這樣,k1就會存儲到c1上了,看一看下下面的圖,比較清晰。

blob.png

摘除c3節點之后,只影響到了原先存儲再c3上的k1,而k3、k4、k2都沒有受到影響,也就意味著解決了最開始的解決方案(hash(key)%N)中可能帶來的雪崩問題。

增加節點原理和刪除時差不多~

blob.png

新增C4節點之后,原先存儲到C1的k4,遷移到了C4,分擔了C1上的存儲壓力和流量壓力。

幾個問題:

1、為什么需要想象成環形?

? ? 為了保證節點宕機摘除之后,原先存儲在當前節點的key能找到可存儲的位置。舉個極端的例子,在不是環狀hash空間下,剛好緩存的服務器處于0這個位置,那么0之后是沒有任何節點信息的,那么當緩存服務器摘除的時候,以前存儲在這臺機器上的key便找不到順時針距離它最近的一個節點了。但如果是環形空間,0之后的最近的一個節點信息有可能是2^32-1這個位置,他可以找到0之后的節點。如下圖描述可能清晰一點。

blob.png

?

2、為什么是2^32個桶空間?

? 沒有搞清楚,個人理解是為了保證足夠的靈活性,減少hash帶來的key值沖突。也方便后續增刪節點。?

繼續改進

?

上面的簡單的一致性hash的方案在某些情況下但依舊存在問題:一個節點宕機之后,數據需要落到距離他最近的節點上,會導致下個節點的壓力突然增大,可能導致雪崩,整個服務掛掉。

如下圖所示,

blob.png

當節點C3摘除之后,之前再C3上的k1就要遷移到C1上,這時候帶來了兩部分的壓力:

? ? ?1)、之前請求到C3上的流量轉嫁到了C1上,會導致C1的流量增加,如果之前C3上存在熱點數據,則可能導致C1扛不住壓力掛掉。

? ? ?2)、之前存儲到C3上的key值轉義到了C1,會導致C1的內容占用量增加,可能存在瓶頸。

當上面兩個壓力發生的時候,可能導致C1節點也宕機了。那么壓力便會傳遞到C2上,又出現了類似滾雪球的情況,服務壓力出現了雪崩,導致整個服務不可用。

如果解決上面的問題?

虛擬節點。歪果人的腦子真好使,想出這么一個牛逼的方式,虛擬節點。

如上描述,一個節點宕機之后可能會引起下個節點的存儲及流量壓力變大,這一點違背了最開始提到的四個原則中的 平衡性, 節點宕機之后,流量及內存的分配方式打破了原有的平衡。

虛擬節點,從名字可以看出來,這個節點是個虛擬的,每個實際節點對應多個虛擬節點。比較專業的說法如下:

“虛擬節點”( virtual node )是實際節點(機器)在 hash 空間的復制品( replica ),一實際個節點(機器)對應了若干個“虛擬節點”,這個對應個數也成為“復制個數”,“虛擬節點”在 hash 空間中以hash值排列。

依舊用圖片來解釋,假設存在以下的真實節點和虛擬節點的對應關系。

Visual100—> Real1

Visual101—> Real1

Visual200—> Real2

Visual201—> Real2

Visual300—> Real3

Visual301—> Real3

同樣的,hash之后的結果如下:

hash(Visual100)—> V100 ?—> Real1

hash(Visual101)—> V101? —> Real1

hash(Visual200)—> V200 ?—> Real2

hash(Visual201)—> V201? —> Real2

hash(Visual300)—> V300 ?—> Real3

hash(Visual301)—> V301 ?—> Real3

key值的hash結果如上,這里暫時不寫了。

如圖解釋:

blob.png

和之前介紹的不添加虛擬節點的類似,主要聊下如果宕機之后的情況。?

假設Real1機器宕機,則會發生一下情況。

1、原先存儲在虛擬節點V100上的k1數據將遷移到V301上,也就意味著遷移到了Real3機器上。?

2、原先存儲再虛擬節點V101上的k4數據將遷移到V200上,也就意味著遷移到了Real2機器上。

結果如下圖:

12160867-2438-46F8-B74E-0B8E21F32187.png

這個就解決之前的問題了,某個節點宕機之后,存儲及流量壓力并沒有全部轉移到某臺機器上,而是分散到了多臺節點上。解決了節點宕機可能存在的雪崩問題。

當物理節點多的時候,虛擬節點多,這個的雪崩可能就越小。

PS:只有2個節點的時候,加入虛擬節點沒有用。你懂的。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387035.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387035.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387035.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java學習筆記11 (構造方法 this深探)

在開發中,經常需要在創建對象的同事明確對象對的屬性值,比如一個person對象創建的時候就應該有name和age 等屬性,那么如何做到在創建對象的同時給對象的屬性值初始化值呢? 這里介紹構造方法 1 構造方法沒有返回值類型,…

密碼中不能包含全角字符的正則表達式

String regex "^((?![^\\x00-\\xff]).)*$"; String str "aA"; System.out.println(str.matches(regex));

編程算法 - 將排序數組按絕對值大小排序 代碼(java)

一個含有多個元素的數組&#xff0c;有多種排序方式。它可以升序排列&#xff0c;可以降序排列&#xff0c;也可以像我們以前章節說過的&#xff0c;以波浪形方式排序&#xff0c;現在我們要看到的一種是絕對值排序。對于數組A,絕對值排序滿足以下條件&#xff1a;|A[i]| < …

QT Linux打包發布

Linux&#xff1a; 1、用Release編譯&#xff1b; 2、把可執行文件(如paike)放入新建目錄中; 3、當前目錄下編寫腳本copyDependency.sh&#xff0c;把動態鏈接庫導入當前目錄&#xff1b; #!/bin/shexe"paike" #發布的程序名稱destination"/home/paike"…

CRM公海自動回收規則

企微云CRM操作指南 – 道一云|企微https://wbg.do1.com.cn/xueyuan/2568.html 銷售云 - 美洽 - 連接客戶&#xff0c;親密無間https://meiqia.com/sales-cloud 轉載于:https://www.cnblogs.com/rgqancy/p/10695466.html

三分鐘看懂一致性哈希算法

一致性哈希算法&#xff0c;作為分布式計算的數據分配參考&#xff0c;比傳統的取模&#xff0c;劃段都好很多。 在電信計費中&#xff0c;可以作為多臺消息接口機和在線計費主機的分配算法&#xff0c;根據session_id來分配&#xff0c;這樣當計費主機動態伸縮的時候&#xf…

數據結構09圖

第七章 圖 Graph 7.1 圖的定義和術語 頂點 Vertex V 是頂點的有窮非空集合&#xff0c;頂點數 |V| n VR 兩個頂點之間關系的集合&#xff0c;邊數 |VR| e 有向圖 Digraph <v, w> Arc v Tail / Inital node w Head / Terminal node 無向圖 Undigraph <v, w> 必…

JVM調優-GC參數

一、Throughput收集器(吞吐量) -XX:UseParallelGC -XX:UseParallelOldGC *參數調整&#xff1a;通過調整堆大小&#xff0c;減少GC停頓時間&#xff0c;增大吞吐量 增強堆大小可以減少Full GC頻率&#xff0c;但卻會增加停頓時間 1.手動調整 -Xmn -Xms -XX:NewRatioN 手動指…

aspnetcore源碼學習(一)

---恢復內容開始--- 筆者從事netcore相關項目開發已經大半年了&#xff0c;從netcore 1.0到現在3.0大概經過了3年左右的時間&#xff0c;記得netcore剛出來的時候國內相關的學習資料缺乏&#xff0c;限制于外語不大熟練的限制國外的相關書籍看起來相當吃力&#xff0c;于是在當…

評估一個垃圾收集(GC)

在實踐中我們發現對于大多數的應用領域&#xff0c;評估一個垃圾收集(GC)算法如何根據如下兩個標準&#xff1a; 吞吐量越高算法越好暫停時間越短算法越好 首先讓我們來明確垃圾收集(GC)中的兩個術語:吞吐量(throughput)和暫停時間(pause times)。 JVM在專門的線程(GC threads…

python數據分析常用包之Scipy

Scipy轉載于:https://www.cnblogs.com/jacky912/p/10697853.html

docker容器狀態跟蹤及疑惑

一、 1 def status_test():2 container client.containers.create("comp")3 print ("create: ", container.status)4 container.start()5 print ("start: ", container.status)6 container.pause()7 print ("paus…

CAP和BASE理論

幾個名詞解釋&#xff1a; 網絡分區&#xff1a;俗稱“腦裂”。當網絡發生異常情況&#xff0c;導致分布式系統中部分節點之間的網絡延時不斷變大&#xff0c;最終導致組成分布式系統的所有節點中&#xff0c;只有部分節點之間能夠進行正常通信&#xff0c;而另一些節點則不能…

Mysql案例5:取得平均薪資最高的部門的部門名稱

一、要求&#xff1a;查詢平均薪水最高部門的部門編號 二、背景&#xff1a;當前數據庫有employee表和department表&#xff0c;數據分別如下&#xff1a; employee表&#xff1a; department表&#xff1a; 三、難點&#xff1a; 1、需要考慮最高平均薪資可能在多個部門同時出…

Spring 處理過程分析

一、處理過程分析 1、首先&#xff0c;Tomcat每次啟動時都會加載并解析/WEB-INF/web.xml文件&#xff0c;所以可以先從web.xml找突破口&#xff0c;主要代碼如下&#xff1a;<servlet ><servlet-name >spring-mvc</servlet-name><!-- servlet類 --><…

python全棧開發中級班全程筆記(第二模塊、第四章)(常用模塊導入)

python全棧開發筆記第二模塊 第四章 &#xff1a;常用模塊&#xff08;第二部分&#xff09; 一、os 模塊的 詳解 1、os.getcwd() &#xff1a;得到當前工作目錄&#xff0c;即當前python解釋器所在目錄路徑 import os j os.getcwd() # 返回當前pyt…

基于 Spring Cloud 完整的微服務架構實戰

本項目是一個基于 Spring Boot、Spring Cloud、Spring Oauth2 和 Spring Cloud Netflix 等框架構建的微服務項目。 作者&#xff1a;Sheldon地址&#xff1a;https://github.com/zhangxd1989 技術棧 Spring boot - 微服務的入門級微框架&#xff0c;用來簡化 Spring 應用的初…

mysql Invalid use of group function的解決辦法

錯誤語句&#xff1a;SELECT s.SID, s.Sname, AVG(a.score)FROM student sLEFT JOIN sc a ON s.SID a.SID WHERE AVG(a.score) > 60GROUP BY s.SID正確語句&#xff1a; SELECTs.SID,s.Sname,AVG(a.score)FROMstudent sLEFT JOIN sc a ON s.SID a.SID GROUP BYs.SID HAVIN…

ipython notebook 中 wavefile, display, Audio的使用

基于ipython notebook的 wavefile以及display, Audio的使用首先是使用的庫使用 wavfile 讀取.wav文件使用display,Audio播放聲音最近在做聲音信號處理的時候&#xff0c;使用了ipython notebook。發現相較于matlab&#xff0c;python在有關生成wave文件和播放音頻需要利用到sci…

spring 設計模式

設計模式作為工作學習中的枕邊書&#xff0c;卻時常處于勤說不用的尷尬境地&#xff0c;也不是我們時常忘記&#xff0c;只是一直沒有記憶。 今天&#xff0c;螃蟹在IT學習者網站就設計模式的內在價值做一番探討&#xff0c;并以spring為例進行講解&#xff0c;只有領略了其設計…