Memcache 基礎(chǔ)筆記

(一):基礎(chǔ)概念

  1. memcache是什么?

Memcache 是一個高性能的分布式內(nèi)存對象緩存系統(tǒng),用于動態(tài)Web應用以減輕數(shù)據(jù)庫負載。它通過在內(nèi)存中緩存數(shù)據(jù)和對象來減少讀取數(shù)據(jù)庫的次數(shù),從而提高動態(tài)、數(shù)據(jù)庫驅(qū)動網(wǎng)站的速度。Memcached基于一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,并通過memcached協(xié)議與守護進程通信。

  1. memcache的工作原理?

theory.jpg

RDBMS :關(guān)系數(shù)據(jù)庫管理系統(tǒng)(Relational Database Management System)。
memcached:
php有兩個memcache客戶端,一個是php memcached, 一個是php memcache??蛻舳说膍emcached
相當于memcache的Plus版,實際在操作上和memcache幾乎類似,當然作為memcache的升級版,memcached在穩(wěn)定性和速度上更好,php操作memcached提供了更多的方法。在php官方的手冊中分別搜索memcached和memcache 能發(fā)現(xiàn)他們的異同點。

  1. memcache的主要特點?
  1. 協(xié)議簡單 基于C/S架構(gòu)(Client/Server)
    2.基于libevent的事件處理
    3.內(nèi)置內(nèi)存存儲方式
    4.互不通信的分布式內(nèi)純緩存服務器
  1. memcache的使用場景?

1.因為memcache是不能持久化數(shù)據(jù)的,一旦memcache宕機或者重啟之類的,原來存入的數(shù)據(jù)都會丟失,所以對一些數(shù)據(jù)的安全性要求不高的可以考慮使用memcache

2.因為memcache存儲的單個對象的最大是1M所以,當有一些體積相對較小,但是頻繁被訪問的數(shù)據(jù)時,可以是考慮memcache

3.當一個系統(tǒng)有大量的動態(tài)內(nèi)容時,存在大量的讀取數(shù)據(jù)庫的操作,造成數(shù)據(jù)庫負載過高時,可以考慮使用memcache做緩存來緩解數(shù)據(jù)庫壓力

4.多臺服務器需要共享某些數(shù)據(jù)的時候,可以考慮使用memcache,例如:session共享

5.小結(jié):memcache基本就是做緩存用的,為的是緩解服務器的壓力,提高系統(tǒng)悉能

(二) 安裝memcache
1.準備工具

1.1 : Xshell
1.2 :一個可用的LAMP/LNMP環(huán)境
1.3:我測試的是LAMP CentOS7+Apache(2.4.6)+MySql(5.6.35)+PHP(5.416)

2.安裝基本流程

2.1 安裝memcached的服務器端
一般在服務器端安裝memcached得首先安裝libevent庫才行,但是在CentSO上使用yum方式安裝可以解決這種依賴

yum install memcached


2.2 安裝php的memcache擴展

yum install php-memcache

2.3 重啟一下服務器

3.memcache安裝后測試

3.1 開啟memcache服務器端

2017-03.png

3.1.1memcached指令參數(shù)基礎(chǔ)解釋

//在memcache的服務器端,我們可以通過memcached -help查該指令有那些參數(shù),我們只解釋下他的基礎(chǔ)參數(shù)的意思
//例如 指令 /usr/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root
-d 表示是守護進程
-l 連接的ip地址
-p memcached服務器監(jiān)聽的端口
-m 分配給memcached服務的最大的內(nèi)存,單位是MB,默認是64M
-u 以誰的身份運行,示例中的是root用戶運行,實際中少這么用,權(quán)限太高了
-c 同時最大的連接數(shù) 默認是1024
-n 最小分配空間 key+value+flags 默認是48

3.2 查看php的memcache安裝是否成功
3.2.1 進入你應用的根目錄 例如:/var/www/html/ 下
3.2.2. 新建一個文件 vim phpinfo.php

<?php
  phpinfo();
?>

