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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容