深入Memcache的Session数据的多服务器共享详解
一相关介绍
1.memcache + memcache的多服务器数据共享的介绍,请参见http://www.guigui8.com/index.php/archives/206.html
2.session机制:
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为sessionid,如果已包含一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含sessionid,则为此客户端创建一个session并且生成一个与此session相关联的sessionid,sessionid的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionid将被在本次响应中返回给客户端保存。
保存这个sessionid的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。
一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,PHPSESSID=ByOK3vjFD75aPnrF3K2HmdnV6QZcEbzWoWiBYEnLerj,它的名字就是PHPSESSID。
二动机
在实际web生产环境中,一个应用系统,往往将不同的业务应用分布到不同服务器上进行处理。
当跟踪当前在线用户信息时,如果是同一个主域名时,可以用全域cookie处理相关数据的共享问题;如果是在不同主域下,则可以通过观察者模式的中心话概念解决相应问题,通过这种概念延伸出的解决方案有很多,而今天我所要讲的,是前一种,通过memcache的多服务器数据共享技术来模拟session,以进行对当前在线用户数据的多服务器共享。
关于多服务器统一session信息,要求如下:
1.能够在memcached规定的几台服务器上,保存session信息(通过前面介绍的memcache的多服务器数据共享);
2.能够象zend定义的session_start()前,通过session_id($sessid)那样,自定义session_id的值。
3.能方便的在系统运行时,切换memcached存储的session信息和 用文件存储的session信息的操作。
三代码
实现方式很简单,通过memcache来模拟session机制,只是利用memcache将存储媒介换成共享服务器的内存,以达到多台分布式部署的服务器共享session信息的目的。而调用的接口,与zend提供的session操作函数相区别,所以可以方便的在memcache和文件的session信息操作建切换。
以下代码,已经过多次实际测试,能达到以上功能需求。先贴下面了:
复制代码 代码如下:
/**
*=---------------------------------------------------------------------------=
* MemcacheSession.class.php
*=---------------------------------------------------------------------------=
*
* 实现基于Memcache存储的 Session 功能
* (模拟session机制,只是利用memcache将存储媒介换成共享服务器的内存)
*
* 缺点:暂时没有引入不同主域的session共享机制的实现策略。即只支持同主域下的实现。
*
* Copyright(c) 2008 by guigui. All rights reserved.
* @author guigui
* @version $Id: MemcacheSession.class.php, v 1.0 2008/12/22 $
* @package systen
* @link http://www.guigui8.com
*/
/**
* class MemcacheSession
*
* 1. 设置客户端的Cookie来保存SessionID
* 2. 把用户的数据保存在服务器端,通过Cookie中的Session Id来确定一个数据是否是用户的
*/
class MemcacheSession
{
// {{{ 类成员属性定义
public $memObject = null; //memcache操作对象句柄
private $_sessId = '';
private $_sessKeyPrefix = 'sess_';
private $_sessExpireTime = 86400;
private $_cookieDomain = '.guigui8.com'; //全域cookie域名
private $_cookieName = '_PROJECT_MEMCACHE_SESS';
private $_cookieExpireTime = '';
private $_memServers = array('192.168.0.3' => 11211, '192.168.0.4' => 11211);
private $_sessContainer = array(); //当前用户的session信息
private static $_instance = null; //本类单例对象
// }}}
/**
* 单例对象获取的静态方法。
* (可以顺便提供memcache信息存储的服务器参数)
*
* @param string $host - memcache数据存储的服务器ip
* @param integer $port - memcache数据存储的服务器端口号
* @param bool $isInit - 是否实例化对象的时候启动Session
*/
public static function getInstance($host='', $port=11211, $isInit = true) {
if (null === self::$_instance) {
self::$_instance = new self($host, $port, $isInit);
}
return self::$_instance;
}
/**
* 构造函数
*
* @param bool $isInit - 是否实例化对象的时候启动Session
*/
private function __construct($host='', $port=11211, $isInit = false){
!empty($host) && $this->_memServers = array(trim($host) => $port);
$isInit && $this->start();
}
/**
*=-----------------------------------------------------------------------=
*=-----------------------------------------------------------------------=
* Public Methods
*=-----------------------------------------------------------------------=
*=-----------------------------------------------------------------------=
*/
/**
* 启动Session操作
*
* @param int $expireTime - Session失效时间,缺省是0,当浏览器关闭的时候失效, 该值单位是秒
*/
public function start($expireTime = 0){
$_sessId = $_COOKIE[$this->_cookieName];
if (!$_sessId){
$this->_sessId = $this->_getId();
$this->_cookieExpireTime = ($expireTime > 0) ? time() + $expireTime : 0;
setcookie($this->_cookieName, $this->_sessId, $this->_cookieExpireTime, "/", $this->_cookieDomain);
$this->_initMemcacheObj();
$this->_sessContainer = array();
$this->_saveSession();
} else {
$this->_sessId = $_sessId;
$this->_sessContainer = $this->_getSession($_sessId);
}
}
/**
* setSessId
*
* 自定义的session id,通常没有必要经过cookie操作处理的(所以省略了cookie记录session_id)
*
* @param string $sess_id
* @return boolean
*/
public function setSessId($sess_id){
$_sessId = trim($sess_id);
if (!$_sessId){
return false;
} else {
$this->_sessId = $_sessId;
$this->_sessContainer = $this->_getSession($_sessId);
}
}
/**
* 判断某个Session变量是否注册
*
* @param string $varName -
* @return bool 存在返回true, 不存在返回false
*/
public function isRegistered($varName){
if (!isset($this->_sessContainer[$varName])){
return false;
}
return true;
}
/**
* 注册一个Session变量
*
* @param string $varName - 需要注册成Session的变量名
* @param mixed $varValue - 注册成Session变量的值
* @return bool - 该变量名已经存在返回false, 注册成功返回true
*/
public function set($varName, $varValue){
$this->_sessContainer[$varName] = $varValue;
$this->_saveSession();
return true;
}
/**
* 获取一个已注册的Session变量值
*
* @param string $varName - Session变量的名称
* @return mixed - 不存在的变量返回false, 存在变量返回变量值
*/
public function get($varName){
if (!isset($this->_sessContainer[$varName])){
return false;
}
return $this->_sessContainer[$varName];
}
/**
* 销毁一个已注册的Session变量
*
* @param string $varName - 需要销毁的Session变量名
* @return bool 销毁成功返回true
*/
public function delete($varName){
unset($this->_sessContainer[$varName]);
$this->_saveSession();
return true;
}
/**
* 销毁所有已经注册的Session变量
*
* @return 销毁成功返回true
*/
public function destroy(){
$this->_sessContainer = array();
$this->_saveSession();
return true;
}
/**
* 获取所有Session变量
*
* @return array - 返回所有已注册的Session变量值
*/
public function getAll(){
return $this->_sessContainer;
}
/**
* 获取当前的Session ID
*
* @return string 获取的SessionID
*/
public function getSid(){
return $this->_sessId;
}
/**
* 获取Memcache的服务器信息
*
* @return array Memcache配置数组信息
*/
public function getMemServers(){
return $this->_memServers;
}
/**
* 设置Memcache的服务器信息
*
* @param string $host - Memcache服务器的IP
* @param int $port - Memcache服务器的端口
*/
public function setMemServers($arr){
$this->_memServers = $arr;
}
/**
* 添加Memcache服务器
*
* @param string $host - Memcache服务器的IP
* @param int $port - Memcache服务器的端口
*/
public function addMemServer($host, $port){
$this->_memServers[trim($host)] = trim($port);
$this->memObject->addServer($host, $port);
}
/**
* 移除Memcache服务器(注意,这个只是移除配置,并不能实际从memcached的连接池移除)
*
* @param string $host - Memcache服务器的IP
* @param int $port - Memcache服务器的端口
*/
public function removeMemServer($host){
unset($this->_memServers[trim($host)]);
}
/**
*=-----------------------------------------------------------------------=
*=-----------------------------------------------------------------------=
* Private Methods
*=-----------------------------------------------------------------------=
*=-----------------------------------------------------------------------=
*/
/**
* 生成一个Session ID
*
* @return string 返回一个32位的Session ID
*/
private function _getId(){
return md5(uniqid(microtime()));
}
/**
* 获取一个保存在Memcache的Session Key
*
* @param string $_sessId - 是否指定Session ID
* @return string 获取到的Session Key
*/
private function _getSessKey($_sessId = ''){
$sessKey = ($_sessId == '') ? $this->_sessKeyPrefix.$this->_sessId : $this->_sessKeyPrefix.$_sessId;
return $sessKey;
}
/**
* 检查保存Session数据的路径是否存在
*
* @return bool 成功返回true
*/
private function _initMemcacheObj(){
if (!class_exists('Memcache') || !function_exists('memcache_connect')){
$this->_showMessage('Failed: Memcache extension not install, please from http://pecl.php.net download and install');
}
if ($this->memObject && is_object($this->memObject)){
return true;
}
$this->memObject = new Memcache;
if (!empty($this->_memServers)) {
foreach ($this->_memServers as $_host => $_port) {
$this->memObject->addServer($_host, $_port);
}
}
return true;
}
/**
* 获取Session文件中的数据
*
* @param string $_sessId - 需要获取Session数据的SessionId
* @return unknown
*/
private function _getSession($_sessId = ''){
$this->_initMemcacheObj();
$sessKey = $this->_getSessKey($_sessId);
$sessData = $this->memObject->get($sessKey);
if (!is_array($sessData) || empty($sessData)){
//this must be $_COOKIE['__SessHandler'] error!
return array();
}
return $sessData;
}
/**
* 把当前的Session数据保存到Memcache
*
* @param string $_sessId - Session ID
* @return 成功返回true
*/
private function _saveSession($_sessId = ''){
$this->_initMemcacheObj();
$sessKey = $this->_getSessKey($_sessId);
if (empty($this->_sessContainer)){
$ret = @$this->memObject->set($sessKey, $this->_sessContainer, false, $this->_sessExpireTime);
}else{
$ret = @$this->memObject->replace($sessKey, $this->_sessContainer, false, $this->_sessExpireTime);
}
if (!$ret){
$this->_showMessage('Failed: Save sessiont data failed, please check memcache server');
}
return true;
}
/**
* 显示提示信息
*
* @param string $strMessage - 需要显示的信息内容
* @param bool $isFailed - 是否是失败信息, 缺省是true
*/
private function _showMessage($strMessage, $isFailed = true){
return;
if ($isFailed){
echo ($strMessage);
}
echo $strMessage;
}
四应用
1.本地session存储,与原始session操作方式一样,没有任何改变。如:
复制代码 代码如下:
session_start();
$_SESSION['file_session_info']= '本地文件保存的session信息'; //本地文件保存的session
2.memcache共享服务器的session存储
复制代码 代码如下:
$mem= MemcacheSession::getInstance('192.168.0.4', 11211);
$mem->addMemServer('192.168.0.4',11211);
$mem->addMemServer('192.168.0.5',11211);
//如果cookie功能不可用,则根据其他参数传递的唯一信息,设置映射为session_id
if(1) {
$sn= '838ece1033bf7c7468e873e79ba2a3ec';
$mem->setSessId($sn);
}
$mem->set('name','guigui'); //多台memcache服务器共享的session
$mem->set('addr','wuhan'); //多台memcache服务器共享的session
//$mem->destroy();
3.分别获取本地和memcache存储的session信息
复制代码 代码如下:
$addr= $mem->get('addr');
$_MEM_SESSION= $mem->getAll();
echo"
localhost file session:";
var_dump($_SESSION);
echo"
memcache session:";
var_dump($_MEM_SESSION);
//$res= $mem->delete('name');

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

0.這篇文章乾了啥?提出了DepthFM:一個多功能且快速的最先進的生成式單目深度估計模型。除了傳統的深度估計任務外,DepthFM還展示了在深度修復等下游任務中的最先進能力。 DepthFM效率高,可以在少數推理步驟內合成深度圖。以下一起來閱讀這項工作~1.論文資訊標題:DepthFM:FastMonocularDepthEstimationwithFlowMatching作者:MingGui,JohannesS.Fischer,UlrichPrestel,PingchuanMa,Dmytr

谷歌力推的JAX在最近的基準測試中表現已經超過Pytorch和TensorFlow,7項指標排名第一。而且測試並不是JAX性能表現最好的TPU上完成的。雖然現在在開發者中,Pytorch依然比Tensorflow更受歡迎。但未來,也許有更多的大型模型會基於JAX平台進行訓練和運行。模型最近,Keras團隊為三個後端(TensorFlow、JAX、PyTorch)與原生PyTorch實作以及搭配TensorFlow的Keras2進行了基準測試。首先,他們為生成式和非生成式人工智慧任務選擇了一組主流

DHCP中繼的作用是將接收到的DHCP封包轉送到網路上的另一個DHCP伺服器,即使這兩台伺服器位於不同的子網路中。透過使用DHCP中繼,您可以實現在網路中心部署集中式的DHCP伺服器,並利用它為所有網路子網路/VLAN動態分配IP位址。 Dnsmasq是一種常用的DNS和DHCP協定伺服器,可設定為DHCP中繼伺服器,以協助管理網路中的動態主機設定。在本文中,我們將向您展示如何將dnsmasq配置為DHCP中繼伺服器。內容主題:網路拓樸在DHCP中繼上設定靜態IP位址集中式DHCP伺服器上的D

在iPhone上面臨滯後,緩慢的行動數據連線?通常,手機上蜂窩互聯網的強度取決於幾個因素,例如區域、蜂窩網絡類型、漫遊類型等。您可以採取一些措施來獲得更快、更可靠的蜂窩網路連線。修復1–強制重啟iPhone有時,強制重啟設備只會重置許多內容,包括蜂窩網路連線。步驟1–只需按一次音量調高鍵並放開即可。接下來,按降低音量鍵並再次釋放它。步驟2–過程的下一部分是按住右側的按鈕。讓iPhone完成重啟。啟用蜂窩數據並檢查網路速度。再次檢查修復2–更改資料模式雖然5G提供了更好的網路速度,但在訊號較弱

特斯拉機器人Optimus最新影片出爐,已經可以在工廠裡打工了。正常速度下,它分揀電池(特斯拉的4680電池)是這樣的:官方還放出了20倍速下的樣子——在小小的「工位」上,揀啊揀啊揀:這次放出的影片亮點之一在於Optimus在廠子裡完成這項工作,是完全自主的,全程沒有人為的干預。而且在Optimus的視角之下,它還可以把放歪了的電池重新撿起來放置,主打一個自動糾錯:對於Optimus的手,英偉達科學家JimFan給出了高度的評價:Optimus的手是全球五指機器人裡最靈巧的之一。它的手不僅有觸覺

多模態文件理解能力新SOTA!阿里mPLUG團隊發布最新開源工作mPLUG-DocOwl1.5,針對高解析度圖片文字辨識、通用文件結構理解、指令遵循、外部知識引入四大挑戰,提出了一系列解決方案。話不多說,先來看效果。複雜結構的圖表一鍵識別轉換為Markdown格式:不同樣式的圖表都可以:更細節的文字識別和定位也能輕鬆搞定:還能對文檔理解給出詳細解釋:要知道,“文檔理解”目前是大語言模型實現落地的一個重要場景,市面上有許多輔助文檔閱讀的產品,有的主要透過OCR系統進行文字識別,配合LLM進行文字理

哭死啊,全球狂煉大模型,一網路的資料不夠用,根本不夠用。訓練模型搞得跟《飢餓遊戲》似的,全球AI研究者,都在苦惱怎麼才能餵飽這群資料大胃王。尤其在多模態任務中,這問題尤其突出。一籌莫展之際,來自人大系的初創團隊,用自家的新模型,率先在國內把「模型生成數據自己餵自己」變成了現實。而且還是理解側和生成側雙管齊下,兩側都能產生高品質、多模態的新數據,對模型本身進行數據反哺。模型是啥?中關村論壇上剛露面的多模態大模型Awaker1.0。團隊是誰?智子引擎。由人大高瓴人工智慧學院博士生高一鑷創立,高

FP8和更低的浮點數量化精度,不再是H100的「專利」了!老黃想讓大家用INT8/INT4,微軟DeepSpeed團隊在沒有英偉達官方支援的條件下,硬生在A100上跑起FP6。測試結果表明,新方法TC-FPx在A100上的FP6量化,速度接近甚至偶爾超過INT4,而且比後者擁有更高的精度。在此基礎之上,還有端到端的大模型支持,目前已經開源並整合到了DeepSpeed等深度學習推理框架中。這項成果對大模型的加速效果也是立竿見影──在這種框架下用單卡跑Llama,吞吐量比雙卡還要高2.65倍。一名
