一次失敗的面試,複習一次一致性哈希算法

2019-09-28     科技百分百

戳藍字「CSDN雲計算關注我們哦!

本文故事絕對真實,如有雷同,絕對不是巧合!

話說前幾天有一次,某大廠的二面。然後呢,煙哥那天剛好有事,所以去不了。於是就約了一場視頻面試了!

於是呢,煙哥提前十分鐘在公司裡頭找了一個廁所的坑位,然後進去隨手一鎖門….(以下省略10000字)…

唉…

我竟然…

我竟然…

我竟然又帶薪上廁所了,而且上了一小時!我有罪!

額,是這樣的,大廠的廁所是有雅間的。所以環境還馬馬虎虎,鼻子還是正常的!

OK,交待完背景,然後開始我們的主題!

全局Session

當時的情形是這樣的,先介紹一下自己的項目。然後介紹完項目背景以後,因為有一個登陸模塊。於是乎有了如下問題

面試官:「先說說全局Session幹嘛用的,你們那邊全局session是怎麼做的?」

這個問題還是很容易的。因為一個應用通常有多台伺服器,在登陸成功後,Session只會在其中某一台存儲。需要想辦法讓多台伺服器都識別到這個Session,因此才有了這個全局Session的概念。我們用的是後端統一存儲的策略,有專門的用戶管理系統,上面存儲著用戶信息以及Session狀態。

煙哥注:目前業內在解決全局Sesssion上無外乎四種方法

  • (1)服務端自己進行同步,例如早期的項目,大概是07年那會的(我司老古董項目啊),那會Tomcat的集群能力不行。用的是Weblogic伺服器,使用的就是Weblogic的Session複製功能。

  • (2)客戶端存儲法,將session存儲到瀏覽器cookie中,每次http請求都帶session。這裡摸著良心坦白說,該方案從沒用過,安全性太差。

  • (3)反向代理hash一致性,不需要修改應用代碼。修改nginx的配置,保證同一個ip的請求落在同一個web-server上即可。

  • (4)後端統一存儲,後端統一找一個中間件將Session存起來即可,這個中間件是資料庫或者緩存。

面試官:「那你知道這個平台里Session怎麼管理的麼?」

必須不知道啊!對我們來說該平台只是一個黑盒,會調接口即可。

於是乎,一個讓我頭疼的問題出現了!

面試官:「如果讓你設計這樣一個平台,管理這些Session,你會怎麼設計?」

用redis來存儲Session,用sessionId作為key,用session當value進行存儲。

OK,這時我頭腦浮現的架構是這樣的

面試官:"如果redis掛了呢?"

咦,這個時候,我突然懵了。面試官到底想問我什麼?難道掛了,不是redis從伺服器頂上麼?這個問題莫非有什麼玄機?

然後我是這樣答的。

一般情況,主redis掛了,由從redis頂上。如果redis某個slot的主從節點全掛了,

那麼我們在rediscluster中有一個配置叫

cluster-require-full-coverage

當cluster-require-full-coverage為no時,表示當負責一個插槽的主庫下線且沒有相應的從庫進行故障恢復時,集群仍然可用。但是該槽的相關命令不可用。

當cluster-require-full-coverage為yes時,表示當負責一個插槽的主庫下線且沒有相應的從庫進行故障恢復時,集群不可用。

該值默認值為yes,也就是集群處於不可用的狀態。

這個時候,可能出現了網絡中斷!

面試官:"你的意思是,redis掛了,整個集群數據就不可用了?"

我回答嗯嗯,是的!

這個時候,面試官

面試官:"你不知道一致性哈希算法麼?回去了解一下!"

然後我突然懵了。原來是我想太多,他這樣問完,我才get到他問的點。

煙哥注:所以我才說這個面試我有點失敗,和面試官不在一個頻道上。如果是現場面,可以現場畫圖,則不會出現這種問題!

面試官想到的架構應該是這樣的

上圖中,由於有4台伺服器(排除從庫),因此公式為hash(sessionId) % 4 = 2 ,可知定位到了第2號伺服器。

但是呢,普通的如果4台緩存伺服器已經不能滿足我們的緩存需求,那麼我們應該怎麼做呢?很簡單,多增加幾台緩存伺服器不就行了!

假設:我們增加了一台緩存伺服器,那麼緩存伺服器的數量就由4台變成了5台。那麼原本hash(sessionId) % 4 = 2 的公式就變成了hash(sessionId) % 5 = ?, 可想而知這個結果肯定不是2的,這種情況帶來的結果就是當伺服器數量變動時,所有緩存的位置都要發生改變!

於是乎,他才想引我去答一致性哈希算法!總之,該死的破網絡!導致兩邊不在一個頻道上!

一致性哈希

既然都提到了一致性哈希算法了,就當複習一下吧~~

一致性哈希算法的精髓只有一個:對2^32次方取模。

我們將二的三十二次方想像成一個圓,這個圓上的數字就是即0~(2^32)-1。

如下圖所示

這時候有三台緩存伺服器A、B、C。

我們

hash(伺服器A的IP位址) % 2^32

插播一下,寫到這裡,這裡我又想起一道題了!

有哪些常見的hash算法啊?

OK,先繼續我們的話題。經過上面的運算,我們算出的結果一定是一個0到2^32-1之間的一個整數,我們就用算出的這個整數,代表伺服器A,既然這個整數肯定處於0到2^32-1之間,那麼,上圖中的hash環上必定有一個點與這個整數對應,我們使用這個整數代表伺服器A,那麼,伺服器A就可以映射到這個環上。

同理進行

hash(伺服器B的IP位址) % 2^32

hash(伺服器C的IP位址) % 2^32

於是,得到了下面這一張圖

那麼,我們要用伺服器存儲session,那麼我們用sessionId做key,進行如下運算

hash(sessionId) % 2^32

得到的一個環上的值。那我們怎麼知道session被存到哪個伺服器上呢,OK,順時針方向找到的第一個伺服器就是。如下圖所示

假設,我們現在有四個session,分別進行映射運算後得到如下的環

這麼做的好處?

使用一致性算法後,當伺服器B移除的時候,伺服器B上的數據會順時針移動到伺服器C上去。從而避免了當伺服器數量發生改變當時候,所有的session都失效。

如下所示

虛擬槽的應用?

真實世界中,伺服器可能映射的並不均勻。這就導致了數據可能是下面這樣的,大量的數據在A伺服器上,導致數據不均勻

為了解決這個問題,我們給A、B、C三台伺服器引入虛擬節點。如下圖所示(圖中黃色節點為虛擬節點)

如圖所示,2號session和3號session映射到了虛擬B節點,就會存儲到真實的B節點上。通過引入虛擬節點的方式,實現數據的均勻分配!

最後,本文內容全當複習一次一致性哈希算法。希望大家有所收穫。

福利

掃描添加小編微信,備註「姓名+公司職位」,入駐【CSDN博客】,加入【雲計算學習交流群】,和志同道合的朋友們共同打卡學習!

文章來源: https://twgreatdaily.com/zh-tw/2wiYf20BMH2_cNUg9emx.html