标签归档:memcache

「转」Memcache 和 Memcached 客户端的区别

PHP Client Comparison

There are primarily two clients used with PHP. One is the older, more widespread pecl/memcache and the other is the newer, less used, more feature rich pecl/memcached.

Both support the basics such as multiple servers, setting vaules, getting values, increment, decrement and getting stats.

Here are some more advanced features and information.

pecl/memcache pecl/memcached
First Release Date 2004-06-08 2009-01-29 (beta)
Actively Developed? Yes Yes
External Dependency None libmemcached
Features
Automatic Key Fixup1 Yes No
Append/Prepend No Yes
Automatic Serialzation2 Yes Yes
Binary Protocol No Optional
CAS No Yes
Compression Yes Yes
Communication Timeout Connect Only Various Options
Consistent Hashing Yes Yes
Delayed Get No Yes
Multi-Get Yes Yes
Session Support Yes Yes
Set/Get to a specific server No Yes
Stores Numerics Converted to Strings Yes
  1. pecl/memcache will convert an invalid key into a valid key for you. pecl/memcached will return false when trying to set/get a key that is not valid.
  2. You do not have to serialize your objects or arrays before sending them to the set commands. Both clients will do this for you.

—end–

原文链接:https://code.google.com/p/memcached/wiki/PHPClientComparison

PS:Memcache会将数字转成字符串存储这个坑刚踩到过~

用Memcache实现分布式的锁服务

一般情况下我们都用Memcache作为一个分布式的key/value缓存服务器,其实Memcache也可以实一些外门邪道的功能比如作为分布式锁来用。

原理其实非常简单就是memecach_add的时候,如果添加的key已经存在那么后面的添加就会失败。设想在高并发的场景下,如果存在被竞争的资源,我们就可以利用这个小trick来对资源加锁。知道了原理实现起来非常简单,下面是我初步实现的代码。


* gist: https://gist.github.com/tomheng/6149779
*/

class Lock{

private $mc = null;
private $key_prefix = "memcache_lock_service_key_";
private $all_lock_names = array();
private $expiration = 60; //one min
private $max_block_time = 15; //最长的阻塞时间
/**
* [__construct description]
*/
public function __construct(){
if(function_exists('memcache_init')){
$this->mc = memcache_connect('memcache_host', 11211);
}
}

/**
* [get_key description]
* @param [type] $name [description]
* @return [type] [description]
*/
private function get_key($name){
$key = $this->key_prefix.$name;
return $key;
}

/**
* 捕获锁
* @param [type] $name [description]
* @return [type] [description]
*/
public function begin($name, $block = true)
{
if(!$this->mc || !$name){
return false;
}
$max_block_time = $this->max_block_time;
$key = $this->get_key($name);
do{
$re = memcache_add($this->mc, $key, 1, false, $this->expiration);
if($re == true){
$this->all_lock_names[$name] = 1;
//$this->debug();
break;
}else{
//dolog('Lock failed '.$name);
}
//echo '#'.PHP_EOL;
//sleep(1);
}while($block && $max_block_time-- && !sleep(1));
return $re;
}

/**
* 释放锁
*/
public function release($name){
if(!$this->mc || !$name){
return false;
}
$key = $this->get_key($name);
$re = memcache_delete($this->mc, $key);
if($re == true){
unset($this->all_lock_names[$name]);
}
return $re;
}

/**
* 释放所有的锁
*/
public function __destruct(){
if(!$this->mc){
return false;
}
foreach ($this->all_lock_names as $name => $value) {
# code...
$this->release($name);
}
}

/**
* 调试
* @return [type] [description]
*/
public function debug(){
var_dump($this->all_lock_names);
foreach ($this->all_lock_names as $name => $value) {
$key = $this->get_key($name);
if($this->mc){
$value = memcache_get($this->mc, $key);
}else{
$value = "no such lock ";
}
echo "Lock name:$key, value:{$value}".PHP_EOL;
}
}
}