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对象

    原文作者:littlexjing
    原文地址: https://www.jianshu.com/p/897fc906a4ff
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