① 基於memcached的session會話共享怎樣實現
由於Cookie是保存的用戶客戶端的,安全性存在問題,為保證用戶數據的安全性,我們必須使用Session機制來保存用戶登錄後的一些信息。
如果我們使用LVS對Apache實現負載均衡,就無法保證用戶每次都能被分配到同一台Apache Server上,以取到自己的Session,雖然LVS可以加-p參數來保證客戶端每次都被分配到同一台Apache Server上,但這種方式存在一些弊端,比如必須設置一個保持時間,如果時間太長了,LVS就需要緩存大量信息,時間太短了,又不能保證用戶每次被分配到同一台Server上,而且這種方式也不易實現Session的冗餘備份。
因此,我們需要Session共享,也就是說每台Apache都可以訪問到所有的Session,這樣用戶被分配到哪台Server就不重要了。
Session共享主要有多種實現方式:
Session復制。Apache可以實現把Session同步到其他Server上去,但這種技術太復雜,而且影響性能,佔用內存,所以不推薦使用。
Session集中存儲。存儲介質可以是NFS文件系統、資料庫、Memcached,從性能上考慮,當然是Memcached最好,推薦使用。
1.3 實現
1.3.1 安裝Memcached
Memcached是基於libevent實現的,所以要首先確保已經安裝libevent。
安裝libevent
tar zxvf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./configure --prefix=/usr
make && make install
安裝Memcached
tar zxvf memcached-1.4.4.tar.gz
cd memcached-1.4.4
./configure --prefix=/usr/local/memcached --with-libevent=/usr
make && make install
啟動Memcached
/usr/local/memcached/bin/memcached -d -m 10 -u root -l 192.168.0.9 -p 11211 -c 256 -P /tmp/memcached.pid
1.3.2 安裝PHP擴展pecl::memcache
pecl install memcache
或源碼安裝
tar zxvf memcache-2.2.5.tgz
cd memcache-2.2.5
phpize
./configure
make && make install
將 php.ini 中 extension=memcache.so 打開,重啟一下 apache,查看 phpinfo 中的 "Registered save handlers" 會有"files user memcache" 這3個可用。
另外,基於libmemached的php擴展在pecl發布了,叫pecl::memcached,性能上可能會更好。
1.3.3 配置Memcached保存Session
修改配置文件,在 php.ini 中全局設置
session.save_handler = memcache
session.save_path = "tcp://192.168.0.9:11211"
或者某個目錄下的 .htaccess :
php_value session.save_handler "memcache"
php_value session.save_path "tcp://192.168.0.9:11211"
再或者在某個一個應用中:
ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://192.168.0.9:11211");
使用多個 memcached server 時用逗號","隔開,並且和 Memcache::addServer() 文檔中說明的一樣,可以帶額外的參數"persistent"、"weight"、"timeout"、"retry_interval" 等等,類似這樣的:"tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2" 。
1.3.4 測試
<?php
session_start();
if (!isset($_SESSION['TEST'])) {
$_SESSION['TEST'] = time();
}
$_SESSION['TEST3'] = time();
print $_SESSION['TEST'];
print "<br><br>";
print $_SESSION['TEST3'];
print "<br><br>";
print session_id();
?>
可以直接用sessionid 去 memcached 里查詢一下:
telnet 192.168.0.9 11211
get
得到
TEST|i:1177556731;TEST3|i:1177556881;
這樣的結果,說明session 正常工作
用Memcached來存儲 session 在讀寫速度上會比文件快很多,而且在多個伺服器需要共用session時會比較方便,將這些伺服器都配置成使用同一組Memcached伺服器就可以,減少了額外的工作量。缺點是 session 數據都保存在 memory 中,持久化方面有所欠缺,但對 session 數據來說也不是很大的問題,如果要持久化數據,也可以使用新浪開發的MemcacheDB或日本人開發的Tokyo tyrant+Tokyo Cabinet。
另外,如何解決Memcached的單點故障問題,有以下幾個方案:
使用上面提到的Memcache::addServer增加多台Memcached,但這樣只能達到一台出故障之後,另外一台可以使用,但每台Memcached的數據是獨立的,不共享,不復制,出故障的數據丟失了。
使用Memcached的一個補丁應用repcached,可以實現multi master replication和asynchronous data repliacation,並且支持原來Memcached的所有命令。不過這個應用只支持Memcached1.2.x版本。
使用Tokyo tyrant+Tokyo Cabinet(簡稱TT+TC)。TT兼容Memcached協議,可以直接替換使用,TT支持replication,可以實現故障轉移,TC則為TT提供持久化。
TT+TC是日本最大的社交類網站mixi.jp開發的開源應用,並已成功應用在mixi.jp中,值得研究。
② 使用memcached後web.xml里配置的session-timeout不起作用了
檢查下你的用戶登錄狀態判定是否有讀取memcached的緩存;
確定下登錄信息是存儲在session還是cookie;
確認下配置的位置是否正確,留意下你主項目是用的nginx?還是tomcat?項目在哪裡,配置應該也在那個server下
③ 高分懸賞50:tomcat中session共享問題,項目的session在filter中獲取不了
你可是考慮使用memcached來代替session,這樣所有的session都會存放到memcached中,布置在tomcat伺服器端,這樣你就可以在filter中獲取登錄時的session,關於具體memcached的相關配置內容網上的資料很多,你可以查查看看,如果查不到的話可以在聯系我。
同時也可以登錄我的網易博客http://ltftosot21713.blog.163.com/查看相關的內容,祝你好運!
④ 為什麼不能用memcached存儲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]。
感謝郭蕾對本文的審校。
⑤ 使用memcached來保存session session的過期時間怎麼計算
1. 基於nfs(net filesystem)的session共享
將共享伺服器目錄mount各伺服器的本地session目錄,session讀寫受共享伺服器io限制,不能滿足高並發。
2. 基於關系資料庫的session共享
這種方案普遍使用。使用關系資料庫存儲session數據,對於mysql資料庫,建議使用heap引擎。 這種方案性能取決於資料庫的性能,在高並發下容易造成表鎖(雖然可以採用行鎖的存儲引擎,性能會下降),並且需要自己實現session過期淘汰機制。
3. 基於cookie的session共享
這種方案也在大型互聯網中普遍使用,將用戶的session加密序列化後以cookie的方式保存在網站根域名下(比如taobao.com),當 用戶訪問所有二級域名站點式,瀏覽器會傳遞所有匹配的根域名的cookie信息,這樣實現了用戶cookie化session的多服務共享。 此方案能夠節省大量伺服器資源,缺點是存儲的信息長度受到http協議限制;cookie的信息還需要做加密解密; 請求任何資源時都會將cookie附加到http頭上傳到伺服器,佔用了一定帶寬。
4. 基於resin/tomcat/iis等web容器的session機制
利用容器機制,通過配置即可實現。
5. 基於zookeeper的分布session存儲
詳見http://my.oschina.net/u/699015/blog/159654
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的值。
⑥ Nginx+Tomcat+Memcached共享session後一直報警告
我這邊在高並發的情況下也會報出此錯誤。
此時在程序裡面獲取session的時候,session明顯異常了,從session裡面拿出來的用戶也不對。
然後從這裡面拿出來的對象的值去構造字元串信息發送給iframe,此時就不對了。
發送下去的串,肯定的不行了。
⑦ 如何採用Memcached實現分布式Session
以Non-Sticky模式為例,首先需要安裝memcached的伺服器,這個在上一篇中已經講述過了。然後在Tomcat的$CATALINA_HOME/conf/context.xml文件配置SessionManager,具體配置如下:
<code class="hljs xml"> <manager classname="de.javakaffee.web.msm.MemcachedBackupSessionManager" lockingmode="auto" memcachednodes="n1:10.10.195.112:11211" requesturiignorepattern=".*\.(ico|png|gif|jpg|css|js)$" sessionbackupasync="false" sessionbackuptimeout="1000" sticky="false" transcoderfactoryclass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"> </manager></code>
?其中,memcachedNodes指定了memcached的節點;sticky表示是否採用sticky模式;sessionBackuoAsync表示是否採用非同步方式備份session;lockingMode表示session的鎖定模式;auto表示對於只讀請求,session將不會被鎖定,如果包含寫入請求,則session會被鎖定;requestUriIgnorePattern表示忽略的url; transcoderFactoryClass用來指定序列化的方式,這里採用的是Kryo序列化,也是memcached-session-manager比較推薦的一種序列化方式。也可以採用其他序列化方式,譬如:javolution-serializer, xstream-serializer, flexjson-serializer。
?memcached-session-manager依賴於memcached-session-manager-{version}.jar,如果使用的是tomcat6,則還需要下載memcached-session-manager-tc6-{version}.jar,如果是tomcat7則採用memcached-session-manager-tc7-{version}.jar的包(博主採用的是tomcat7+jdk7)。還需要spymemcached-2.7.3.jar,在啟動tomcat之前需要將這些jar包放到tomcat的lib目錄下。如果採用Kryo方式序列化,還需要加入其他一些包
⑧ java怎麼獲取memcached-session-manager裡面的session
這個屬性必須包含所有的 memcached nodes或者membase bucket uri(s) ,所有的tomcat都必須配置好。每個節點用","分割例如對於一個節點來說<id>是可選的(e.g. memcachedNodes="n1:app01:11211,n2:app02:11211"),所以還可以使用<host>:<port>來定義 (e.g. memcachedNodes="localhost:11211"),這樣sessionId就不會改變(沒有添加node id),這個選項在配置 membase+moxi是非常有用的,所有的tomcat僅僅認識一個"memcached"(實際上是moxi)
memcached nodes:每一個memcached node 定義方式為<id>:<host>:<port>.
membase bucket uris (since 1.6.0): 使用membase 必須配置一個或者多個membase bucket uris, 例如 http://host1:8091/pools,http://host2:8091/pools. Bucket用戶名和密碼必須通過 username跟password 配置(下面還會講到)。 連接到 membase 需要一些支持memcached 協議的jar包. 需要把 jettison.jar 跟 netty.jar 放到 CATALINA_HOME/lib/.
failoverNodes (可選的, 在 non-sticky sessions 是必須的)
當有其他可以使用的memcache 節點的時候使用,因此你應該列出那些跟你的tomcat在同一台機器上的memcached node例如,host1上安裝了tomcat1(t1) memcached1(m1),host2上安裝了tomcat1(t2) memcached1(m2),你應該設置n1作為tomcat1的failover node.因此當memcached2(tomcat2 failoverNodes 設置為 n2)不能使用的時候tomcat1 的session 僅僅存儲在memcached1. 這種設置當host1宕機的時候tomcat1的session 還是可以繼續工作的。
對於非粘性會話的會話是不依賴於一個單一的tomcat failoverNodes不得指定。對於membase buckets 這個屬性可以省略。
多個memcached node 必須用空格「 」或者逗號「,」分隔。
username (1.6.0以後, 可選的)
membase bucket或者SASL 使用的username,如果memcachedNodes 包含一個(或多個)membase bucket uri,這就是bucket的名稱。如果memcachedNodes 使用了username 給SASL授權。還需要一個memcached 協議的包。
password (1.6.0以後, 可選的)
membase bucket 或者 SASL 授權密碼(如果沒有密碼默認為空就好)。
memcachedProtocol (1.3以後, 可選的, 默認值 text)
使用的memcached的協議, text或者binary.
sticky (1.4.0以後, 可選的, 默認值 true)
設置 sticky Session 或者 non-sticky Session.