Memcached 緩存技術

基本介紹

memcached是一種緩存技術,他可以把你的數據放入內存,從而通過內存訪問提速,因為內存是最快的,memcached的主要目的是提速。

在memcached中維護了一張大的hashtable表,該表在內存中,表的結構是key和value

memcached的key一般是字串,不能重復

memcached的value可以放入(字符串,數值,數組,對象,布爾,二進制數據,圖片和視頻)

面對一個請求,有如下選擇:

  1. 可以直接查詢數據庫(慢)

  2. 使用真靜態(一般)

  3. 直接操作內存(快)

安裝使用

  1. 下載 memcached

  2. 安裝
    進入cmd,切換到memcached.exe所在目錄,memcached.exe -d install

  3. 啟動 memcached
    第一種:可以到服務點擊啟動
    第二種:命令行,memcached.exe -d start

如果你在win7下啟動不成功,則可以使用如下方法:
????memcached.exe -p 端口號(不要關閉控制臺)

端口號的范圍是0 ~ 65535,因為端口號是用兩個字節來表示的
有名端口:0 ~ 1024端口,已經有程序使用了,一般不要占用
apache 80 mysql 3306 ftp 21 ssh 22 oracle 1521 smtp 25
使用netstat -an 如果看到11211端口在監聽,說明啟動ok

netstat -anb 是哪個程序監聽,這個指令還可以看到有哪些用戶連接到我們的服務器

如果沒有安裝好,原因可能是

a. 如果是win7,win7對安全性要求較高,所以必須以administrator身份安裝,須切換成administrator去安裝,再啟動。

b. 你的memcached.exe目錄有中文,或特殊字符,保證路徑沒有中文或特殊字符即可

Telnet操作Memcached

  1. 登錄到telnet連接到memcached服務

    telnet 127.0.0.1 11211

    如果你們不能使用telnet是因為系統不存在telnet.exe,就可以到其他機器上拷貝telnet.exe放在C:\windows\system32即可

  2. 增加語法

    add key 名 0 存放時間(秒) 數據大小(字符)

     add key1 0 30
    
  3. 獲取語法

    get key 值

     get key1
    
  4. 修改語法

    set key 名 0 存放時間 數據大小 (如果key不存在,相當于添加一個新的,如果存在,則相當與替換)

     set key1 0 45 5
    

    replace key 名 存放時間 數據大小 (如果key不存在,則失敗,這個指令要求key必須存在)

     replace key1 0 40 5
    
  5. 刪除語法

    delete key 名

     delete key100
    

    flush_all(可以統一把數據清空)

  6. 查看狀態

    stats
    

    這里可以根據cmd_hits/cmd_gets計算出命中率,越高越好。

PHP程序操作Memcached

  1. 把php_memcache.dll文件拷貝到php的ext下
    不同版本的php所使用的php_memcache.dll的版本不一樣

  2. 修改php.ini文件,加載php_memcache.dll(該文件就是封裝了一堆函數)
    extension=php_memcache.dll

  3. 重新啟動apache

  4. 編寫程序來完成curd操作

使用php memcache擴展操作memcached服務實例

