memcache一致性hash的php完成格局

TableManager::getInstance()->add(
    'process_hash_map',[
        'pid'=>[
            'type'=>Table::TYPE_INT,
            'size'=>10
        ]
    ],256
);

构造方法做了如下事情

<?php
class memcacheHashMap {
        private $_node = array();
        private $_nodeData = array();
        private $_keyNode = 0;
        private $_memcache = null;
        //每一个物理服务器生成虚拟节点个数
[注:节点数越多,cache分布的均匀性越好,同时set
get操作时,也更功耗源,10台物理服务器,接纳200较为客体]
        private $_virtualNodeNum = 200;
        private function __construct() {
                $config = array(//五个memcache服务器
                                                ‘127.0.0.1:11211’,
                                                ‘127.0.0.1:11212’,
                                                ‘127.0.0.1:11213’,
                                                ‘127.0.0.1:11214’,
                                                ‘127.0.0.1:11215’
                                        );
                if (!$config) throw new Exception(‘Cache config
NULL’);
                foreach ($config as $key => $value) {
                        for ($i = 0; $i < $this->_virtualNodeNum;
$i++) {
                                $this->_node[sprintf(“%u”,
crc32($value . ‘_’ . $i))] = $value . ‘_’ .
$i;//循环为各类memcache服务器成立200个虚拟节点
                        }
                }
               
ksort($this->_node);//创立出来的1000个虚拟节点根据键名从小到大排序
        }
        //实例化该类
        static public function getInstance() {
                static $memcacheObj = null;
                if (!is_object($memcacheObj)) {
                        $memcacheObj = new self();
                }
                return $memcacheObj;
        }
        //根据传来的键查找到相应虚拟节点的职位
        private function _connectMemcache($key) {
                $this->_nodeData =
array_keys($this->_node);//全数的杜撰节点的键的数组
                $this->_keyNode = sprintf(“%u”,
crc32($key));//算出键的hash值
                $nodeKey =
$this->_findServerNode();//找出相应的杜撰节点
               
//假设超出环,从头再用二分法查找三个最近的,然后环的头尾做判定,取最接近的节点
                if ($this->_keyNode > end($this->_nodeData))
{
                        $this->_keyNode -=
end($this->_nodeData);
                        $nodeKey2 = $this->_findServerNode();
                        if (abs($nodeKey2 – $this->_keyNode) <
abs($nodeKey – $this->_keyNode))  $nodeKey = $nodeKey2;
                }
                var_dump($this->_node[$nodeKey]);
                list($config, $num) = explode(‘_’,
$this->_node[$nodeKey]);
                if (!$config) throw new Exception(‘Cache config
Error’);
                if (!isset($this->_memcache[$config])) {
                        $this->_memcache[$config] = new
Memcache;
                        list($host, $port) = explode(‘:’, $config);
                       
$this->_memcache[$config]->connect($host, $port);
                }
                return $this->_memcache[$config];
        }
        //二分法依照提交的值找出多年来的虚拟节点地方
        private function _findServerNode($m = 0, $b = 0) {
            $total = count($this->_nodeData);
            if ($total != 0 && $b == 0) $b = $total – 1;
            if ($m < $b){
                $avg = intval(($m+$b) / 2);
                if ($this->_nodeData[$avg] == $this->_keyNode)
return $this->_nodeData[$avg];
                elseif ($this->_keyNode <
$this->_nodeData[$avg] && ($avg-1 >= 0)) return
$this->_findServerNode($m, $avg-1);
                else return $this->_findServerNode($avg+1, $b);
            }
                if (abs($this->_nodeData[$b] –
$this->_keyNode) < abs($this->_nodeData[$m] –
$this->_keyNode))  return $this->_nodeData[$b];
                else return $this->_nodeData[$m];
        }
        public function set($key, $value, $expire = 0) {
                return $this->_connectMemcache($key)->set($key,
json_encode($value), 0, $expire);
        }
        public function add($key, $value, $expire = 0) {
                return $this->_connectMemcache($key)->add($key,
json_encode($value), 0, $expire);
        }
        public function get($key) {
                return
json_decode($this->_connectMemcache($key)->get($key), true);
        }
        public function delete($key) {
                return
$this->_connectMemcache($key)->delete($key);
        }
}
$runData[‘BEGIN_TIME’] = microtime(true);
//测试两万次set加get
for($i=0;$i<10000;$i++) {
        $key = md5(mt_rand());
        $b = memcacheHashMap::getInstance()->set($key, time(), 10);
}
var_dump(number_format(microtime(true) –
$runData[‘BEGIN_TIME’],6));
$runData[‘BEGIN_TIME’] = microtime(true); $m= new Memcache;
$m->connect(‘127.0.0.1’, 11211);
for($i=0;$i<10000;$i++) {
        $key = md5(mt_rand());
        $b = $m->set($key, time(), 0, 10);
}
var_dump(number_format(microtime(true) –
$runData[‘BEGIN_TIME’],6));
?>

