docker高級篇2-分佈式存儲之三種算法

面試題:

1~2億條數據需要緩存,請問如何設計這個緩存案例?

答:單機單臺100%是不可能的。肯定是分佈式緩存的。那麼用Redis如何落地?

一般有三種方案:

哈希取餘分區;一致性哈希算法分區;哈希槽分區。如下圖:

a791fd553bf3b7666ed7e4207c786d7f.png

大家好,我是凱哥Java(kaigejava),樂於分享,每日更新技術文章,歡迎大家關注“凱哥Java”,及時瞭解更多。讓我們一起學Java。也歡迎大家有事沒事就來和凱哥聊聊~~~

哈希取餘分區:

對redis的key進行hash後和機器總數取餘。公式:has(key)%N

這種分區算法的優點:

簡單粗暴,直接有效。只需要預估好數據規劃好節點。就能保證一段時間的數據支撐。使用HASH算法讓固定的一部分請求落到同一臺服務器上,這樣每臺服務器固定處理一部分請求,起到負載均衡+分而治之的作用。

缺點:

原來規劃後的節點,進行擴容或者縮容就比較麻煩了。不管是擴容還是縮容,每次數據變更導致幾點有變動,映射關係需要重新進行計算。在服務器個數固定不變的時候沒問題。如果需要彈性擴容或者故障停機的情況下,原來的取模公式就會發生變化。此時地址經過某個redis機器宕機了。由於機器總數量發生了變化,會導致hash取餘全部數據重新洗牌啊!!

一致性哈希算法分區:

一致性hash算法是什麼?

一致性hash算法在1997年麻省理工學院提出的,設計目標是爲了解決:

分佈式緩存數據變動和映射問題。某個機器宕機了,分母數量改變了,自然取餘就出問題了。

一致性hash算法能幹嘛?

提出一致性hash解決方案。目的是當服務器個數發生變動的時候,儘量減少影響客戶端到服務器的映射關係。

都有哪些步驟?

3大步驟。

1:算法構建一致性哈希環;

一致性哈希算法必然有個hash函數並安裝算法產生hash值,這個算法的所有可能哈希值會構成一個全量集,這個集合可以成爲hash空間,範圍是[0,2^32-1],這是一個線性空間,但是在算法中,通過適當的邏輯控制將其首尾相連(0=2^32),這樣在邏輯上,就形成了一個環形的空間。

一致性哈希環也是使用的取模的方方,是對2^32取模。一致性hash算法將這個哈希值空間組織成一個虛擬的圓環,整個哈希環是按照順時針方法組織的。如下圖:

393f5eec28962da1332cfbc95733ffe7.png

2:服務器IP節點映射

將集羣中的各個IP節點映射到環上的某一個位置。將各個服務器使用hash進行一個hash.(具體可以選擇服務器的IP或者主機名稱作爲關鍵字進行哈希,這樣每臺機器就能確定其在哈希環上的位置)。例如4個節點NodeA、B、C、D,經過IP地址的哈希環上計算(hash(ip)),使用IP地址哈希後環空間位置如下圖:

a938aca2882396590626fff082ba02e0.png

 

3:key落到服務器的落鍵規則

hash環構建了、服務器IP節點也映射了,那麼當我們需要存儲一個KV鍵值對的時候,先要計算的是key對應的hash值(hash(key)),將這個key使用相同的函數hash計算出哈希值並確定此數據在環上的位置,從此位置沿着環順時針"行走",第一遇到的服務器就是其應該定位到的服務器。並將該鍵值對存儲在這個節點上。

例如:我們有ObjA、ObjB、ObjC、ObjD四個數據對象,在經過hash計算之後,在環上分佈的空間位置如下圖。

根據一致性hash算法,ObjA的數據將會被定位到NodeA上。其他的類推,B將會在NodeB上,C將會在NodeC上,D將會在NodeD上.

4a5bc04625fd58d8ec7385f9a34981f2.png

一致性hash算法的優點是什麼?

1:一致性哈希算法的容錯性

假設上圖中的NodeC所在的服務器宕機了,可以看到次數對象ABD不會受到影響,只有C隊形會被重定位到NodeD的機器上。一般地,在一致性Hash算法中,如果一臺服務器不可用了,則受到影響的數據僅僅是對應服務器到其環空間中前一臺服務器(也就是沿着逆時針方向行走遇到的第一臺服務器)之間的數據而已,其他的數據不會受到影響,簡單的來說,就是C服務器掛了,受影響的只是B、C之間的數據,並且這些數據會遷移到D上進行存儲。

43f6d5ccd8e103b8ec59c4e79870422a.png

 

2:一致性哈希算法的擴展性

