1. 程式人生 > >解決多個伺服器共享session的幾個方案

解決多個伺服器共享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/