session共享redis存儲設計與實現

Session的實現原理簡介

背景:

1.  由於Http協議是無狀態的,服務端如何識別客戶端請求呢,只能依靠http報文中新增部分頭字段來實現請求識別(如何在請求body或這參數中設置會員參數,服務器端會話就與自定義的會員識別綁定到一起

2.  基於瀏覽器的web應用,請求都是有瀏覽器發起的,貌似也不能手動隨便添加請求頭(僅有XMLHttpRequest可以手動設置請求頭),哪有沒有一種可以由服務端生成,客戶端請求是自動在請求中設置對應頭字段的技術呢,這就是cookie

Cookie:

cookie是在客戶端負責保存的,既可以客戶端生成,也可以服務器端生成,Cookie總是保存在客戶端中,按在客戶端中的存儲位置,可分爲內存Cookie和硬盤Cookie:

(1)內存Cookie由瀏覽器維護,保存在內存中,瀏覽器關閉後就消失了,其存在時間是短暫的

(2)硬盤Cookie保存在硬盤裏,有一個過期時間,除非用戶手工清理或到了過期時間,硬盤Cookie不會被刪除

(3)cookie一些重要的屬性,path,domain,maxAge,secure,httponly,可以自己去研究一下

(4)服務端生成cookie的響應頭爲 Set-Cookie:JSESSIONID=164A9B3B768FD959AA20505D4C09; Path=/; HttpOnly

(5)客戶端發送http請求帶的cookie請求頭 Cookie:AMCV_niwodai%40AdobeOrg=-15069…7-badf-4795-9c64-eb9960c23d48

Session的實現原理:

(1)服務端首先查找對應的cookie的值(sessionid)

(2)根據sessionid,從服務器端session存儲中獲取對應id的session數據,進行返回

(3)如果找不到sessionid,服務器端就創建session,生成sessionid對應的cookie,寫入到響應頭中

 

session共享實現

傳統的session由服務器端生成並存儲,當應用進行分佈式集羣部署的時候,如何保證不同服務器上session信息能夠共享呢?

兩種實現方式:1.session集中存儲(redis,memcached,hbase等),2. 不同服務器上session數據進行復制,兩種方式的優缺點,大家應該一目瞭然

基於session集中存儲的實現方案:

(1)新增Filter,攔截請求,包裝HttpServletRequest

(2)改寫getSession方法,從session存儲中獲取session數據,返回自定義的HttpSession實現

(3)在生成新Session後,寫入sessionid到cookie中

 

Redis存儲session的需要考慮問題

1.  session數據如何在Redis中存儲?

2.  session屬性變更何時觸發存儲?

我們的實現:

考慮到session中數據類似map的結構,採用redis中hash存儲session數據比較合適,如果使用單個value存儲session數據,不加鎖的情況下,就會存在session覆蓋的問題,因此使用hash存儲session,每次只保存本次變更session屬性的數據,避免了鎖處理,性能更好

如果每改一個session的屬性就觸發存儲,在變更較多session屬性時會觸發多次redis寫操作,對性能也會有影響,我們是在每次請求處理完後,做一次session的寫入,並且之寫入變更過的屬性

如果本次沒有做session的更改, 是不會做redis寫入的,僅當沒有變更的session超過一個時間閥值(不變更session刷新過期時間的閥值),就會觸發session保存,以便session能夠延長有效期

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