如何增添 Laravel 的缓存驱动

Cache是以单例情势完结的。构造器会举办如下操作

个中有2个工具类TableManager。这么些类为了处理进度间数据共享。是对swoole_table的一层封装
swoole_table一个基于共享内部存储器和锁实现的超高品质,并发数据结构。用于消除多进度/四线程数据共享和协助进行加锁难题。

你可能感兴趣的稿子:

  • php 分库分表hash算法
  • php的hash算法介绍
  • PHP中对各样加密算法、Hash算法的进程测试对照代码
  • PHP
    Hash算法:Times33算法代码实例
  • PHP完成的各项hash算法长度及质量测试实例
  • PHP完结的一致性HASH算法示例
  • php常用hash加密函数
  • PHP随机生成唯一HASH值自定义函数
  • php对文本进行hash运算的方法
  • PHP落成的一致性Hash算法详解【分布式算法】

Laravel 4 内置的 Memcached 缓存驱动,完结的流程是那般的:

ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class)那句话才是Cache的主干逻辑。

那边可以看到ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class)

经测试,陆个memcache,各种memcache生成一百个虚拟节点,set加get1000次,与单个memcache直接set加get慢5倍,所以成效一般,有待优化!

<?php
 
namespace Ace;
use Illuminate\Cache\StoreInterface;
use Illuminate\Cache\TaggableStore;
 
class AceMemcachedStore extends TaggableStore implements StoreInterface
{
 
    protected $memcached;
    protected $prefix;
 
    public function __construct($space, $prefix = ”) {
        $this->memcached = \Alibaba::Cache($space);
        $this->prefix = strlen($prefix) > 0 ? $prefix.’:’ : ”;
    }
 
    /**
     * Retrieve an item from the cache by key.
     *
     * @param  string $key
     * @return mixed
     */
    public function get($key)
    {
        $value = $this->memcached->get($this->prefix.$key);
        if(is_bool($value) && $value === false) {
            return null;
        }
        return $value;
    }
 
    /**
     * Store an item in the cache for a given number of minutes.
     *
     * @param  string $key
     * @param  mixed $value
     * @param  int $minutes
     * @return boolean
     */
    public function put($key, $value, $minutes)
    {
        return $this->memcached->set($this->prefix.$key,
$value, $minutes);
    }
 
    /**
     * Increment the value of an item in the cache.
     *
     * @param  string $key
     * @param  mixed $value
     * @return boolean
     */
    public function increment($key, $value = 1)
    {
        return $this->memcached->increment($this->prefix.$key,
$value);
    }
 
    /**
     * Decrement the value of an item in the cache.
     *
     * @param  string $key
     * @param  mixed $value
     * @return boolean
     */
    public function decrement($key, $value = 1)
    {
        return $this->memcached->decrement($this->prefix.$key,
$value);
    }
 
    /**
     * Store an item in the cache indefinitely.
     *
     * @param  string $key
     * @param  mixed $value
     * @return boolean
     */
    public function forever($key, $value)
    {
        return $this->memcached->set($key, $value, 0);
    }
 
    /**
     * Remove an item from the cache.
     *
     * @param  string $key
     * @return boolean
     */
    public function forget($key)
    {
        return $this->memcached->delete($this->prefix.$key);
    }
 
    /**
     * Remove all items from the cache.
     *
     * @return void
     */
    public function flush()
    {
        //$this->memcached->flush();
        return false;
    }
 
