隨着互聯網的發展,用戶產生的數據愈來愈多,企業面臨着龐大數據的存儲問題,目前市面上主流的分佈式大數據文件系統,都是對數據切片打散,經過離散方法將數據散列在集羣的全部節點上,本文將帶你瞭解DHT(Distributed Hash Table):分佈式哈希表是如何實現數據的分佈式離散存儲的。算法
DHT(Distributed Hash Table):分佈式哈希表
互聯網發展早期,數據一般存儲在單個服務器上,初期數據增加較爲緩慢,能夠經過提高單機的存儲能力知足數據的增加需求;隨着互聯網普及程度的推動,用戶數、用戶產生和訪問的數據呈指數增加;單機已沒法存儲用戶須要的數據。爲此,迫切須要多個服務器共同協做,存儲量級更大的數據。服務器
傳統 Hash 經過算法 hash()=X mod S 來對數據進行分散,在元數據比較分散的狀況下,數據可以很好的散列在集羣節點中。因爲S表明了集羣的節點數,當進行集羣的擴容縮容時,S的變化會影響到歷史數據的命中問題,所以爲了提升數據命中率,會產生大量測數據遷移,性能較差。負載均衡
分佈式 Hash 經過構造一個長度爲2的32次方(ipv4地址的數量)的環,將節點散列在 Hash環上,根據不一樣的 Hash算法計算出來的 Hash值有所不一樣,本文采用FNV Hash算法來計算 Hash值。分佈式
如圖所示,先將存儲節點經過 Hash計算後添加到 DHT 環上,每一個節點距離上一個節點間的這段區間,做爲該節點的數據分區,Hash值落在這個分區的數據將存儲到這個節點上;性能
而後將數據經過 Hash算法散列到DHT環上,數據落到DHT環上後,按照順時針方向找到離本身最近的節點做爲數據存儲節點,以下所示,數據 ObjectA 落到節點 NodeA上,數據 ObjectB 落到節點 NodeB 上;大數據
初始化DHT的源碼以下:spa
首先定義了一個存放集羣節點元數據的Map,用來存儲接入到DHT環中的物理節點數據。而後定義了一個DHT環——vNodes,用來存儲DHT環中的節點位置信息。這樣咱們就實現了一個簡單的DHT環,經過addPhysicalNode方法能夠模擬集羣節點的加入。加入時會計算節點的Hash值並存放到vNodes中。3d
初始化4個存儲節點。blog
經過countNodeValue方法插入100條數據,在寫數據的過程當中,根據數據的 Hash值找到DHT環上最近的一個節點,而後將數據寫入該節點中。ip
插入100條數據後,各個節點的數據分佈以下,能夠看見4個節點的數據並不均勻,只有一個節點分配到了數據(這與寫入的數據也有必定關係)。
插入100萬條數據後,各個節點的數據分佈以下,雖然每一個節點都分配到了數據,但仍然出現了較大的數據傾斜。這將致使99%的請求都會由Node3進行處理,出現一核有難三核圍觀的狀況。
出現如上問題是什麼緣由呢?經過查看DHT環上各節點的hash值不難看出,各節點間距不均勻,插入的數據按順時針查找節點時都找到了Node3,所以數據都寫到了Node3裏面,因此節點區間不均勻會使某些節點能覆蓋更多的數據,致使數據不均衡。
說了一個簡單DHT環的基本原理後,再來思考一個問題:簡單的DHT環數據離散,但仍然存在數據傾斜的狀況,還不如用傳統的hash方式分配數據。
前面提到傳統的hash方式在當時在節點故障後,整個集羣的數據會進行大量的遷移,影響集羣性能,那麼DHT能解決這一問題嗎?
咱們仍是用以前分配好的100萬條數據,模擬節點4故障,以下圖所示,Node4上的數據只遷移到了Node1,對Node2和Node3不產生數據遷移,從而下降了節點故障致使每一個節點都須要進行數據遷移帶來的影響。
一、虛擬節點
你們思考一下,解決數據傾斜的問題能夠如何解決?
經過增長集羣節點的方式最簡單直接,目的是將更多的節點散列到DHT環上,使得環上全部節點分佈更加均勻,節點間的區間間隔儘量的均衡,如下是10個節點和20個節點集羣的數據分佈狀況。
能夠發現,經過增長節點的方式,仍然沒法從根本上解決數據傾斜的問題。而且增長節點會提升集羣的設備成本和維護成本。同時,這種方案還引出了一個嚴重的問題,若是Node20故障了,那麼Node20的數據會全數遷移到下一個節點上,最終致使集羣出現數據傾斜,數據較多的節點還將處理更多的IO請求,容易造成數據熱點,成爲性能瓶頸,引起集羣總體的性能降低。
(2) 引入虛擬節點
爲了解決數據傾斜的問題,引入了虛擬節點的概念。虛擬節點也就是真實節點的一個邏輯副本,如圖所示,對節點NodeA進行3次虛擬節點hash分佈,造成了虛擬節點NodeA一、NodeA二、NodeA3。當NodeA故障後,指向NodeA的數據會指向NodeB、NodeC。
當引入虛擬節點數量爲100時,數據已經分散在各個節點上了,若是虛擬節點足夠多,最終將達到數據均衡的狀態。
虛擬節點數據1萬時的數據分佈:
虛擬節點數量爲100萬時的數據分佈:
當Node3故障後,Node3上的數據被均勻的分散到其餘節點上,不會出現數據傾斜的狀況。
二、負載邊界因子
這樣就完美了嗎?咱們初始化一個4個節點的DHT環,虛擬節點設置爲100,而後插入100條數據,並打印DHT環的元數據信息以下:
能夠發現,雖然設置的虛擬節點,可是仍然沒法均衡的將節點散列到DHT環上,致使Node2過載,Node空閒。咱們再思考一種極端場景,當咱們的數據剛好計算hash值後都在區間A,而這個區間只有NodeA,那麼仍然出現了數據傾斜。如何解決這個問題呢,這裏咱們引入一個叫負載邊界因子的概念。DHT環部署了4個節點,總共有100條數據要插入,那麼平均下來每一個節點的權重就是100/4+1=26,當數據映射過程當中達到了該節點的權重,則映射到下一個節點,下面是代碼實現。
打開負載邊界因子開關的狀況:
在打開負載邊界因子開關後,數據獲得了較好的均衡。
上述的只是一個簡單的DHT,數據也作了簡化,數據的存儲和讀取都須要查詢DHT環,如何提高DHT的讀寫性能?如何提高DHT的高可靠?當節點故障後,如何將故障節點的數據遷移到新的節點?如何作好數據備份?如何保證副本數據不集中在一個節點上?也是須要去思考的,本文只是拋磚引玉簡單的介紹了DHT基本的思想,更多生產環境面臨的挑戰,在此不作展開。
能夠看到,DHT提供了一種負載均衡的思路。利用hash算法的特性,將數據或業務請求分散到集羣中的各個節點上,提升系統容錯性。
vivo 用戶運營開發團隊