3.2.3 使用瀏覽器訪問該文件 如果出現(xiàn)如下信息

2017-03.png

3.2.4 表示php的memcache擴展開啟成功了
3.2.5 注意: 當你的memcache都安裝好了,在服務器上寫的php腳本,通過客戶端瀏覽器訪問卻沒有什么內(nèi)容返回的情況,我們首先查看一下Linux上的訪問日志和錯誤日志,我是的LAMP環(huán)境,訪問日志和錯誤日志都是放在了默認的位置 /var/log/httpd 目錄下.打開access_log
access_log.png

狀態(tài)碼是200 表示訪問是ok的
我們再看錯誤日志error_log


error.png

我們看到最近的一次錯誤是許可被拒絕了
基本分析是可能和權(quán)限,安全保護有關(guān)(SELinux,防火墻等)
此處我臨時關(guān)閉SElinux即可 指令如下

setenforce 0  

(三):PHP操作memcache

  1. 簡單的講memcache是php對內(nèi)存操作的一種媒介
  1. 既然是對內(nèi)存的操作,不能免俗的就要從增刪改查四部曲開始
  2. php操作memcache,就和操作一個普通的類是一樣的

php連接memcache服務器

  1. 我們進入項目的根目錄(例如:/var/www/html/)新建一個文件con.php
<?php

//新建一個memcache對象$mem
$mem = new Memcache;
//連接memcache服務器
//connect("memcache服務器地址","memcache服務器使用的端口號")
$mem->connect("127.0.0.1",11211);
//查看memcache服務器的統(tǒng)計狀態(tài)
print_r($mem->getStats());