所謂的擴展性,就是數據量增加了,則需要增加一臺節點NodeX,X的位置在A和B之間,那受到影響的也就是A到X之間的數據,重新把A到X的數據錄入到X上即可,不會導致hash重新取餘,全部數據重新洗牌.如下圖:

a8a4317d684b46528eb12ca9b30b32ef.png

 

一致性hash算法的缺點是什麼?

一致性哈希算法的數據傾斜問題

在服務器節點太少的情況下,容易因爲節點數據分佈不均勻而造成數據傾斜(被緩存的對象大部分集中緩存在某一臺服務器上)的問題。假設系統中只有兩臺服務器。那麼出現數據傾斜就如下圖:

3acd61d9f32f1766e82bbea2e3d9e691.png

總結一致性hash算法:

目的:爲了在節點數目發生改變時儘可能少遷移數據。將所有的存儲節點排列在相接的hash環上,每個key在計算hash之後,會按照順時針找到的存儲節點存放。而當有節點加入或者退出時候,僅影響該節點在hash環上的順時針相鄰的後續節點。

優點:加入和刪除節點只會影響哈希環中順時針方向相鄰的節點,對其他節點無影響。

缺點:數據的分佈和節點的位置有關,因爲這些節點不是均勻地分佈在哈希環上的,所以數據進行存儲時候達不到均勻分佈效果。可能就出現了數據傾斜問題。

針對上面問題,於是,又有了新的方案。就是接下來要講的,哈希槽分區。

哈希槽分區

哈希槽是什麼?

爲什麼會出現哈希槽算法?

因爲一致性哈希算法的數據傾斜問題,爲了解決這個問題。

哈希槽實質上就是一個數組,數組[0,2^14-1]形成hash slot空間。

能幹什麼?

解決均勻分配的問題,在數據和節點之間又加入了一層,把這一層稱爲哈希槽(slot),用於管理數據和節點之間的關係。現在就相當於節點上放的是槽,槽裏面上的是數據。

621e4296584006fd105db502d512b905.png

槽解決的是粒度問題,相當於是把粒度變大了。這樣便於數據移動。

哈希解決的是映射問題,使用key的哈希值來計算所對應槽,便於數據分配。

多少個hash槽:

一個集羣中只能有16384個槽。編號爲0--16383(0-2^14-1),這些槽會分配給集羣中所有的主節點,分配策略沒有要求。可以指定哪個編號的槽分配給哪個主節點。集羣會記錄節點和槽對應的關係。解決了節點和槽的關係後,接下來就需要對key進行hash值計算,然後對16384取餘。餘數是幾,那麼key就落入到對應的槽中。slot=CRC16(key)%16384.以槽爲單位移動數據,因爲槽的數目是固定的,處理起來比較容器,這樣數據遷移問題就解決了.

哈希槽計算

Redis集羣中內置了16384個哈希槽,Redis會根據節點數量大致均等地將hash槽映射到不同的節點。當需要在集羣中放置一個k-v時,Redis先對key使用crc16算法算出一個結果,然後把結果對16834求餘數。這樣每個key都會對應一個編號,也就會映射到某個節點上。如下圖:

24c4e7b31fb116780e1f8401148ee46a.png

 

結束語

如操作有問題歡迎去 我的 個人博客(www.kaigejava.com)留言或者   微信公衆號(凱哥Java)留言交流哦。

 

 

直通車,本系列教程已發佈文章,快速到達,《Docker學習系列》教程已經發布的內容如下:

【圖文教程】Windows11下安裝Docker Desktop

【填坑】在windows系統下安裝Docker Desktop後遷移鏡像位置

【Docker學習系列】Docker學習1-docker安裝

【Docker學習系列】Docker學習2-docker設置鏡像加速器

【Docker學習系列】Docker學習3-docker的run命令幹了什麼?docker爲什麼比虛擬機快?

【Docker學習系列】Docker學習2-常用命令之啓動命令和鏡像命令

【Docker學習系列】Docker學習系列3:常用命令之容器命令

【Docker學習系列】Docker學習4-常用命令之重要的容器命令

【Docker教程系列】Docker學習5-Docker鏡像理解

【Docker教程系列】Docker學習6-Docker鏡像commit操作案例

【Docker學習教程系列】7-如何將本地的Docker鏡像發佈到阿里雲

【Docker學習教程系列】8-如何將本地的Docker鏡像發佈到私服?

「Docker學習系列教程」9-Docker容器數據卷介紹

「Docker學習系列教程」10-Docker容器數據卷案例

Docker學習11-Docker常規方式安裝軟件

「Docker學習系列教程」基礎篇小總結及高級篇預告

docker高級篇1-dockeran安裝mysql主從複製

 

【Docker學習教程系列彙總】筆記及遇到問題解決文章


 

 


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章