網站業務規模和訪問量的逐步發展,原本由單一伺服器、單一網域的迷你網站架構已經無法滿足發展需求。
此時我們可能會購買更多伺服器,並且啟用多個二級子網域以頻道化的方式,根據業務功能將網站分佈部署在獨立的伺服器上;或透過負載平衡技術(如:DNS輪詢、 Radware、F5、LVS等)讓多個頻道共用一組伺服器。
OK,頭腦中我們已經構思了這樣的解決方案,不過進入深入開發後新的技術問題又隨之而來:
我們把網站程式分佈部署到多台伺服器上,而且獨立為幾個二級域名,由於Session受實現原理的局限(PHP中Session預設以檔案的形式保存在本地伺服器的硬碟),使得我們的網站使用者必須經常在幾個頻道間來回輸入使用者名稱、密碼登錄,導致使用者體驗大打折扣;另外,原本程式可以直接從使用者Session變數讀取的資料(如:暱稱、積分、登錄時間等),因為無法跨伺服器同步更新Session變量,迫使開發人員必須即時讀寫資料庫,從而增加了資料庫的負擔。
於是,解決網站跨伺服器之間的Session共享方案需求變得迫切起來,最終催生了多種解決方案,以下列舉4種較為可行的方案進行對比探討:
1. 基於NFS的Session共享
NFS是Net FileSystem的簡稱,最早由Sun公司為解決Unix網路主機間的目錄共享而研發。
這個方案實現最為簡單,無需做過多的二次開發,僅需將共享目錄伺服器mount到各頻道伺服器的本地session目錄即可,缺點是NFS依託於複雜的安全機制和檔案系統,因此並發效率不高,尤其對於session這類高並發讀寫的小文件, 會由於共享目錄伺服器的io-wait過高,最終拖累前端WEB應用程式的執行效率。
2. 基於資料庫的Session共享
首選當然是大名鼎鼎的Mysql資料庫,並且建議使用內存表Heap,提高session操作的讀寫效率。這個方案的實用性比較強,相信大家普遍在使用,它的缺點在於session的並發讀寫能力取決於Mysql資料庫的效能,同時需要自己實作session淘汰邏輯,以便定時從資料表更新、刪除session記錄,當同時發生過高時容易出現表鎖,雖然我們可以選擇行級鎖的表引擎,但不得不否認使用資料庫儲存Session還是有些殺雞用牛刀的架勢。
3. 基於Cookie的Session共享
這個方案我們可能比較陌生,但它在大型網站中還是比較普遍被使用。原理是將全站使用者的Session資訊加密、序列化後以Cookie的方式, 統一種植在根域名下(如:.host.com),利用瀏覽器訪問該根域名下的所有二級域名站點時,會傳遞與之網域對應的所有Cookie內容的特性,進而實現使用者的Cookie化Session 在多服務間的共享存取。
這個方案的優點無需額外的伺服器資源;缺點是由於受http協議頭信心長度的限制,僅能夠存儲小部分的用戶信息,同時Cookie化的Session內容需要進行安全加解密(如:採用DES、RSA等進行明文加解密;再由MD5、SHA-1等演算法進行防偽認證),另外它也會佔用一定的頻寬資源,因為瀏覽器會在請求當前網域下任何資源時將本地Cookie附加在http頭中傳遞到伺服器。
4. 基於Memcache的Session共享
Memcache由於是一款基於Libevent多路異步I/O技術的內存共享系統,簡單的Key + Value數據存儲模式使得代碼邏輯小巧高效,因此在並發處理能力上佔據了絕對優勢,目前本人所經歷的專案達到2000/秒平均查詢,且伺服器CPU消耗仍不到10%。
另外值得一提的是Memcache的內存hash表所特有的Expires資料過期淘汰機制,正好和Session的過期機制不謀而合,降低了過期Session資料刪除的程式碼複雜度,對比「基於資料庫的儲存方案”,僅這塊邏輯就給資料表產生巨大的查詢壓力。
基於Memcache 的儲存是這幾個方案中建議選用的!
其它方案依然有其使用的場合,具體選用哪套需要開發人員的根據當前的伺服器資源、網站並發壓力等綜合評估。