戳藍字「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博客】,加入【雲計算學習交流群】,和志同道合的朋友們共同打卡學習!