解決多個服務器共享session的幾個方案


轉載地址:http://toutiao.com/a6294758409293086977/  博主還是希望大家去原文地址看,博主下面寫的也都在原文中有解釋,嘿嘿,看人家比看我清晰多了


A、文件方式:這種方式,將文件作爲一個map,當新增一個數據的時候,就在文件中增加類似這樣的一條數據:angOwberup =>data={"user":{"id":1,"nickname":"老王"}};expiry="2016-10-0100:00:00"(當然,具體實現的時候有可能是用的二進制方式,而不是字符串)這種方式的好處,就是能夠存儲大量的用戶session,使得這個session有效期可以比較長(比如:三個月用戶不用登錄)。不過這個方式也有對應的問題,就是文件操作比較麻煩。比如,有一個用戶的session過期了,需要刪掉這條記錄,那這個文件就需要挪動或重寫。
B、cache方式:有好多web端的邏輯服務器都採用這種方式。這種方式好處非常明顯,就是實現起來非常簡單。將所有數據放入到內存cache中。如果有失效,直接內存刪除就可以了。不過帶來的問題也很明顯,當服務器重啓以後,所有session都丟失了。或者當有大量用戶登錄(也有可能是遭受攻擊),就會很快讓cache被充滿,然後大量session被LRU算法淘汰,造成session的大量失效,使得用戶需要反覆登錄等操作。
C、cookie方式:這種方式是最偷懶的方式。就是我服務器任何數據都不存,我把你們所有的客戶端當做我的存儲器,我就需要做一個加密和解密操作。當然這種方式最大的好處就是實現極其簡單(還有其他的好處,稍後再說),不過問題也是很明顯的,就是客戶端要記錄大量信息,同時還要保證加密信息的安全。如果session裏要存放大數據,這種方式就不是很適合了。除了上述說到的優缺點以外,A、B兩種方式還有另外一個問題,就是當我有不止一臺服務器的時候,不同服務器間的session數據共享就成問題了。一招制勝---詳解分佈式系統裏session同步比如,最初我只有一臺服務器1,他的session裏記錄了user-1和user-2的數據。這個時候,我需要增加一臺服務器2。當nginx把用戶的請求轉發到服務器2的時候,他就傻眼了:用戶帶了一個jsession_id=angOwberup這個的cookie過來,而在他的session管理器裏卻找不到這樣一個session數據。那該怎麼辦?!(苦!惱!啊!)因此,就出現了我們文章一開始提到的問題:在分佈式系統裏,用戶session如何才能實現同步?3、session的同步有了上面的情況,我們就必須要去考慮,如何在多個服務器之間實現session同步這個操作。
常見的做法有以下幾種,我們逐個來看看:
             A、進程間通信傳遞session數據。這是最容易想到的一個方法。我們在不同的server服務裏開一個socket,然後用socket來將相互擁有的session數據進行傳遞。我記得多年以前tomcat就是採用這樣的方式來做的(已經很久沒用過tomcat了,不知道現在是否還在這樣使用)。這種方式的好處很明顯,就是原理簡單明瞭;壞處也很明顯,就是同步合併過程複雜,還容易造成同步延遲。比如,某個用戶在server-1登錄了,server-1存儲了這個用戶的session,當正準備將數據同步給server-2的時候,由於用戶訪問實在是太快(飛一般的速度),server-2還沒收到server-1傳來的session數據,用戶訪問就已經來了。這個時候,server-2就不能識別這個用戶,造成用戶需要再次登錄。而且,當有成千上萬臺服務器的時候,session同步就是一個噩夢:每一個服務器都要將自己擁有的session廣播給其他所有機器,而且還要隨時進行,不能停歇…… (最後這些機器估計都是累死的)
            B、cookie存儲方式。我們在上面講到了一個很偷懶的方式,就是把session數據做加密,然後存儲到cookie中。用戶請求到了,就直接從cookie讀取,然後做解密。這種方式真是把分佈式思想發揮到了一個相當的高度。他把用戶也當做分佈式的一員,你要訪問數據,那你就自己攜帶着他,每次到服務器的時候,我們的服務器就只負責解密……對於session裏只存放小數據,並且加密做的比較好(防止碰撞做暴力破解)的系統來講,這是一個比較好的選擇。他實現超級簡單,而且不用考慮數據的同步。不過如果要往session裏存放大數據的情況就不是太好處理。或者安全性要求很高的系統,也不是太好的一個方式(數據有被破解的風險)。
C、cache集羣或者數據庫做session管理。我們也可以採用另外一種架構來解決session同步問題,那就是引入統一session接入點。一招制勝---詳解分佈式系統裏session同步我們session放入到cache集羣或者數據庫中,每次請求的時候,都從他們中來獲取。這樣,所有的機器都能獲取到最新的session數據。這種方案也是很多中大型網站採用的解決方案。他實現起來相對簡單(利用cache集羣或者主從數據庫自身的管理來實現多機的互備),而且效率很高,安全性也不錯。
            D、還有一種方式是從上面這種方式延展出來的,就是提供session服務。這個服務負責管理session,其他服務器每次從這個服務處獲取session數據,從而達到數據的共享。一招制勝---詳解分佈式系統裏session同步大家如果仔細觀察一下baidu或者google,你做登錄的時候,他們可能會讓你跳到passport.baidu.com 或者accounts.google.com這兩個域名之下。這兩個就是他們用來做用戶登錄和類似session管理的一個地方(由於之前只呆過baidu,所以google並不是非常清楚)。當一個訪問請求來的時候,server就從cookie裏取類似session_id的東東,然後用這個東東去passport服務去請求用戶的session數據。
           這種方式的好處就在於:A、可以非常方便的擴展用戶登錄的數量以及存儲數據的大小。當時在x度的時候,N億用戶的session都在這個系統裏進行管理;B、方便做性能優化。如果用cache集羣的方案,如果cache有機器壞掉,那麼就會造成一部分用戶session失效;如果用數據庫方案,如果量太大,有可能會出現性能問題。而這種方案在實現的時候,可以用cache和數據庫結合的實現方式,保證高效和穩定。同時,針對一些接口,可以做性能的優化,提升查詢效率;C、對外封閉,保證數據安全。這種方式還有一個好處,就是可以將加密算法、密鑰等封閉在系統內部,對外只暴露接口,使得數據安全性更有保障。(涉及到用戶信息的,都是隱私!)不過,這種方式也有自己的問題,就是運維相對更復雜,有可能需要專門的團隊去管理這些系統。當然,除了上述的一些方式以外,還有其他的手段(比如,在入口nginx處對用戶cookie做一致Hash,將某一用戶分配到固定機器)。鑑於老王知識有限,且碼字速度有限,就先介紹這些了,不知道你是否看懂了呢?總結一下:關於session同步,其實方案有很多,沒有哪個方案是最好的,只有某一種方案是最適合你現在架構的。


原文鏈接:http://toutiao.com/a6294758409293086977/

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