這是最簡單的實現方式,數據庫還能在整個系統都當掉時依舊保存好session數據,可靠性高,幾乎所有J2EE實現都提供了這種方式,當然,你的session數據必須是可序列化的。但是,這種方式一般推薦不要在session中存放過大過多的數據,因爲數據庫的事務過程相當費資源,但這樣也大大限制了它的使用範圍,畢竟我們有時必須要在session中存放一些大對象
內存拷貝方式
雖然實現起來容易,但這種方法的弊端也顯而易見,當節點增加時,拷貝量就要成倍增長,性能有時還不如不集羣
Weblogic, Jboss 和 WebSphere的實現:雙服務器拷貝
雖然這種方法的性能和擴展性都很好,但也有不少弊端
l 負載均衡器的複雜度加大,因爲要記住每個服務器的備份者是誰
l 除了處理請求外,每個服務器還得自己維護備份開銷
l 平時大量的內存都被用於備份數據,會增加jvm的垃圾收集頻率,間接影響性能
l 一旦某個服務器長時間掛掉,那麼另一臺服務器的負荷就會翻倍,可能也被一起拖垮
爲了克服以上缺點,各個廠商都有自己的不同解決方案
IBM的方案:中央服務器
很像是之前的數據庫方式吧,只是把數據庫換成了一臺專門備份的服務器,綜合了數據庫和內存方式的優點。
l 將備份和請求處理分開,增強了系統的魯棒性
l 所有的備份數據都在專門的服務器上,節省了其他服務器的內存
l 所有服務器都能存取備份機器上的數據,任何服務器宕機了,負載都能平滑的分配到剩餘所有服務器上,而不至於加重某臺機器的負擔
l 比起數據庫連接,備份服務器使用的socket連接更加輕量級
比起直接的雙服務器互拷內存,這種方式效率還是比較低的,因爲還要有個恢復的過程,而且在管理上也增加了系統的複雜度。此外,備份服務器本身也很有可能成爲瓶頸。
Sun的實現:專用數據庫
表面上就是數據庫的方式,但實際上,Sun JES應用服務器使用的稱爲“HADB”的數據庫是專門爲session的備份做了優化的,其大部分數據都是直接存放在內存中
Session備份的性能考慮
集羣中每臺服務器都有多個web應用,每個應用又同時有數以千記的用戶session,這些session的備份和恢復都會耗費大量資源。更恐怖的是,session一直在變,比如失效了,比如增加或修改某個屬性了,等等。所以如何備份session是考驗系統架構水平的
何時備份?
不管是用數據庫還是內存方式,下面兩點都是比較常見的考慮
l 按web 請求,即每次請求都進行備份更新,這樣可以保證備份的數據是最新的
l 固定時間備份,雖然不能保證備份的session是最新的,但卻可以提高性能
備份粒度
l 全部備份,最保險也是最慢的方法
l 備份修改過的session。通常的做法是檢測”HTTPSession.setAttribute()” 或“HTTPSession.removeAttribute()” 的調用,當然你要保證session的狀態只能由這兩個方法更改,儘管這不是J2EE規範的要求。
l 備份修改過的session的屬性,最節省性能的做法。但是有一點很重要:防止交叉引用。如下圖,session中包含school對象,指向一個student對象。當school對象某個屬性改變後,被備份到AS2中,它此時引用的是舊的student對象。接着student對象被單獨改變了,也進行了備份,但是school中仍然引用舊的student。因此這種方法對web容器的設計要求很高,儘管它的性能是最好的。
圖十三:session複製中的交叉引用
其他失效備援的實現
以上不論是數據庫還是內存複製,歸根結底都要使用Java的序列化機制,這給web容器的性能造成了不小的影響,因此有些應用服務器使用別的方式進行session備份
JRun with Jini
JRun 4使用jini實現集羣,jini的詳細介紹請參考 http://java.sun.com/products/jini/2_0index.html
Tangosol with Distributed Cache
Tangosol Coherence™提供了一個分佈式數據管理平臺,可以嵌入到大部分J2EE系統中,此外還提供一個分佈式緩存系統,能夠在多臺jvm上有效的共享緩存,詳情請參考 http://www.tangosol.com/