一个memcache类的具体实现过程:
class Core_Memcache {
private $_cache;
private $_isMemcached;
private function _connect()
{
if ($this->_cache != null && is_object($this->_cache)) {
return true;
}
if ($_isMemcached) {
$this->_cached = new memcached();
// 添加服务器
$servers = array();
foreach ($this->_config['servers'] as $server) {
$server += array('host' => '127.0.0.1', 'port' => '11211', 'weight' => 1);
$servers[] = array($server['host'], $server['port'], $server['weight']);
}
$this->_cache->addServers($servers);
// 开启一致性哈希
$this->_cache->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
// 开启ketama算法兼容,注意,打开本算法时,sub_hash会使用KETAMA默认的MD5
$this->_cache->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
// 设置哈希算法,当不使用KETAMA算法时,这个设置才生效,有几种可选择,不过如果启用ketama,这个选项是没用的
// $this->_cache->setOption(Memcached::OPT_HASH, Memcached::HASH_MD5);
// $this->_cache->setOption(Memcached::OPT_HASH, Memcached::HASH_CRC);
// 开启已连接socket的无延迟特性(在某些环境可能会带来速度上的提升)
$this->_cache->setOption(Memcached::OPT_TCP_NODELAY, true);
// 开启异步I/O。这将使得存储函数传输速度最大化。
$this->_cache->setOption(Memcached::OPT_NO_BLOCK, true);
}
}
}
需要考虑的问题如下:
(a) 安装了memcache服务器后,为什么php可以访问到memcache?
因为php提供了连接memcache的扩展,当使用到memcache这个扩展类的时候,就可以连接并使用memcache,连接一台memcache服务器需要知道服务器的ip,监听的端口号,权重。一台主机上可以按照多台memcache,只需要每个memcache监听的端口号不一样的就可以了。
(b)memcache类是否可以做成单例模式 (即定义private $_cache 为 private static $_cache)?
使用单例模式最重要的是理解类静态成员。在php发起一次请求中,多次调用memcache的类,静态成员变量$_cache只需要实例化一次,就可以被多个多个实例化类共享,这就是单例模式的好处,为了节约实例化同一个类的开销。但是memcache类是否能做出单例模式呢。
显然是不能的,因为使用到memcache的时候,会根据不同的情况使用不同的配置文件(有多台memcache,对应相应的配置文件),也就是说,memcache可能会需要读取不同的配置文件实例化多次。
(c)memcache 分布式算法的理解
memcache分布式算法中,使用到了一致性算法,具体的算法实现请关注下一篇文章(php版)
(d)这个类中,如何实现调用memcache的内置方法?
使用PHP的魔术方法和内置函数call_user_func_array().
/**
* 调用魔术方法(大多数会直接转移调用原生方法,少部分方法会重写)
*
* @param string $method
* @param mixed $args
* @return mixed
*/
public function __call($method, $args)
{
$this->_connect();
return call_user_func_array(array($this->_cache, $method), $args);
}
写入:
/**
* 写入操作
*
* @param string $func set/add/replace
* @param string $key
* @param string $value
* @param int $ttl
* @return bool
*/
private function _write($func, $key, $value, $ttl = 0)
{
$this->_connect();
if ($this->_isMemcached) {
return $this->_cache->$func($key, $value, $ttl);
} else {
return $this->_cache->$func($key, $value, MEMCACHE_COMPRESSED, $ttl);
}
}
具体写入方法:
public function set($key, $value, $ttl = 0)
{
return $this->_write('set', $key, $value, $ttl);
}
(e)memcache析构函数,释放连接
/**
* 释放连接
*/
public function __destruct()
{
if ($this->_cache && is_object($this->_cache)) {
if (method_exists($this->_cache, 'close')) {
$this->_cache->close();
}
$this->_cache = null;
}
}