```php
<?php

//新建一個memcache對象$mem
$mem = new Memcache;
//向連接池中添加一個memcache服務器
/*
*使用addServer方法也可以連接memcache服務器上,引用php手冊上的說法是:
*"使用這個方法的時候網(wǎng)絡(luò)連接并不會立刻建立,而是直到真正使用的時候才建立。 因此在加
*入大量服務器到連接池中時也是沒有開銷的,因為它們可能并不會被使用"
*/
$mem->addServer("127.0.0.1",11211);
//查看memcache服務器的統(tǒng)計狀態(tài)
print_r($mem->getStats());

  1. 通過瀏覽器訪問該文件


    2017-03.png

    2.1 返回的統(tǒng)計信息是一個數(shù)組,我們大概了解一下返回的統(tǒng)計信息的意思

    [pid] => 37344   服務器的進程id
    [uptime] => 21672     服務從啟動到當前所經(jīng)過的時間,單位是秒
    [time] => 1489951190    服務器所在主機當前系統(tǒng)的時間,單位是秒
    [version] => 1.4.15    memcached的版本號
    [libevent] => 2.0.21-stable
    [pointer_size] => 64     服務器所在主機操作系統(tǒng)的指針大小
    [rusage_user] => 1.174806    
    [rusage_system] => 0.931503
    [curr_connections] => 8     表示當前系統(tǒng)打開的連接數(shù)
    [total_connections] => 33   表示從memcached服務啟動到當前時間,系統(tǒng)打開過的連接的總數(shù)
    [connection_structures] => 9   
    [reserved_fds] => 20
    [cmd_get] => 14   累積獲取數(shù)據(jù)的數(shù)量
    [cmd_set] => 1     累積保存數(shù)據(jù)的數(shù)量
    [cmd_flush] => 0
    [cmd_touch] => 0
    [get_hits] => 12    表示獲取數(shù)據(jù)成功的次數(shù)
    [get_misses] => 2  表示獲取數(shù)據(jù)失敗的次數(shù)
    [delete_misses] => 0 表示刪除數(shù)據(jù)失敗的次數(shù)
    [delete_hits] => 0      表示刪除數(shù)據(jù)命中的次數(shù)
    [incr_misses] => 0   表示增加一個元素失敗的次數(shù)
    [incr_hits] => 0        表示增加一個元素命中的次數(shù)
    [decr_misses] => 0   表示減少一個元素失敗的次數(shù)
    [decr_hits] => 0        表示減少一個元素命中的次數(shù)
    [cas_misses] => 0
    [cas_hits] => 0
    [cas_badval] => 0
    [touch_hits] => 0
    [touch_misses] => 0
    [auth_cmds] => 0
    [auth_errors] => 0
    [bytes_read] => 270    memcached服務器從網(wǎng)絡(luò)讀取的總的字節(jié)數(shù)
    [bytes_written] => 12788    memcached服務器發(fā)送到網(wǎng)絡(luò)的總的字節(jié)數(shù)。
    [limit_maxbytes] => 157286400  memcached服務緩存允許使用的最大字節(jié)數(shù)
    [accepting_conns] => 1
    [listen_disabled_num] => 0
    [threads] => 4    被請求的工作線程的總數(shù)量
    [conn_yields] => 0
    [hash_power_level] => 16
    [hash_bytes] => 524288
    [hash_is_expanding] => 0
    [bytes] => 0
    [curr_items] => 0
    [total_items] => 1
    [expired_unfetched] => 0
    [evicted_unfetched] => 0
    [evictions] => 0
    [reclaimed] => 0

2.2 我們看到使用php操作memcache,首先是實例化一個memcache的對象,然后建立一個memcache服務端的連接.

php操作memcache

添加數(shù)據(jù)###

1.1 例如文件位置 : /var/www/html/con.php

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
//memcache緩存數(shù)據(jù)的結(jié)構(gòu)是基于 key -> value (鍵值)的
//add('鍵名','值','是否壓縮','多少秒后失效')
$mem->add('one','故人西辭黃鶴樓',0,60);  

1.2 我們再用一個文件驗證是否存入 文件位置:/var/www/html/test.php

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
echo date("Y-m-d H:i:s");
echo $mem->get('one');  

1.3 通過瀏覽器訪問執(zhí)行,結(jié)果如下

2017-03-25.png

超過設(shè)定的時間后就失效了

2017-03-25.png

1.4 我們也可以使用set('鍵名','值',是否壓縮,失效時間)來添加數(shù)據(jù)

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
//set('鍵名','值','是否壓縮','多少秒后失效')
$mem->add('one','故人西辭黃鶴樓',0,60);  
$mem->set('one','煙花三月下?lián)P州',0,60);  

1.5 我們再獲取一下這個值

2017-03-25.png

1.6 add()和set()方法的區(qū)別: add()添加一個值,如果這個值存在,則添加失敗
set()添加一個值,如果這個值存在,則替換掉原有的

刪除數(shù)據(jù)###

2.1 修改 /var/www/html/test.php 文件

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
echo date("Y-m-d H:i:s");
echo $mem->get('one')."<br />";
$mem->delete('one');
$one = $mem->get('one');
if(empty($one))
{
        echo "數(shù)據(jù)已經(jīng)刪除";
}

2.2 執(zhí)行該文件后的效果

2017-03-25.png
2017-03-25.png

2.3 使用flush()方法清除已經(jīng)存儲的所有數(shù)據(jù)
2.3.1 修改 /var/www/html/con.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->addServer("127.0.0.1",11211);
$mem->add('one','故人西辭黃鶴樓',false,0);
$mem->set('two','煙花三月下?lián)P州',0,0);
$mem->set('three','孤帆遠影碧空盡',0,0);
$mem->set('four','唯見長江天際流',0,0);

2.3.2 修改 /var/www/html/test.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

2.3.3 結(jié)果如下

2017-03-25.png

2.3.4 再修改 /var/www/html/test.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->flush();
$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

2.3.5 結(jié)果如下

2017-03-25.png

修改數(shù)據(jù)###

3.1 php修改memcache的數(shù)據(jù)一般有兩個方法set() 和replace()
3.1.1再修改 /var/www/html/test.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
//replace('被更新的鍵','新值','是否壓縮','過期時間')
$flag = $mem->replace('four','歡迎來到揚州',0,0);
if($flag === FALSE)
{
   echo "更新數(shù)據(jù)失敗";
}else{
  echo "更新數(shù)據(jù)成功";
}


$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

3.1.2 通過瀏覽器訪問test.php文件后的結(jié)果如下:

2017-03-25.png

3.1.3 我們再次修改 /var/www/html/test.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
//更新一個不存在的鍵 例如:five
$flag = $mem->replace('five','火星歡迎您',0,0);
if($flag === FALSE)
{
   echo "更新數(shù)據(jù)失敗";
}else{
  echo "更新數(shù)據(jù)成功";
}


$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

3.1.4 執(zhí)行后結(jié)果如下:

2017-03-25.png

3.2 set()和replace是區(qū)別是:

當數(shù)據(jù)存在的時候,set()方法和replace()方法都能更新(修改),作用相同
當數(shù)據(jù)不存在的時候,set()方法會添加這樣一條數(shù)據(jù),replace()方法會返回FALSE

查詢數(shù)據(jù)###

//memcache有關(guān)查詢的幾個方法
get()獲取memcache上key的值,前面有示例,既能是單一的key值也可以是一組key的數(shù)組
getStatus()獲取當前memcache服務器的統(tǒng)計信息
getServerStatus('服務器地址','端口號')用于獲取一個服務器的在線/離線狀態(tài),返回一個服務器的狀態(tài),0表示服務器離線,非0表示在線。 
getExtendedStats()緩存服務器池中所有服務器統(tǒng)計信息,如果緩存池中有多臺memcache服務器,就將這些服務器的信息以二維數(shù)組的形式都返回
//例如,我向連接池中添加兩臺memcache服務器:
$mem->addServer("127.0.0.1",11211);
$mem->addServer("127.0.0.1",11212);
$stats = $mem->getExtendedStats();
print_r($stats);
//返回的信息格式將會是:
Array
(
        [127.0.0.1:11211]=>Array
          (
              .........
          )
        [127.0.0.1:11212]=>Array
          (
              .........
          )
)

增加或者減少一個元素的值###

increment('要增加值的元素的鍵','增加的量');
decrement('要減少值的元素的鍵','減少的量');

我們修改 /var/www/html/con.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->set('num',4,0,0);

我們修改 /var/www/html/test.php 文件并執(zhí)行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->increment('num',3);
echo $mem->get('num');

結(jié)果如下:

2017-03-26.png

鍵 , 壓縮 ,過期時間,緩存過期,分配內(nèi)存耗盡

  1. 鍵(key) : 因為memcache是基于鍵和值的存儲方式,memcache中鍵的命名很可以很隨意,但是我們還是推薦比較有意義鍵名,key的最大長度是250個字節(jié)
  2. 壓縮 :因為memcache存儲單個item最大數(shù)據(jù)是在1MB內(nèi).所以當我們進行存儲,會考慮是否開啟壓縮
//e.g:
bool memcache::set(key,value,是否壓縮[0/1],失效時間);

2.1 壓縮會節(jié)省更多的內(nèi)存空間,但是也會帶來額外的CPU開銷,運行速度相對會慢
2.2 未壓縮,占用的內(nèi)存空間小,但是運行速度快
2.3memcache 支持的最大存儲對象是1M,所以在將單個大于1M的內(nèi)容存儲到memcache的時候需要開壓縮

  1. 有效時間:
memcache::set("key","value",是否壓縮,有效時間);
memcache::add("key","value",是否要鎖,有效時間);

memcache的有效時間單位是秒(s),手冊的解釋是"當前寫入緩存的數(shù)據(jù)的失效時間",設(shè)置有效時間有兩種寫法,并且有區(qū)別

//這種設(shè)置的有效時間的最大值是2592000秒既30天,但是要是有效時間大于30天怎么辦?
memcache::set("home","love",0,2592000);
//這樣這種時間戳的方式可以設(shè)置大于30天的有效時間
memcache::set("hope","love",0,time()+2592001);
  1. 當我們設(shè)置的一個緩存超過的有效期,那么這個緩存就"過期"了,不能再使用了,那么些過期的緩存數(shù)據(jù)會被memcache清除掉嗎?會的,memcache清除過期的數(shù)據(jù)是采用的一種"懶惰"的機制,過期后不會立刻清除掉,而是當再次通過get()方式獲取緩存時刪除過期的數(shù)據(jù)
  2. 我們再開啟memcache的時候曾經(jīng)通過-m這個參數(shù)給開啟的這個memcache分配一定內(nèi)存大小,可是當這個分配的內(nèi)存被使用殆盡的時候會怎么樣呢?當分配的內(nèi)存用盡,此時再向memcache中存入數(shù)據(jù),那么memcache就會將最近不常用的數(shù)據(jù)刪除掉,這種機制就是LRU(least recently used )

php操作memcache 基礎(chǔ)示例

我們模擬一個場景,我現(xiàn)在的user表(僅三個字段)中存在52W條數(shù)據(jù),我要取出最新的2萬條數(shù)據(jù).

分析:第一次訪問,memcache中沒有這些數(shù)據(jù),我們就從DB中取得這些數(shù)據(jù),并且將這些數(shù)據(jù)存入memcache中,當需要訪問相同的數(shù)據(jù)的時候,直接從memcache中提供這些數(shù)據(jù)

  1. 準備數(shù)據(jù)


    mysql.png
  2. 編寫基本腳本(php)文件
    我們在根目錄下新建一個文件 vim /var/www/html/test2.php
<?php
$starttime = microtime(true);
echo $starttime;
echo "<hr />";
function getmemcache($sql,Memcache $memacche)
{
$key  = md5($sql);
      $data = $memcache->get($key);
       if(!$data)
      {
         try{
            $pdo = new PDO("mysql:host=localhost;dbname=test",'root','123456');
            }catch(PDOException $e){
              die($e->getMessage());
            }
            $stmt = $pdo->prepare($sql);
            $stmt->execute();
            $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $memcache->set($key,$data,MEMCACHE_COMPRESSED, 0);
  }

return $data;
}
$mem = new Memcache();
$mem->connect('127.0.0.1',11211);
$sql = "select * from user order by id desc limit 0,20000";
$data = getmemcache($sql,$mem);
echo "<pre>";
print_r($data);
$mem->close();
$endtime = microtime(true);
echo "<hr />";
echo $endtime.'<br />';
echo '執(zhí)行時間'.round($endtime-$starttime,3).'秒';


3.通過客戶端瀏覽器第一次訪問test2.php文件

one.png

4.再次訪問test2.php文件

one.png

5.我們可以看到第二訪問是從memcache中獲取測數(shù)據(jù),應為我在test2.php文件中有2W條數(shù)據(jù)輸出,感覺還是耗時很多,我們將數(shù)據(jù)輸出那段代碼注釋掉,再次并且清空一下memcache緩存,再次訪問test2.php文件

three.png
four.png

學習本是一個自我修正的過程,總結(jié)中有許多的不足,萬望不吝賜教

[參考資料]:
1.http://php.net/manual/zh/class.memcache.php php手冊memcache部分
2.http://www.w3cschool.cn/memcached/ W3Cschool memcached部分
3.http://blog.csdn.net/heiyeshuwu/article/details/3950532 Memcached原理和使用詳情
[拓展資料]:

  1. 《大型網(wǎng)站技術(shù)架構(gòu)》李智慧著
  2. http://www.songyawei.cn/content/5008?utm_source=tuicool&utm_medium=referral memcache和memcached的區(qū)別
  3. http://www.cnblogs.com/caoxiaojian/p/5715568.html Memcache介紹與應用場景
  4. http://yw666.blog.51cto.com/11977292/1910163?utm_source=tuicool&utm_medium=referral memcache緩存服務器
  5. http://www.cnblogs.com/crazyacking/p/5793239.html 走進緩存的世界
  6. http://www.imooc.com/learn/527 近距離探索memcache緩存
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容