了解Memcache
1、什么是Memcache
概括:就是一個(gè)數(shù)據(jù)庫、但是數(shù)據(jù)存在內(nèi)存中
作用:常用來做緩存服務(wù)器、將從數(shù)據(jù)庫查詢的數(shù)據(jù)緩存起來,減少數(shù)據(jù)庫查詢、加快查詢速度。
M腳下留心:數(shù)據(jù)存儲(chǔ)在內(nèi)存中系統(tǒng)重啟則丟失
2、與mysql比較
?共同點(diǎn):都是C/S架構(gòu)(客戶端client/服務(wù)器server)
?不同點(diǎn):mysql存磁盤文件、memcache內(nèi)存
?不同點(diǎn):mysql存儲(chǔ)數(shù)據(jù)得先創(chuàng)建數(shù)據(jù)庫再創(chuàng)建表、memcache直接以鍵值對(duì)形式存儲(chǔ)
鍵key 值value
字串(唯一) 字符串,整數(shù),浮點(diǎn)數(shù),布爾,數(shù)組,對(duì)象,NULL,二進(jìn)制數(shù)據(jù)(圖片,視頻,音頻)
?關(guān)于memcached.exe相關(guān)參數(shù)
-l localhost 服務(wù)器ip地址(默認(rèn)本機(jī))
-p port 端口(11211)
-d install/uninstall/start 管理memcache
-m memory 內(nèi)存大小,默認(rèn)64M
3、操作memcache
增/改鍵(set)
?語法:set 鍵 是否壓縮 緩存時(shí)間 數(shù)據(jù)長(zhǎng)度
?鍵 - 對(duì)打長(zhǎng)度不超過250字符
?是否壓縮 - 1-是,0-否(以空間換時(shí)間)
?緩存時(shí)間 - 0-理論永久,其他-單位秒(注:最大存儲(chǔ)時(shí)間30天)
?數(shù)據(jù)長(zhǎng)度 - 寫數(shù)字,單位字節(jié)(注:回車輸入具體內(nèi)容)
?說明: 鍵存在-則修改,鍵不存在-則創(chuàng)建
獲取鍵值(get)
?語法:get 鍵
添加鍵數(shù)據(jù)(add)
?語法:add 鍵 是否壓縮 緩存時(shí)間/s 數(shù)據(jù)長(zhǎng)度/字節(jié)
?說明:不能添加不能修改
修改鍵數(shù)據(jù)(replace)
?語法:replace 鍵 是否壓縮 緩存時(shí)間/s 數(shù)據(jù)長(zhǎng)度/字節(jié)
?說明:只能修改不能添加
刪除鍵(delete)
?語法:delete 鍵
刪除所有鍵(flush_all)
?語法:flush_all
遞增(incr)和遞減(decr)
?語法:incr 鍵 數(shù)字
?語法:decr 鍵 數(shù)字
?說明:返回增長(zhǎng)后的結(jié)果,鍵必須存在
遞增(incr)和遞減(decr)
?語法:incr 鍵 數(shù)字
?語法:decr 鍵 數(shù)字
?說明:返回增長(zhǎng)后的結(jié)果,鍵必須存在
4、PHP操作Memcached
1、開啟php的php_memcache.dll擴(kuò)展
?步驟1:下載擴(kuò)展,網(wǎng)址:<u>http://pecl.php.net/package/memcache/3.0.8/windows</u>
?步驟2:查看php相關(guān)信息選擇對(duì)應(yīng)的擴(kuò)展庫文件
?步驟3:將擴(kuò)展文件移動(dòng)到對(duì)應(yīng)PHP版本的ext目錄下(extension)
?步驟4:修改php的配置文件(進(jìn)php.ini配(extension_dir和extension=php_memcache.dll))
?步驟5:重啟apache并通過phpinfo驗(yàn)證是否開啟成功
2、操作
官方手冊(cè):
<u>https://secure.php.net/manual/zh/memcache.set.php</u>
常用命令:
連接服務(wù)器: $mem->connect(服務(wù)ip地址,端口)
關(guān)閉服務(wù)器: $mem->close();
設(shè)置數(shù)據(jù): $mem->set(鍵,值 [,是否壓縮,緩存時(shí)間])
獲取數(shù)據(jù): $mem->get(鍵)
遞增: $mem->incrment(鍵,數(shù)字);
遞減: $mem->decrment(鍵,數(shù)字);
3、Memcache能存儲(chǔ)的數(shù)據(jù)類型
①基本類型:字符串、布爾、整型、浮點(diǎn)型
②復(fù)合類型:數(shù)組、對(duì)象
(注:只能存儲(chǔ)基本數(shù)據(jù)類型,但是數(shù)組/對(duì)象通過序列化也可以存儲(chǔ),在調(diào)用set和get方法時(shí),會(huì)檢測(cè)數(shù)據(jù)是否是數(shù)組或?qū)ο?,是則自動(dòng)序列化或反序列化)
③特殊類型:null、資源(null輸出為int(0),資源可以插入,但是讀取失敗)
4、Memcache的相關(guān)算法
1、惰性過期機(jī)制(lazy expiration)
?說明:memcached內(nèi)部不會(huì)監(jiān)視記錄是否過期,而是在get時(shí)查看記錄的時(shí)間戳,檢查記錄是否過期。這種技術(shù)被稱為惰性過期
?好處:減少監(jiān)控過期產(chǎn)生的開銷
2、最近最少使用算法(LRU:Least Recently Used)
緩存空間已滿,采用LRU策略,
將使用頻率最低數(shù)據(jù)進(jìn)行刪除
5、Memcache常見問題
a、單個(gè)key鍵名的最大長(zhǎng)度是多少?
答:最大長(zhǎng)度是250個(gè)字符
b、每個(gè)item選項(xiàng)其最大可以存儲(chǔ)多少M(fèi)的數(shù)據(jù)
答:?jiǎn)蝹€(gè)鍵最大存儲(chǔ)數(shù)據(jù)為1M
c、最大存儲(chǔ)時(shí)間(30天)
6、memcache里面適合存儲(chǔ)哪些數(shù)據(jù)
?明確使用場(chǎng)景:緩存服務(wù)器
?適合存儲(chǔ)哪些數(shù)據(jù):
訪問比較頻繁的數(shù)據(jù),安全性差的數(shù)據(jù),丟失無所謂的數(shù)據(jù)。
數(shù)據(jù)更新,比較頻繁的數(shù)據(jù),比如用戶的在線狀態(tài)。
數(shù)據(jù)的單個(gè)鍵值不能太大,不要超過1Mb數(shù)據(jù)。
7、分布式Memcache服務(wù)器
1)分布式服務(wù)器原理
集群概念:多臺(tái)服務(wù)器實(shí)現(xiàn)相同的業(yè)務(wù)
分布式概念:多臺(tái)服務(wù)器實(shí)現(xiàn)不同的業(yè)務(wù)

