基本介绍
memcached是一种缓存技术,他可以把你的数据放入内存,从而通过内存访问提速,因为内存是最快的,memcached的主要目的是提速。
在memcached中维护了一张大的hashtable表,该表在内存中,表的结构是key和value
memcached的key一般是字串,不能重复
memcached的value可以放入(字符串,数值,数组,对象,布尔,二进制数据,图片和视频)
面对一个请求,有如下选择:
可以直接查询数据库(慢)
使用真静态(一般)
直接操作内存(快)
安装使用
下载 memcached
安装
进入cmd,切换到memcached.exe所在目录,memcached.exe -d install启动 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
-
登录到telnet连接到memcached服务
telnet 127.0.0.1 11211
如果你们不能使用telnet是因为系统不存在telnet.exe,就可以到其他机器上拷贝telnet.exe放在C:\windows\system32即可
-
增加语法
add key 名 0 存放时间(秒) 数据大小(字符)
add key1 0 30
-
获取语法
get key 值
get key1
-
修改语法
set key 名 0 存放时间 数据大小 (如果key不存在,相当于添加一个新的,如果存在,则相当与替换)
set key1 0 45 5
replace key 名 存放时间 数据大小 (如果key不存在,则失败,这个指令要求key必须存在)
replace key1 0 40 5
-
删除语法
delete key 名
delete key100
flush_all(可以统一把数据清空)
-
查看状态
stats
这里可以根据cmd_hits/cmd_gets计算出命中率,越高越好。
PHP程序操作Memcached
把php_memcache.dll文件拷贝到php的ext下
不同版本的php所使用的php_memcache.dll的版本不一样修改php.ini文件,加载php_memcache.dll(该文件就是封装了一堆函数)
extension=php_memcache.dll重新启动apache
编写程序来完成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中
变化频繁,具有不稳定性的数据,不需要实时入库(比如用户在线状态,在线人数)
门户网站的新闻等,觉得页面静态化仍不能满足需求,可以放入到memcache中(配合jquery的ajax请求)
php的安全模式一旦开启,fopen,rmdir的对文件的操作被禁用
在PHP中有八种被认为是false的情形:
1.布尔值 FALSE
2.整型值 0
3.浮点型值 0.0
4.空字符串以及字符串"0"
5.不包括任何元素的数组
6.不包括任何成员变量的对象
7.特殊类型NULL
8.从没有任何标记的XML文档生成的SingleXML对象