以下內容轉自: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的更多信息,可以查看這里[3]。
感謝郭蕾對本文的審校。
[1]:http://www.dormando.me/articles/memcached_sessions/
[2]:http://dormando.livejournal.com/495593.html
[3]:http://work.tinou.com/2011/04/memcached-for-dummies.html
-----------------------------分割線---------------------
PS:LRU算法和Memcache有空在整理下