為什么不能用memcached存儲Session
原文 http://www.infoq.com/cn/news/2015/01/memcached-store-session
Memcached創建者Dormando很早就寫過兩篇文章 [1] [2] ,告誡開發人員不要用memcached存儲Session。他在第一篇文章中給出的理由大致是說,如果用memcached存儲Session,那么當
memcached集群發生故障(比如內存溢出)或者維護(比如升級、增加或減少服務器)時,用戶會無法登錄,或者被踢掉線。而在第二篇文章中,他則指
出,memcached的回收機制可能會導致用戶無緣無故地掉線。
Titas Norkūnas 是DevOps咨詢服務提供商 Bear Mountain的聯合創始人 。由于看到Ruby/Rails社區忽略了Dormando那兩篇文章所指出的問題,所以他近日 撰文 對此進行了進一步的闡述。他認為問題的根本在于,memcached是一個設計用于緩存數據而不是存儲數據的系統,因此不應該用于存儲Session。
對于Dormando的那兩篇文章,他認為第一篇文章給出的原因很容易理解,而人們經常會對第二篇文章給出的原因認識不足。因此他對這個原因進行了詳細地闡述:
Memcached使用“最近最少使用(LRU)”算法回收緩存。但 memcached的LRU算法針對每個slab類執行,而不是針對整體 。
這意味著,如果所有Session的大小大致相同,那么它們會分成兩三個slab類。所有其它大小大致相同的數據也會放入同一些slab, 與Session爭用存儲空間。一旦slab滿了,即使更大的slab中還有空間,數據也會被回收,而不是放入更大的slab中……在特定的slab 中,Session最老的用戶將會掉線。用戶將會開始隨機掉線,而最糟糕的是,你很可能甚至都不會注意到它,直至用戶開始抱怨……
另外,Norkūnas提到,如果Session中增加了新數據,那么Session變大也可能會導致掉線問題出現。
有人提出將Session和其它數據分別使用單獨的memcached緩存。不過,由于memcached的LRU算法是局部的,那種方式不僅導致內存使用率不高,而且也無法消除用戶因為Session回收而出現隨機掉線的風險。
如果讀者非常希望借助memcached提高Session讀取速度,那么可以借鑒Norkūnas提出的memcached+RDBMS(在有些情況下,NoSQL也可以)的模式:
- 當用戶登錄時,將Session “set”到memcached,并寫入數據庫;
- 在Session中增加一個字段,標識Session最后寫入數據庫的時間;
- 每個頁面加載的時候,優先從memcached讀取Session,其次從數據庫讀取;
- 每加載N頁或者Y分鐘后,再次將Session寫入數據庫;
- 從數據庫中獲取過期Session,優先從memcached中獲取最新數據。
關于memcached的更多信息,可以查看 這里 。