您的位置:首页 > 数据库 > Memcache

memcached开发注意事项

2015-11-22 12:52 561 查看
连接控制

Important to not call ->addServers() every run – only call it if no servers exist (check getServerList() ); otherwise, since addServers() does not check for dups, it will let you add the same server again and again and again, resultings in hundreds if not thousands of connections to the MC daemon. Specially when using FastCGI.

class Cache {
private $id;
private $obj;

function __construct($id){
$this->id = $id;
$this->obj = new Memcached($id);
}

public function connect($host , $port){
$servers = $this->obj->getServerList();
if(is_array($servers)) {
foreach ($servers as $server)
if($server['host'] == $host and $server['port'] == $port)
return true;
}
return $this->obj->addServer($host , $port);
}

}


并发控制

所有的被发送到memcached的单个命令是完全原子的。如果您针对同一份数据同时发送了一个set命令和一个get命令,它们不会影响对方。它们将被串行化、先后执行。即使在多线程模式,所有的命令都是原子的,除非程序有bug:)

命令序列不是原子的。如果您通过get命令获取了一个item,修改了它,然后想把它set回memcached,我们不保证这个item没有被其他进程(process,未必是操作系统中的进程)操作过。在并发的情况下,您也可能覆写了一个被其他进程set的item。

memcached 1.2.5以及更高版本,提供了gets和cas命令,它们可以解决上面的问题。如果您使用gets命令查询某个key的item,memcached会 给您返回该item当前值的唯一标识。如果您覆写了这个item并想把它写回到memcached中,您可以通过cas命令把那个唯一标识一起发送给 memcached。如果该item存放在memcached中的唯一标识与您提供的一致,您的写操作将会成功。如果另一个进程在这期间也修改了这个 item,那么该item存放在memcached中的唯一标识将会改变,您的写操作就会失败。

CAS (chech and save)

$m = new Memcached();
$m->addServer('localhost', 11211);

do {
/* 获取ip列表以及它的标记 */
$ips = $m->get('ip_block', null, $cas);
/* 如果列表不存在, 创建并进行一个原子添加(如果其他客户端已经添加, 这里就返回false)*/
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* 其他情况下,添加ip到列表中, 并以cas方式去存储, 这样当其他客户端修改过, 则返回false */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while ($m->getResultCode() != Memcached::RES_SUCCESS);


返回值判断

This method also returns false in case you set the value to false, so in order to have a proper fault mechanism in place you need to check the result code to be certain that a key really does not exist in memcached.

<?php
$Memcached = new Memcached();
$Memcached->addServer('localhost', 11211);
$Memcached->set('key', false);
var_dump($Memcached->get('key'));       // boolean false
var_dump($Memcached->getResultCode());  // int 0 which is Memcached::RES_SUCCESS
?>


注意上面代码中的 get 方法中有一个$cas 参数,这个就是当前cnt_key对应的token,一旦 cnt_key 被操作后,其值也发生变化。在cas方法中需要传递$cas值,如果token发生变化,那么cas 将会执行失败,也即 $m->getResultCode() != Memcached::RES_SUCCESS。所以将会再次执行循环体。

这个是在memcached 客户端做的。对于incr,保证原子性,是在memcached服务端完成的,原理应该类似上述的cas操作,由于没有查看memcached的源代码,不敢妄下结论。

压缩问题

如果Memcached::OPT_COMPRESSION常量开启,这个操作会失败,并引发一个警告,因为向压缩数据 后追加数据可能会导致解压不了。

replace

Memcached::replace()和 Memcached::set()类似,但是如果 服务端不存在key, 操作将失败。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  memcached