分佈式session有如下幾種方案:
1. 基於nfs(net filesystem)的session共享mysql
將共享服務器目錄mount各服務器的本地session目錄,session讀寫受共享服務器io限制,不能知足高併發。web
2. 基於關係數據庫的session共享redis
這種方案廣泛使用。使用關係數據庫存儲session數據,對於mysql數據庫,建議使用heap引擎。 這種方案性能取決於數據庫的性能,在高併發下容易形成表鎖(雖然能夠採用行鎖的存儲引擎,性能會降低),而且須要本身實現session過時淘汰機制。算法
3. 基於cookie的session共享sql
這種方案也在大型互聯網中廣泛使用,將用戶的session加密序列化後以cookie的方式保存在網站根域名下(好比taobao.com),當 用戶訪問全部二級域名站點式,瀏覽器會傳遞全部匹配的根域名的cookie信息,這樣實現了用戶cookie化session的多服務共享。 此方案可以節省大量服務器資源,缺點是存儲的信息長度受到http協議限制;cookie的信息還須要作加密解密; 請求任何資源時都會將cookie附加到http頭上傳到服務器,佔用了必定帶寬。數據庫
4. 基於resin/tomcat/iis等web容器的session機制瀏覽器
利用容器機制,經過配置便可實現。tomcat
5. 基於zookeeper的分佈session存儲服務器
詳見http://my.oschina.net/u/699015/blog/159654cookie
6. 基於redis/memcached的session共享存儲
這些key/value非關係存儲有較高的性能,輕鬆達到2000左右的qps,內置的過時機制正好知足session的自動實效特性。
以上方案各有優缺點,本文主要介紹第六種基於redis存儲session時,如何實現動態擴容。 redis目前並無內置高可用集羣,不少客戶端代理基於一致性hash算法可以實現分佈式存儲,可是擴容並不方便(須要成倍擴容),目前咱們採用了淘寶 fourinone中session方案的思想:
a. 用於存儲session的redis集羣有多個redis節點
b. proxy記錄了每一個節點加入到集羣的時間,並按照時間順序對節點進行了編號(0—n)
c. session key的生成算法方面,須要在session key中包含生成時的當前日期(可考慮細化到小時仍是分秒),在session key生成後,再進行取模運算 hash(sesionKey)%redisHost_count, 根據取模結果決定當前session值存儲到落到哪一個節點上存儲。
d. 再經過sessionkey獲取session信息時,根據當前sessionKey取出時間部分,再根據取出的時間與redis集羣中全部的節點的添加 時間進行比較,篩選出全部addtime<sessionkey_time的節點,再進行c中的取模計算,因爲即便這期間進行了擴容,因爲進行了時 間匹配,redisHost_count也不會發生變化,因此取模結果和存儲此session時同樣,還會落到當時存儲這個session的節點上,在那 個節點可以獲得此session的值。
可是對於這種部署結果如何可以保障高可用性,如何應對單點故障,後續會在redis高可用方案中介紹。