<?php
   //創建一個mem對象實例
    $mem = new Memcache;
    if(!$mem->connect("127.0.0.1",11211)) {
       die('連接失敗!');
    }

   //1.增加字串
   $mem->add("key1", "北京", MEMCACHE_COMPRESSED, 60);
   //2.添加數值
   $mem->set("key1", 100, MEMCACHE_COMPRESSED, 60);
   //3.添加數組
   //在添加數組時,根據需要,需要序列化再放入也可以 
   //serialize() <=> unserialize(),根據需要,也可以json_encode() <=> json_decode()再放入   
   $arr = array("北京", "天津");
   $mem->set("key1", $arr, MEMCACHE_COMPRESSED, 60);
   //4. 添加對象
   class Dog {
        public $name;
        public $age;
          public function __construct($name, $age) {
            $this->name=$name;
            $this->age=$age;
        }
   }        
   $dog1 = new Dog("小狗", 50);
   $mem->set("key1", $dog1, MEMCACHE_COMPRESSED, 60);

   //在另外文件中取出對象時,有一個注意的地方,對應5.2這個版本會提示錯誤
   //對于php5.3這個版本會提示incomplete信息,解決方法是聲明類定義即可
   class Dog {
        public $name;
        public $age;
        public function __construct($name, $age) {
            $this->name=$name;
            $this->age=$age;
        }
    }       
    $dog = $mem->get('key1');
    var_dump($dog);

   //5.添加null
   $mem->set("key1", null, MEMCACHE_COMPRESSED, 50);

   //6. 添加bool
   $mem->set("key1", false, MEMCACHE_COMPRESSED, 50);

   //7. 資源類型放入
   $con = mysql_connect("127.0.0.1", "root", "root");
   if(!con) {
         die("連接數據庫失敗");
   }
   if($mem->set("key1", false, MEMCACHE_COMPRESSED, 60)){
     echo "添加資源ok";
   }

   //查詢
   $val = $mem->get('key1');
   echo '<br/>val='.$val;   

   //修改
   //可以使用replace()
   if($mem->replace("key1", "hello", MEMCACHE_COMPRESSED, 60)){
       echo "replace ok!";
   }

    //刪除
    if($mem->delete("key1")){
       echo "delete ok!";   
    }
?>

對象序列化和json編碼實例

<?php
    class Dog {
        public $name;
        public $age;
        public function __construct($name, $age) {
            $this->name=$name;
            $this->age=$age;
        }
    }       

    $dog2 = new Dog("小黃", 40);
    file_puts_contents("d:/my.log", serialize($dog2));
    echo "save ok!";    
    $dog = unserialize(file_get_contents("d:/my.log"));
    var_dump($dog);

    $arr = array("北京", "天津");
    file_put_contents("d:/my.log", json_encode($arr));
    echo "save ok!";
    $arr = json_decode(file_get_contents("d:/my.log"));
    var_dump($arr); 
?>

serialize()側重于數據的保存和傳輸,會保存數據類型,json_encode()側重于數據的處理,不會保存數據類型

在我們添加數據的時候,如果把expire設為0表示永不過期,只要memcache不重新啟動,就永遠在memcache中

expire直接給的秒數,則最大30 * 3600 * 24

如果希望時間超過30天,則time()+30 * 3600 * 24

使用PHP socket擴展操作memcached服務實例

如果管理員不讓我們去加載memcache.dll文件,我們可以直接通過源碼操作。這里我們要有一個使用php socket擴展編寫的memcache類memcached-client.php

<?php
    require_once("memcached-client.php");
    $mc = new memcached(array(
        'servers' => array("127.0.0.1:11211"),
        'debug'   => false,
        'compress_threshold' => 10240,
        'persistant' => true));
    $mc->add("key1", arrray('some', 'array'));

    $val = $mc->get('key1');
     var_dump($val);    

    $mc->set("key1", "北京");
    $val = $mc->get("key1");
     var_dump($val);

    $mc->delete("key1");
    $val = $mc->get("key1");
     var_dump($val);
?>

Memcached的深入理解

1.基于c/s架構,協議簡單

c/s架構,此時memcached為服務端,我們可以使用php,c/c++等程序連接memcached服務器

memcached的服務器客戶端通信并不使用xml等格式,而使用簡單的基于文本的協議。因此,功過

telnet也能在memcached上保存數據,取得數據。

2.基于libevent的事件處理

libevent是一套跨平臺的事件處理接口的封裝,能夠兼容包括這些操作系統windows/linux/bsd/solaris等操作系統的事件處理

Memcached使用libevent來進行網絡并發連接的處理,能夠保持在很大并發情況下,仍舊能夠保持迅速的響應能力

3.內置內存存儲方式

為了提高性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中,由于數據僅存在于內存中,因此重啟memcached和重啟操作系統會導致全部數據消失。

另外,內部容量達到指定值之后,就基于LRU(Least Recent Used)算法自動刪除不使用的緩存。memcached本身是為了緩存而設計的服務器,因此并沒有過多考慮數據的永久性問題。

4.基于客戶端的分布式

memcached盡管是"分布式"緩存服務器,當時服務器并沒有分布式功能,各個memcached不會互相通信以共享信息。那么,怎樣進行分布式完全取決于客戶端的實現

