分佈式系統session一致性的問題

session的概念

什麼是session?

服務器爲每一個用戶建立一個會話,存儲用戶的相關信息,以便屢次請求可以定位到同一個上下文。這樣,當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。當用戶請求來自應用程序的 Web 頁時,若是該用戶尚未會話,則 Web 服務器將自動建立一個 Session 對象。當會話過時或被放棄後,服務器將終止該會話。nginx

Web開發中,web-server能夠自動爲同一個瀏覽器的訪問用戶自動建立session,提供數據存儲功能。最多見的,會把用戶的登陸信息、用戶信息存儲在session中,以保持登陸狀態。web

什麼是session一致性問題?

只要用戶不重啓瀏覽器,每次http短鏈接請求,理論上服務端都能定位到session,保持會話。數據庫

分佈式session

單服務器web應用中,session信息只需存在該服務器中,這是咱們前幾年最常接觸的方式,可是近幾年隨着分佈式系統的流行,單系統已經不能知足日益增加的百萬級用戶的需求,集羣方式部署服務器已在不少公司運用起來,當高併發量的請求到達服務端的時候經過負載均衡的方式分發到集羣中的某個服務器,這樣就有可能致使同一個用戶的屢次請求被分發到集羣的不一樣服務器上,就會出現取不到session數據的狀況,因而session的共享就成了一個問題。後端

如上圖,假設用戶包含登陸信息的session都記錄在第一臺web-server上,反向代理若是將請求路由到另外一臺web-server上,可能就找不到相關信息,而致使用戶須要從新登陸。瀏覽器

Session一致性解決方案

1.session複製(同步)

 

思路:多個web-server之間相互同步session,這樣每一個web-server之間都包含所有的session緩存

優勢:web-server支持的功能,應用程序不須要修改代碼安全

不足服務器

  • session的同步須要數據傳輸,佔內網帶寬,有時延cookie

  • 全部web-server都包含全部session數據,數據量受內存限制,沒法水平擴展網絡

  • 有更多web-server時要歇菜

 

2.客戶端存儲法 

思路:服務端存儲全部用戶的session,內存佔用較大,能夠將session存儲到瀏覽器cookie中,每一個端只要存儲一個用戶的數據了

優勢:服務端不須要存儲

缺點

  • 每次http請求都攜帶session,佔外網帶寬

  • 數據存儲在端上,並在網絡傳輸,存在泄漏、篡改、竊取等安全隱患

  • session存儲的數據大小受cookie限制

「端存儲」的方案雖然不經常使用,但確實是一種思路。

 

3.反向代理hash一致性

 思路:web-server爲了保證高可用,有多臺冗餘,反向代理層能不能作一些事情,讓同一個用戶的請求保證落在一臺web-server上呢?

 

 

方案一:四層代理hash

反向代理層使用用戶ip來作hash,以保證同一個ip的請求落在同一個web-server上

 

方案二:七層代理hash

反向代理使用http協議中的某些業務屬性來作hash,例如sid,city_id,user_id等,可以更加靈活的實施hash策略,以保證同一個瀏覽器用戶的請求落在同一個web-server上

優勢

  • 只須要改nginx配置,不須要修改應用代碼

  • 負載均衡,只要hash屬性是均勻的,多臺web-server的負載是均衡的

  • 能夠支持web-server水平擴展(session同步法是不行的,受內存限制)

不足

  • 若是web-server重啓,一部分session會丟失,產生業務影響,例如部分用戶從新登陸

  • 若是web-server水平擴展,rehash後session從新分佈,也會有一部分用戶路由不到正確的session

session通常是有有效期的,全部不足中的兩點,能夠認爲等同於部分session失效,通常問題不大。

對於四層hash仍是七層hash,我的推薦前者:讓專業的軟件作專業的事情,反向代理就負責轉發,儘可能不要引入應用層業務屬性,除非不得不這麼作(例如,有時候多機房多活須要按照業務屬性路由到不一樣機房的web-server)。

 

4.後端統一集中存儲

 

思路:將session存儲在web-server後端的存儲層,數據庫或者緩存

優勢

  • 沒有安全隱患

  • 能夠水平擴展,數據庫/緩存水平切分便可

  • web-server重啓或者擴容都不會有session丟失

不足:增長了一次網絡調用,而且須要修改應用代碼

對於db存儲仍是cache,我的推薦後者:session讀取的頻率會很高,數據庫壓力會比較大。若是有session高可用需求,cache能夠作高可用,但大部分狀況下session能夠丟失,通常也不須要考慮高可用。

 

總結

保證session一致性的架構設計常見方法:

  • session同步法:多臺web-server相互同步數據

  • 客戶端存儲法:一個用戶只存儲本身的數據

  • 反向代理hash一致性:四層hash和七層hash均可以作,保證一個用戶的請求落在一臺web-server上

  • 後端統一存儲:web-server重啓和擴容,session也不會丟失

 

對於方案3和方案4,我的建議推薦後者:

  • web層、service層無狀態是大規模分佈式系統設計原則之一,session屬於狀態,不宜放在web層

  • 讓專業的軟件作專業的事情,web-server存session?仍是讓cache去作這樣的事情吧。

 

來源:架構師之路

相關文章
相關標籤/搜索