    public function getMemcached()
    {
        return $this->memcached;
    }
    /**
     * Get the cache key prefix.
     *
     * @return string
     */
    public function getPrefix()
    {
        return $this->prefix;
    }
}

$key = md5($processName);
if(!isset($this->processList[$key])){
    try{

        $process = new $processClass($processName,$args,$async);
        $this->processList[$key] = $process;
        return true;
    }catch (\Throwable $throwable){
        Trigger::throwable($throwable);
        return false;
    }
}else{
    trigger_error("you can not add the same name process : {$processName}.{$processClass}");
    return false;
}

get方法
直接回到swoole_table的实例。

在翻阅本文在此之前,最好精通二分查找法。

因而上述操作,就能够在 Laravel 4 中调用 ACE
的缓存服务,使用上与平时的用法完全一致,比如:

那么CacheProcess::class的实例话做了什么操作呢
$this->cacheData = new
SplArray();//那里很重点,为啥如此说各种Cache进度实际保存的缓存值都以在此处的,每一种Cache进度都有和好的3个cacheData数组
$this->persistentTime =
Config::getInstance()->getConf(‘EASY_CACHE.PERSISTENT_TIME’);
parent::__construct($processName, $args);
CacheProcess::class继承于AbstractProcess
AbstractProcess的构造方法

图片 1

近来在看一些分布式方面包车型地铁小说,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做
分布式,当生产进程中加上或删除一台memcache都会造成数据的总体失效,一致性hash便是为了解决那个标题,把失效数据降到最低,相关材质能够google一下!

// 钦点缓存空间名称
‘ace’ => ‘lblog-cache’,

ProcessManager::getInstance()这句话主要做了上边包车型客车操作
ProcessManager
的__construct构造函数创制了三个swoole_table,表名是process_hash_map

ProcessManager也是二个很要紧的定义。其实正是一个管制职分映射的工具。

期待本文所述对大家的php程序设计有着协理。

复制代码 代码如下:

$this->async = $async;
$this->args = $args;
$this->processName = $processName;
$this->swooleProcess = new \swoole_process([$this,'__start'],false,2);
ServerManager::getInstance()->getServer()->addProcess($this->swooleProcess);//然后swoole服务会addProcess一个Cache的任务进程。

前文连接,讲了es是什么样运维swoole服务的。

复制代码 代码如下:

复制代码 代码如下:

if(PHP_OS != 'Darwin'){
    $process->name($this->getProcessName());
}
TableManager::getInstance()->get('process_hash_map')->set(
    md5($this->processName),['pid'=>$this->swooleProcess->pid]
);
ProcessManager::getInstance()->setProcess($this->getProcessName(),$this);
if (extension_loaded('pcntl')) {
    pcntl_async_signals(true);
}
Process::signal(SIGTERM,function ()use($process){
    $this->onShutDown();
    TableManager::getInstance()->get('process_hash_map')->del(md5($this->processName));
    swoole_event_del($process->pipe);
    $this->swooleProcess->exit(0);
});
if($this->async){
    swoole_event_add($this->swooleProcess->pipe, function(){
        $msg = $this->swooleProcess->read(64 * 1024);
        $this->onReceive($msg);
    });
}
$this->run($this->swooleProcess);

TableManager重要做了下边几件事
add方法
要是$list数组中有这几个表名($name是一个表名也许叫做集合名),就开头化swoole_table,然后配置的字段类型数组举行创办

php实现效能有一定的缺少,如若要高功用,依旧写增加比较好

就此,这一次先是步获得的不是正式 Memcached 对象,因而就不可能创立Illuminate\Cache\MemcachedStore 对象。需求团结完结Illuminate\Cache\StoreInterface 接口。

addProcess($this->generateProcessName($i),CacheProcess::class);
$this->generateProcessName($i)那几个代码很简短就是基于$i来安装进程名称
addProcess 是在processList存款和储蓄CacheProcess::class的实例,具体代码如下

提早略带讲解一下Cache的set方法加深概念

贯彻进程:

ACE 的缓存服务

发表评论

电子邮件地址不会被公开。 必填项已用*标注