分布式存入數據代碼實例

<?php
    //我的電腦上有兩個memcached服務
    $mem = new Memcache();
    $mem->addServer("127.0.0.1", 11211);
    $mem->addServer("127.0.0.1", 9999);
    //這里注意把key1放入11211端口還是9999端口是由對象本身維護
    if($mem->add("key1", "hello", MEMCACHE_COMPRESSED, 300)){
         echo "add ok!";
    }
    if($mem->add("key2", "hello", MEMCACHE_COMPRESSED, 300)){
         echo "add ok!";
    } 
    if($mem->add("key3", "hello", MEMCACHE_COMPRESSED, 300)){
         echo "add ok!";
    }
?>

分布式取出數據代碼實例

<?php
    //如何從多個memcached服務中取出key
    $mem = new Memcache;
    $mem->addServer("127.0.0.1", 11211);
    $mem->addServer("127.0.0.1", 9999);
    //如何取出是由對象本身維護的
    $val = $mem->get("key1");
    echo "程序中取出分布的值 =".$val;
?>

總結

1.memcached服務的數據不同步,數據是分布的

2.把什么數據放入哪個memcached是由客戶端的memcache對象決定的

3.當執行addServer的時候,并不是立即去連接memcached服務,而是通過hash后才去決定連接哪一個memcached服務,因此當你大量加入服務器到連接池時沒有多余開銷。

Memcache的細節討論

1.生命周期

從數據放入memcache開始計時直到時間到就銷毀,如果時間設為0則表示不過期

memcache的數據被銷毀的情況如下:

a.時間到

b.重啟memcached服務

c.重啟memcached服務所在的機器

d.delete/flush銷毀數據

2.把session數據放入到memcached服務中

a.修改php.ini配置文件如下

session.save_handler 有user|files|memcache

session.save_handler = memcache

session.save_path = "tcp://127.0.0.1:11211"

也可以通過php函數ini_set()來在頁面設置

b.重啟apache

<?php
    //存入session數據
    session_start();
    $_SESSION['name'] = '天龍八部';
    $_SESSION['city'] = 'beijing';

    class Dog {
        public $name;
    }
    $dog1 = new Dog;
    $dog1->name = 'abcde';
    $_SESSION['dog'] = $dog1;

    //如果session數據入memcache,那一定是以session_id為key進行添加的
    //取出session數據
    $name = $_SESSION['name'];
    echo "name=$name";
    echo "sessionid=".session_id();
?>

如果管理員不讓我們修改php.ini文件,如何處理session入memcached這個功能

我們通過一個函數可以去修改php.ini的配置

<?php
    ini_set("session.save_handler", "memcache");
    ini_set("session.save_path", "tcp://127.0.0.1:11211");
?>

同時你也可以通過ini_set()去動態的修改對php.ini文件的其他設置,只針對該文件臨時生效不影響其他頁面。

memcached數據和session數據的比較

1.memcached主要目的是提速,因此它是一種無狀態的數據,即數據不和用戶綁定。和memcached相類似的技術有redis技術(key/value數據庫)

2.session數據是和用戶綁定的,是一種有狀態的數據

Memcached的安全性

如何使用memcached才是安全的

在windows下通過啟用防火墻來保護我們的memcached,原理圖如下

在linux下也可以使用防火墻

setup配置

iptables -a input -p tcp -s ip -dport 端口 -j ACCEPT

什么樣的數據適合放入memcached中

  1. 變化頻繁,具有不穩定性的數據,不需要實時入庫(比如用戶在線狀態,在線人數)

  2. 門戶網站的新聞等,覺得頁面靜態化仍不能滿足需求,可以放入到memcache中(配合jquery的ajax請求)

php的安全模式一旦開啟,fopen,rmdir的對文件的操作被禁用

在PHP中有八種被認為是false的情形:

1.布爾值 FALSE

2.整型值 0

3.浮點型值 0.0

4.空字符串以及字符串"0"

5.不包括任何元素的數組

6.不包括任何成員變量的對象

7.特殊類型NULL

8.從沒有任何標記的XML文檔生成的SingleXML對象

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容