2)使用PHP實(shí)現(xiàn)分布式Memcache

8、Session入Memcache緩存
?語法:
session.save_handler = files/memcache/redis
session.save_path= 磁盤路徑/寫tcp協(xié)議/寫tcp協(xié)議
"tcp://服務(wù)器ip地址:端口,...,tcp://服務(wù)器ip地址:端口"
方法1:永久,修改php配置文件(php.ini)
?步驟

?代碼
<?php
#文件存儲(chǔ):會(huì)判斷是否生成和session_id同名的文件(有-則讀取文件,沒有-則創(chuàng)建)
#內(nèi)存存儲(chǔ):將session_id作為鍵(鍵已存在-則獲取數(shù)據(jù)保存到$_SESSION數(shù)組中,不存在-則創(chuàng)建空數(shù)據(jù))
session_start();
$_SESSION['php13_name'] = '蒼蒼';
$_SESSION['age'] = 18;
print_r($_SESSION);
echo '<hr />';
echo session_id();
方法2:臨時(shí),在php中使用 ini_set函數(shù)

?步驟:打開php文件通過ini_set函數(shù)臨時(shí)設(shè)置session的存儲(chǔ)方式

?代碼
<?php
#通過ini_set函數(shù)臨時(shí)更改配置文件
ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', 'tcp://127.0.0.1:11211,tcp://192.168.43.37:11211');
#session_start作用
#文件存儲(chǔ):會(huì)判斷是否生成和session_id同名的文件(沒有-則創(chuàng)建,有-則讀取文件)
#內(nèi)存存儲(chǔ):會(huì)判斷是否生成和session_id同名的鍵 (沒有-則創(chuàng)建,有-則讀取文件)
session_start();
$_SESSION['php13_name'] = 'abc';
$_SESSION['age'] = 18;
print_r($_SESSION);
echo '<hr />';
echo session_id();
方法3:通過設(shè)置用戶自定義會(huì)話存儲(chǔ)函數(shù)(session_set_save_handler)
?語法:session_set_save_handler(開啟session機(jī)制函數(shù),關(guān)閉session機(jī)制函數(shù),
讀取session數(shù)據(jù)函數(shù),寫入session函數(shù),銷毀session函數(shù),后手過期session函數(shù))
?作用:自定義session會(huì)話處理方式,交給指定函數(shù)處理
自 PHP 5.4 開始,可以使用SessionHandlerInterface接口實(shí)現(xiàn)(注:接口里面都是抽象方法)
抽象類:有抽象方法的類就是抽象類
抽象方法:用關(guān)鍵詞abstract并且沒有函數(shù)體的方法
接口:特殊的抽象類(注:因?yàn)槔锩娴姆椒ǘ际浅橄蠓椒ǎ?/code>
<?php
class MemcacheSessionHandler implements \SessionHandlerInterface
{
private $memcache;
//自定義用戶更改session的處理方式
public static function start()
{
#更改session的存儲(chǔ)方式
session_set_save_handler(new self, true);
#開啟會(huì)發(fā),會(huì)觸發(fā)open方法
session_start();
}
public function open($savePath, $sessionName) {
$this->memcache = new Memcache;
$this->memcache->addServer('127.0.0.1', 11211);
return true;
}
public function close() {
return true;
}
public function read($sessionId) {
return $this->memcache->get( $sessionId ) ? : '';
}
public function write($sessionId, $data) {
return $this->memcache->set($sessionId, $data);
}
public function destroy( $sessionId ) {
//$this->memcache->delete($sessionId)
return true;
}
public function gc( $lifetime ) {
return true;
}
}
MemcacheSessionHandler::start();
$_SESSION['aa'] = 123;
$_SESSION['bb'] = 456;
echo session_id();
?>
實(shí)現(xiàn)session共享
步驟一
配置兩個(gè)本地虛擬主機(jī)
步驟二
在配置的站點(diǎn)下分別創(chuàng)建test.php文件,并分別輸入以下代碼
<?php #開啟SESSION共享,允許跨域訪問SESSION ini_set('session.cookie_domain','test.com'); #通過php的ini_set函數(shù)臨時(shí)更改php的配置文件 ini_set('session.save_handler','memcache'); ini_set('session.save_path','tcp://127.0.0.1:11211'); session_start(); $_SESSION['userinfo'] = array( 'id' => 1, 'username' => '小澤' ); echo session_id() . '<hr />'; print_r($_SESSION);<?php #開啟SESSION共享,允許跨域訪問SESSION ini_set('session.cookie_domain','test.com'); #通過php的ini_set函數(shù)臨時(shí)更改php的配置文件 ini_set('session.save_handler','memcache'); ini_set('session.save_path','tcp://127.0.0.1:11211'); session_start(); echo session_id() . '<hr />'; print_r($_SESSION);
實(shí)現(xiàn)單點(diǎn)登陸
概念
單點(diǎn)登錄:名詞,指a網(wǎng)站登錄后,b網(wǎng)站同步登錄
案例
百度搜索登錄成功,百度網(wǎng)盤,百度等網(wǎng)站同步登錄
流程
步驟一:配置兩個(gè)本地虛擬主機(jī)
步驟二:分別把項(xiàng)目復(fù)制到配置后的本地虛擬主機(jī)
步驟三:
圖片6.png
圖片7.png
圖片8.png
記錄訪問者信息
需求:高并發(fā)如何避免重復(fù)記錄用戶ip地址
分解1:連接數(shù)據(jù)庫插入數(shù)據(jù)(瑕疵:用戶量大出現(xiàn)重復(fù)IP)
<?php //1.創(chuàng)建mem對(duì)象 $mem = new Memcache; //2.連接服務(wù)器 $mem->connect('127.0.0.1', 11211); $ip = '192.168.9.'.rand(0, 10); //3.創(chuàng)建用戶信息數(shù)據(jù)結(jié)構(gòu) $person_info = [ 'ip' => $ip, 'page'=> 'http://baidu.com', 'referrer'=> 'http://baidu.com', ]; //4.判斷是否記錄IP:已記錄-不管,未記錄-入庫 if( !$mem->get($ip) ) { //入庫 $filename = $ip . '_' . time(); $mem->add($ip, $person_info); file_put_contents('./ip/'.$filename, 1); }分解2:加鎖限制(排隊(duì)操作避免出現(xiàn)重復(fù)ip插入)
<?php //1.創(chuàng)建mem對(duì)象 $mem = new Memcache; //2.連接服務(wù)器 $mem->connect('127.0.0.1', 11211); $ip = '192.168.1.'.rand(0, 10); //3.創(chuàng)建用戶信息數(shù)據(jù)結(jié)構(gòu) $person_info = [ 'ip' => $ip, 'page'=> 'http://baidu.com', 'referrer'=> 'http://baidu.com', ]; //加鎖不成功的,進(jìn)行排隊(duì)等待(注:第一個(gè)用戶進(jìn)來未處理完,后面的用戶循環(huán)等待) while ( !$mem->add('lock', 'lock', 0, 0) ){ //進(jìn)行休息 usleep(1000); //usleep單位是微秒,1秒 = 1000毫秒 ,1毫秒 = 1000微秒 } //4.判斷是否記錄IP:已記錄-不管,未記錄-入庫 if( !$mem->get($ip) ) { //入庫 $filename = $ip . '_' . time(); $mem->add($ip, $person_info); //因?yàn)閙emcache不能查看所有鍵,所以通過創(chuàng)建文件方式檢測(cè)是否有重復(fù) file_put_contents('./'.$filename, 1); } //5.刪除鎖(注:操作完畢后,釋放鎖,讓后面用戶進(jìn)來) $mem->delete('lock');測(cè)試
圖片9.png



