redisphpsession共享
『壹』 php兩台機器如何session同步
給你2種解決方案.
默認情況(php自帶的文件實現)
這種情況. 需要設置sess 文件存儲位置是個網路位置.
例如 設置2號機器的sess存儲目錄為 1號機器的sess存儲目錄, (需要掛載實現)
這樣的話, 就保證了多台機器讀取寫入的是同一個sess文件.使用mysql, memcache, mongodb, redis 等實現.
這個稍微麻煩些. 需要寫實現代碼.
然後用php內置的函數(session_set_save_handler)注冊擴展
還可以用自己的方式單獨實現.(這個更麻煩些, 可以參考下一些開源系統的實現)
『貳』 thinkphp redis存入session怎麼調用
1.在配置項中定義:
'SESSION_TYPE'=>'Redis',//session保存類型
'SESSION_PREFIX'=>'sess_',//session前綴
'REDIS_HOST'=>'127.0.0.1'//REDIS伺服器地址
'REDIS_PORT'=>6379,//REDIS連接埠號
'SESSION_EXPIRE'=>3600,//SESSION過期時間
2.在目錄下新建Redis.class.php文件
文件內容如下:
<?php
namespaceThinkSessionDriver;
classRedis{
//Redis連接對象
private$redis;
//Session過期時間
private$expire;
/**
*打開方法
*@paramtype$path
*@paramtype$name
*@returntype
*/
publicfunctionopen($path,$name){
$this->expire=C('SESSION_EXPIRE')?C('SESSION_EXPIRE'):ini_get('session.gc_maxLifetime');
$this->redis=newRedis();
return$this->redis->connect(C('REDIS_HOST'),C('REDIS_PORT'));
}
/**
*關閉
*@returntype
*/
publicfunctionclose(){
return$this->redis->close();
}
/**
*讀取
*@paramstring$id
*@returntype
*/
publicfunctionread($id){
$id=C('SESSION_PREFIX').$id;
$data=$this->redis->get($id);
return$data?$data:'';
}
/**
*寫入
*@paramstring$id
*@paramtype$data
*@returntype
*/
publicfunctionwrite($id,$data){
$id=C('SESSION_PREFIX').$id;
return$this->redis->set($id,$data,$this->expire);
}
/**
*銷毀
*@paramstring$id
*/
publicfunctiondestroy($id){
$id=C('SESSION_PREFIX').$id;
$this->redis->delete($id);
}
/**
*垃圾回收
*@paramtype$maxLifeTime
*@returnboolean
*/
publicfunctiongc($maxLifeTime){
returntrue;
}
}
memcached的方法和Redis差不多一樣!
『叄』 如何在多台web伺服器上共享session
一、將本該保存在web伺服器磁碟上的session數據保存到cookie中
即用cookie會話機制替代session會話機制,將session數據保存到客戶端瀏覽器的cookie中,這樣同一個用戶訪問同一網站時,無論負載均衡到哪台web伺服器,都不用再去伺服器請求session數據,而直接獲取客戶端cookie中的session數據。如此,同一個用戶的登錄狀態就不會丟失了。
但這樣做,有三大弊端:
把session數據放到客戶端的cookie中,一般都是重要數據(如用戶id、昵稱等),會存在安全問題,但可以將session數據加密後,再存放到cookie中,來降低安全風險。
瀏覽器對單個cookie的數據量大小限制為4K左右,因此會存在數據量的限制問題。
影響帶寬性能,降低了頁面的訪問速度。在高訪問量的情況下,用戶每次請求時,都要將客戶端cookie中的session數據發送到伺服器,要佔用較多的帶寬,進而影響訪問速度,伺服器帶寬成本增高。
二、將本該保存在web伺服器磁碟上的session數據保存到MySQL資料庫中
sessionid還是利用cookie機制存儲到客戶端,但session數據卻存放在MySQL伺服器上。(需要建立sessionid和session數據行的對應關系)
但這樣做,只適合訪問量比較小的網站。如果網站的訪問量比較大,對MySQL伺服器會造成很大壓力。因為每次用戶請求頁面(即使是刷新頁面)都要查詢MySQL資料庫中的session數據表,進而判斷用戶的登錄狀態和讀取用戶相關信息,勢必會對資料庫伺服器造成很大壓力,這樣就會降低伺服器的響應速度,影響用戶體驗。
三、將本該保存在web伺服器磁碟上的session數據保存到內存資料庫(memcache或redis)中
memcache或redis是基於內存存儲數據的,性能很高,尤其是高並發的情況下尤為合適。主要是因為從內存中讀取數據要比從磁碟讀取數據快很多。
內存資料庫還支持數據過期失效的機制,正好與session的過期機制對應,推薦使用redis內存資料庫,因為它比memcache支持更多的
數據類型,且支持內存數據備份到磁碟。
這里簡單說一下,後面兩種方法的注意要點:
如果多台web伺服器對應的是不同的域名,為了保證cookie的唯一(同一個cookie在各個域名有效),需要修改php.ini文件中的session.cookie_domain
由於後面兩種方法,屬於用戶自定義的方式管理session,而非默認的文件處理方式,故需修改php.ini中的session.save_handler=user
在開啟session之前(即調用session_start()之前),需要先調用session_set_save_handler,關於session_set_save_handler的具體用法,請參考php手冊
『肆』 如何實現php+session+memcached高可用集群
在這個互聯網高度發達的時代,許多應用的用戶動輒成百上千萬,甚至上億。為了支持海量用戶的訪問,應用伺服器集群這種水平擴展的方式是最常用的。這種情形下,就會涉及到許多單機環境下完全不需要考慮的問題,這其中session的創建、共享和存儲是最常見之一。
在單機環境中,Session的創建和存儲都是由同一個應用伺服器實例來完成,而存儲也僅是內存中,最多會在正常的停止伺服器的時候,把當前活動的Session鈍化到本地,再次啟動時重新載入。
而多個實例之間,Session數據是完全隔離的。而為了實現Session的高可用,多實例間數據共享是必然的,下面我們以Redis 的SessionManager實現多Tomcat實例Session共享的配置為例,我們來梳理下一般session共享的流程:
添加具體要使用的manager的Jar文件及其依賴
redis session manager依賴jedis, commons-pool, commons-pool2
對應版本的redis session manager的jar文件
在TOMCAT_HOME/conf/context.xml中增加如下配置
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379" database="0"
maxInactiveInterval="30" />
其中host和port等替換為對應的配置信息
啟動多個Tomcat實例,以自帶的examples應用為例進行驗證
訪問examples應用的servlets/servlet/SessionExample,
在頁面中添加數據到session中,並查看頁面上對應的session信息
訪問另一個實例上相同應用的頁面,查看session信息,兩者應該是一致的
使用redis-cli查看redis中存儲的對應數據,相應的sessionId對應的數據已經保存了下來
以上是一個基本的配置過程,而在這些配置與驗證的步驟中,第二步是核心邏輯實現。 前面的文章,曾介紹過Tomcat的Valve,在請求處理時,Pipeline中的各個Valve的invoke方法會依次執行。Tomcat的AccessLogValve介紹
此處的session處理,就是以一個自定義Valve的形式進行的。關於Session的文章,前面也寫過幾篇,會附在結尾處。
以下是RedisSessionhandlerValve的invoke方法,我們看,主要是在Valve執行後進行Session的存儲或移除。
public void invoke(Request request, Response response) {
try {
getNext().invoke(request, response);
} finally {
final Session session = request.getSessionInternal(false);
storeOrRemoveSession(session);
manager.afterRequest();
}
}
而session的保存和移除又是通過manager執行的。 manager.save(session); manager.remove(session);
這里,manager就是前面定義的RedisSessionManager。默認單實例情況下,我們使用的都是StandardManager,對比一下兩者,標準的Manager對於session的創建和刪除,都會調到其父類ManagerBase中相應的方法,
public void add(Session session) {
sessions.put(session.getIdInternal(), session);
int size = getActiveSessions();
if( size > maxActive ) {
synchronized(maxActiveUpdateLock) {
if( size > maxActive ) {
maxActive = size;
}
}
}
}
public void remove(Session session, boolean update) {
if (session.getIdInternal() != null) {
sessions.remove(session.getIdInternal());
}
}
我們來看,由於其只保存在內存的Map中protected Map<String, Session> sessions = new
ConcurrentHashMap<>(),每個Tomcat實例都對於不同的map,多個實例間無法共享數據。
對應到RedisSessionManager對於session的處理,都是直接操作redis,基本代碼是下面這個樣:
public void save(Session session) throws IOException {
Jedis jedis = null;
Boolean error = true;
try {
RedisSession redisSession = (RedisSession) session;
Boolean sessionIsDirty = redisSession.isDirty();
redisSession.resetDirtyTracking();
byte[] binaryId = redisSession.getId().getBytes();
jedis = acquireConnection();
if (sessionIsDirty || currentSessionIsPersisted.get() != true) {
jedis.set(binaryId, serializer.serializeFrom(redisSession));
}
currentSessionIsPersisted.set(true);
jedis.expire(binaryId, getMaxInactiveInterval());
} }
移除時的操作是這樣的
public void remove(Session session, boolean update) {
Jedis jedis = null;
Boolean error = true;
log.trace("Removing session ID : " + session.getId());
try {
jedis = acquireConnection();
jedis.del(session.getId());
error = false;
} finally {
if (jedis != null) {
returnConnection(jedis, error);
}
}
}
而此時,多個Tomcat實例都讀取相同的Redis,session數據是共享的,其它實例的初始請求過來時,由於會執行findSession的操作,此時會從Redis中載入session,
public Session findSession(String id) throws IOException {
RedisSession session;
if (id == null) {
session = null;
currentSessionIsPersisted.set(false);
} else if (id.equals(currentSessionId.get())) {
session = currentSession.get();
} else {
session = loadSessionFromRedis(id); // 看這里,會從redis中load
if (session != null) {
currentSessionIsPersisted.set(true);
}
}
currentSession.set(session);
currentSessionId.set(id);
return session;
}
從而可以保證在一個實例被切換後,另外的實例可以繼續響應同一個session的請求。
以上即為Redis實現session共享高可用的一些關鍵內容。有興趣的朋友可以看下通過Memcached實現高可用,也是這個原理。順著這個思路,如果你有將Session存儲在其它地方的需求時,完全可以寫一個出來,自己動手,豐衣足食。
總結一下,我們是通過自定義的Valve來實現請求後session的攔截,同時,使用自定義的SessionManager,來滿足不同的session創建與存儲的需求。而至於是存儲在Redis/Memcached中,還是存儲在DB中,只是位置的區別。原理,是一致的。
『伍』 做登陸的時候正常session怎麼處理的
nfs文件共享系統,讓不同項目訪問同一個共享的文件。
2)存放在mysql。
3)存放在內存資料庫,比如redis,memcache等。
4)基於cookie的共享。這個需要域名統一。
3.關於redis的session共享,其他類似
1)php.ini裡面存放得有session的存放地址,可以將session的地址改成redis存放session的地址。session.save_path
但是一般這種伺服器端會有訪問控制。所以可以參考第二種方法
2)重寫session,通過php代碼更改session的存放路徑什麼的。php有相關的session重寫的類。
『陸』 thinkphp做的兩套程序的session是共享的,怎麼解決
在thinkphp5.0以上版本中,支持指定 Session 驅動,也就是把session存到一個共用的redis資料庫中。
配置文件如下:
'session' => [
'prefix' => 'mole',
'type' => 'redis',
'auto_start' => true,
// redis主機
'host' => '127.0.0.1',
// redis埠
'port' => 6379,
// 密碼
'password' => '',
]
表示使用redis作為session類型。
具體的可以參考thinkphp5的文檔。
另外,負載均衡的session共享也可以採用這種方式
『柒』 php將session存入redis伺服器中,是否一直存在,何時會被清除
redis是存在內存中的,重啟就會清掉
『捌』 php 用redis儲存session(修改PHP配置文件的),是哪種方式鏈接redis的
我的習慣是直接修改php.ini
session.save_handler = redis
session.save_path = "tcp://host1:6379?weight=1, tcp://host2:6379?weight=2&timeout=2.5, tcp://host3:6379?weight=2&persistent=1"
weight 伺服器權重
persistent 持久性(整數,應該是1或0)
timeout 超時時長
『玖』 微信小程序 php後端使用redis代替session 請求時怎麼處理
因為小程序不支持cook,所以不能直接使用後台語言的session,需要手動搭建session,比如用webcache,或者redis替代session,小程序第一次訪問或者登錄的時候隨機分配一個唯一標識,下次請求伺服器一定要把標識帶上,伺服器用這個標識可以查詢當前用戶信息
『拾』 springboot redis共享後 不同應用怎麼共享同一個sessionid
在spring boot的文檔中,告訴我們添加@EnableRedisHttpSession來開啟spring session支持,配置如下:
@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
}