memcache一致性hash的php已毕格局,略提及Cache工具的法则

by admin on 2019年2月5日

前文提到的在系统设置Cache组件
Cache::getInstance()的时候,会去调用processManager去创建Cache的经过,然后以管道通讯的点子展开安装缓存和收获缓存。

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

正文实例讲述了memcache一致性hash的php完成方式。分享给我们供大家参考。具体如下:

事先我写了一篇在 Laravel 4 框架中采纳阿里云 OCS
缓存的文章,介绍了怎么着通过扩张Laravel 4 来协助须要 SASL 认证的阿里云 OCS 缓存服务。有网友问我,ACE
的缓存怎么在 Laravel 4
中行使。我本来认为应该可以完全用平等的情势,后来友好尝试的时候才察觉,ACE
的缓存差异非常大。所以再写一篇,介绍一下怎么样在 Laravel 框架中选择阿里云
ACE 的缓存服务。

Cache是以单例格局完成的。构造器会进行如下操作

中间有一个工具类TableManager。这些类为了处理进度间数据共享。是对swoole_table的一层封装
swoole_table一个基于共享内存和锁完结的超高质量,并发数据结构。用于缓解多进度/八线程数据共享和一块加锁难点。

近日在看有些分布式方面的文章,所以就用php落成一致性hash来练练手,以前一般用的是最原始的hash取模做
分布式,当生产进度中拉长或删除一台memcache都会招致数据的全部失效,一致性hash就是为精通决那么些题目,把失效数据降到最低,相关资料可以google一下!

怎么着伸张 Laravel 的缓存驱动

//根据配置创建指定数目的Cache服务进程,然后启动。
$num = intval(Config::getInstance()->getConf("EASY_CACHE.PROCESS_NUM"));//默认配置数目是1,在Config.php里'EASY_CACHE.PROCESS_NUM'=>1
if($num <= 0){
   return;
}
$this->cliTemp = new SplArray();//这个数组以后会给单元测试时候单独使用,正常模式这个数组是不使用的
//若是在主服务创建,而非单元测试调用
if(ServerManager::getInstance()->getServer()){
    //创建了一个swoole_table ,表名为__Cache,里面存储data(后面就讲到其实这里存储的是操作Cache的指令)作用是用来做GC(防止Cache被撑爆)
    TableManager::getInstance()->add(self::EXCHANGE_TABLE_NAME,[
        'data'=>[
            'type'=>Table::TYPE_STRING,
            'size'=>10*1024
        ],
        'microTime'=>[
            'type'=>Table::TYPE_STRING,
            'size'=>15
        ]
    ],2048);
    $this->processNum = $num;
    for ($i=0;$i < $num;$i++){
        ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class);
    }
}

TableManager首要做了上边几件事
add方法
即使$list数组中有其一表名($name是一个表名或者叫做集合名),就开端化swoole_table,然后配置的字段类型数组举行创办

php落成效能有自然的缺少,假使要高效用,如故写扩充相比好

在 Laravel 4 中利用 Cache::get($key), Cache::put($key, $value, $minutes)
这样的代码时,实际上是造访 实例化的 Illuminate\Cache\Repository,
所以我们经过 Cache::extend 方法增加自定义缓存驱动时,同样应当回到一个
Illuminate\Cache\Repository 对象。

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

if(!isset($this->list[$name])){
    $table = new Table($size);
    foreach ($columns as $column => $item){
        $table->column($column,$item['type'],$item['size']);
    }
    $table->create();
    $this->list[$name] = $table;
}

经测试,5个memcache,每个memcache生成100个虚拟节点,set加get1000次,与单个memcache直接set加get慢5倍,所以作用一般,有待优化!

Laravel 4 内置的 Memcached 缓存驱动,完毕的流程是这么的:

ProcessManager::getInstance()那句话主要做了下边的操作
ProcessManager
的__construct构造函数创设了一个swoole_table,表名是process_hash_map

get方法
一贯回到swoole_table的实例。

在读书本文往日,最好精通二分查找法。

1.成立一个标准 Memcached 类的新目的
2.用上一步创设的 Memcached 对象创造一个贯彻了
Illuminate\Cache\StoreInterface 接口的
Illuminate\Cache\MemecachedStore 对象。
3.用上一步创造的 MemcachedStore 对象成立一个
Illuminate\Cache\Repository 对象。

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

采取的地点有这个
前文提到的在系统装置Cache组件 Cache::getInstance()的时候

兑现进程:

从而大家在扩展自定义的 Cache
驱动时,依照自己的动静,选用方面的某一个手续自定义,最后仍然要赶回
Illuminate\Cache\Repository
对象。比如上一篇文章中,我就是在首先步,创立标准
Memcached 对象之后,通过 setSaslAuthData() 方法设定 OCS
须要的用户名密码。之后第2步、第3步并不需求自定义。

addProcess($this->generateProcessName($i),CacheProcess::class);
$this->generateProcessName($i)那个代码很粗略就是基于$i来设置进程名称
addProcess 是在processList存储CacheProcess::class的实例,具体代码如下

构造方法做了之类事情

memcache的布置 ip+端口+虚拟节点系列号
做hash,使用的是crc32,形成一个闭环。
对要操作的key进行crc32
二分法在编造节点环中查找近来的一个虚拟节点
从虚拟节点中提取真实的memcache ip和端口,做单例连接

ACE 的缓存服务

$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;
}
$num = intval(Config::getInstance()->getConf("EASY_CACHE.PROCESS_NUM"));//Config默认配置是1,如果配置为小于等于0则不开启Cache
if($num <= 0){
   return;
}
$this->cliTemp = new SplArray();
//若是在主服务创建,而非单元测试调用
if(ServerManager::getInstance()->getServer()){
    //创建table用于数据传递
    TableManager::getInstance()->add(self::EXCHANGE_TABLE_NAME,[
        'data'=>[
            'type'=>Table::TYPE_STRING,
            'size'=>10*1024
        ],
        'microTime'=>[
            'type'=>Table::TYPE_STRING,
            'size'=>15
        ]
    ],2048);
    //创建了一个__Cache的swoole_table表,字段为 data String 10240,microTime String 15的表
    $this->processNum = $num;
    for ($i=0;$i < $num;$i++){
        ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class);
    }
}

复制代码 代码如下:

阿里云 ACE 的缓存服务,跟默认的 OCS 有所差距:

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

ProcessManager也是一个很主要的定义。其实就是一个管理职务映射的工具。

<?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_memcache一致性hash的php已毕格局,略提及Cache工具的法则。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->_memcache一致性hash的php已毕格局,略提及Cache工具的法则。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));
?>

1.由此 阿里巴巴(Alibaba)(Alibaba)::Cache() 方法赢得 Cache 对象。
2.ACE 的 Cache 对象与规范 Memcached 对象不一致,接济的方法简单。

$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的任务进程。

此地可以观察ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class)

仰望本文所述对大家的php程序设计有所辅助。

就此,本次率先步得到的不是规范 Memcached 对象,由此就不可以创制Illuminate\Cache\MemcachedStore 对象。须要团结完结Illuminate\Cache\StoreInterface 接口。

__start方法紧如若给swoole_table,表名为process_hash_map插入当前CacheProcess的历程名为key,进度IDpid为value。并且注册进度退出的风云。

骨子里那里是透过ProcessManager,让swoole服务添加了一个历程。swoole的addProcess方法,文档链接

您或许感兴趣的稿子:

  • php 分库分表hash算法
  • php的hash算法介绍
  • PHP中对种种加密算法、Hash算法的快慢测试对照代码
  • PHP
    Hash算法:提姆es33算法代码实例
  • PHP完毕的种种hash算法长度及质量测试实例
  • PHP完毕的一致性HASH算法示例
  • php常用hash加密函数
  • PHP随机生成唯一HASH值自定义函数
  • php对文件举办hash运算的法子
  • PHP完成的一致性Hash算法详解【分布式算法】

在控制台创立了缓存空间之后,会有唯一的“缓存空间名称”,然后通过
Alibaba(Alibaba)::Cache(‘缓存空间名称’) 来拿到 Cache 对象。以下就是促成 ACE
缓存服务驱动的步子:

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);

bf88必发唯一官网 1

1.为了便于修改,我在配备文件 app/config/cache.php 中加进一个名为 ace
的键,存储缓存空间名称。
2.然后创立一个 AceMemcachedStore 类,那么些类达成Illuminate\Cache\StoreInterface 接口。
3.结尾,用 AceMemcachedStore 对象来创立 Illuminate\Cache\Repository
对象。

$this->run($this->swooleProcess)这几个函数是CacheProcess如若配置了persistent提姆e,就会张开一个定时器定时去取$file

Config::getInstance()->getConf(‘TEMP_DIR’).”/{$processName}.data”;的数据备份,默许是0也就是不会去做定时数据落地的操作

观察这里才是Cache组件在率先次实例化的时候做的连锁工作,计算就是创制了点名数量的Cache进度绑定到swoole服务器上。在大局的process_hash_map表中能找到相应的Cache进程ID。然后Cache进程是可以以管道情势来进展通信。

 

set缓存方法

public function set($key,$data)
{
    if(!ServerManager::getInstance()->isStart()){
        $this->cliTemp->set($key,$data);
    }
    if(ServerManager::getInstance()->getServer()){
        $num = $this->keyToProcessNum($key);
        $msg = new Msg();
        $msg->setCommand('set');
        $msg->setArg('key',$key);
        $msg->setData($data);
        ProcessManager::getInstance()->getProcessByName($this->generateProcessName($num))->getProcess()->write(\swoole_serialize::pack($msg));//直接把需要缓存的数据,封装成msg然后write给hash映射到的Cache进程
    }
}

当进度取得到的时候会回调onReceive方法

public function onReceive(string $str,...$agrs)
{
    // TODO: Implement onReceive() method.

    $msg = \swoole_serialize::unpack($str);
    $table = TableManager::getInstance()->get(Cache::EXCHANGE_TABLE_NAME);
    if(count($table) > 1900){
        //接近阈值的时候进行gc检测
        //遍历Table 依赖pcre 如果发现无法遍历table,检查机器是否安装pcre-devel
        //超过0.1s 基本上99.99%为无用数据。
        $time = microtime(true);
        foreach ($table as $key => $item){
            if(round($time - $item['microTime']) > 0.1){
                $table->del($key);
            }
        }
    }
    if($msg instanceof Msg){
        switch ($msg->getCommand()){
            case 'set':{
                $this->cacheData->set($msg->getArg('key'),$msg->getData());
                break;
            }
            case 'get':{
                $ret = $this->cacheData->get($msg->getArg('key'));
                $msg->setData($ret);
                $table->set($msg->getToken(),[
                    'data'=>\swoole_serialize::pack($msg),
                    'microTime'=>microtime(true)
                ]);
                break;
            }
            case 'del':{
                $this->cacheData->delete($msg->getArg('key'));
                break;
            }
            case 'flush':{
                $this->cacheData->flush();
                break;
            }
            case 'enQueue':{
                $que = $this->cacheData->get($msg->getArg('key'));
                if(!$que instanceof \SplQueue){
                    $que = new \SplQueue();
                    $this->cacheData->set($msg->getArg('key'),$que);
                }
                $que->enqueue($msg->getData());
                break;
            }
            case 'deQueue':{

                $que = $this->cacheData->get($msg->getArg('key'));
                if(!$que instanceof \SplQueue){
                    $que = new \SplQueue();
                    $this->cacheData->set($msg->getArg('key'),$que);
                }
                $ret = null;
                if(!$que->isEmpty()){
                    $ret = $que->dequeue();
                }
                $msg->setData($ret);
                //deQueue 有cli 服务未启动的请求,但无token
                if(!empty($msg->getToken())){
                    $table->set($msg->getToken(),[
                        'data'=>\swoole_serialize::pack($msg),
                        'microTime'=>microtime(true)
                    ]);
                }
                break;
            }
            case 'queueSize':{
                $que = $this->cacheData->get($msg->getArg('key'));
                if(!$que instanceof \SplQueue){
                    $que = new \SplQueue();
                }
                $msg->setData($que->count());
                $table->set($msg->getToken(),[
                    'data'=>\swoole_serialize::pack($msg),
                    'microTime'=>microtime(true)
                ]);
                break;
            }
        }
    }
}

此间一先导会进展缓存GC确保内存不会撑爆

set方法会直接给$this->cacheData,设置缓存值。

 

get方法比较新鲜,它会去给Cache进度发送get的下令,然后Cache读取到命令会将值写到_Cache,Swoole_table表中。然后再去读取(那一个会有一个while循环,类似自旋)出缓存内容。这样的益处,可以确保可以读取到及时的数目缓存,不会因为高并发读取到最新的缓存值内容。而且仍能更管用的做gc,防止Cache内存撑爆。

public function get($key,$timeOut = 0.01)
{
    if(!ServerManager::getInstance()->isStart()){
        return $this->cliTemp->get($key);
    }
    $num = $this->keyToProcessNum($key);
    $token = Random::randStr(9);//这个是一个凭证,是确保获取到自己此刻想获取的cache数据,和事务类似为了保证可重复读
    $process = ProcessManager::getInstance()->getProcessByName($this->generateProcessName($num));
    $msg = new  Msg();
    $msg->setArg('timeOut',$timeOut);
    $msg->setArg('key',$key);
    $msg->setCommand('get');
    $msg->setToken($token);
    $process->getProcess()->write(\swoole_serialize::pack($msg));
    return $this->read($token,$timeOut);
}

$process->getProcess()->write(\swoole_serialize::pack($msg))发那么些包给Cache进程,Cache进程会举行上面那个操作

$ret = $this->cacheData->get($msg->getArg('key'));//获取到当前的缓存值
$msg->setData($ret);
//将当前的内容设置到_Cache表中,token是请求的时候发过来的凭证原样拼装。这有什么好处呢,就是确保在高并发下,在A时刻获取的缓存,不会拿到后面B时刻更新的值。
$table->set($msg->getToken(),[
    'data'=>\swoole_serialize::pack($msg),
    'microTime'=>microtime(true)
]);

$this->read($token,$timeOut);

//这里的操作是直接从_Cache表中获取缓存数据,如果缓存存在并且进程调度没有超时,然后在表中将取过数据的内容删除掉返回
private function read($token,$timeOut)
{
    $table = TableManager::getInstance()->get(self::EXCHANGE_TABLE_NAME);
    $start = microtime(true);
    $data = null;
    while(true){
        usleep(1);
        if($table->exist($token)){
            $data = $table->get($token)['data'];
            $data = \swoole_serialize::unpack($data);
            if(!$data instanceof Msg){
                $data = null;
            }
            break;
        }
        if(round($start - microtime(true),3) > $timeOut){
            break;
        }
    }
    $table->del($token);
    if($data){
        return $data->getData();
    }else{
        return null;
    }
}

 

超前略带讲解一下Cache的set方法加深概念

上边来看现实的代码落成:

//讲解一下Cache的set方法加深概念
if(!ServerManager::getInstance()->isStart()){//兼容测试模式。也就是不开启服务的情景下直接是clitemp中取缓存数据
    $this->cliTemp->set($key,$data);
}
if(ServerManager::getInstance()->getServer()){
    $num = $this->keyToProcessNum($key);//这里是通过key然后hash到应该投放的Cache进程中去。
    $msg = new Msg();
    $msg->setCommand('set');
    $msg->setArg('key',$key);
    $msg->setData($data);
    //下面一句话还是挺复杂的,根据key名hash到ProcessManager对应的映射,然后获取到swoole_process的实例,以swoole的write函数向管道内写入数据。
    ProcessManager::getInstance()->getProcessByName($this->generateProcessName($num))->getProcess()->write(\swoole_serialize::pack($msg));
    //在写完数据后,在CacheProcess的onReceive方法中可以看到对应setCommand的操作细节。其实数据都被写到了一个Arr数组中。下篇接着讲一下Cache的实现细节。这节还是主要讲TableManager和它的相关作用.
}

编码达成自定义 ACE 缓存驱动:

先是步,修改配置文件。打开 app/config/cache.php,在结尾增添一行:

复制代码 代码如下:

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

其次步,为了有利于,把团结的类公事放在 src/Ace 目录下,使用 Ace
作为命名空间。

1.在 app 的同级目录创设目录 src/Ace。
2.开拓 composer.json 文件,修改 autoload 节,在 classmap 上边用 psr-0
或者 psr-4 来机关加载文件。

复制代码 代码如下:

“autoload”: {
    “classmap”: [
        // autoload class
    ],
    “psr-4”: {
      “Ace\\”: “src/Ace”
    }
},

创造 src/Ace/AceMemcachedStore.php 文件,代码如下:

复制代码 代码如下:

<?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;
bf88必发唯一官网,    }
    /**
     * Get the cache key prefix.
     *
     * @return string
     */
    public function getPrefix()
    {
        return $this->prefix;
    }
}

那段代码比较不难,然则要尤其注意一下 get($key) 方法的完结。标准
memcached 以及 ACE 的缓存对象的 get
方法都是key有效时重返对应的缓存值,否则重返false,而在 Laravel 4
中,是由此检测 get 方法重返的是还是不是 null
来做判断,所以那边需求处理一下,再次回到缓存值或者null。

AceMemcachedStore类已经成立好了,接下去在 bootstrap/start.php 文件中扩大Cache:

开辟 bootstrap/start.php, 添加以下代码:

复制代码 代码如下:

// 扩充名为 ace 的缓存驱动
Cache::extend(‘ace’, function($app)
{
    // 从 app/config/cache.php 文件中读取 “ace” 的值
    $space = $app[‘config’][‘cache.ace’];
    
    // 从 app/config/cache.php 文件中读取 “prefix” 的值
    $prefix = $app[‘config’][‘cache.prefix’];
    
    // 创建 \Ace\AceMemcachedStore 对象
    $store = new \Ace\AceMemcachedStore($space, $prefix);
    
    // 创建并重临 \Illuminate\Cache\Repository 对象
    return new \Illuminate\Cache\Repository($store);
 
});

点名系统利用 ‘ace’ 作为缓存驱动:打开 app/config/cache.php,找到
‘driver’ => ‘…’ 所在行,修改为:’driver’ => ‘ace’.

利用和范围

通过以上操作,就足以在 Laravel 4 中调用 ACE
的缓存服务,使用上与平时的用法完全一致,比如:

复制代码 代码如下:

// 添加缓存,有效时间10分钟
Cache::put(‘my_key’, ‘my value’, 10);
 
// 读取缓存
Cache::get(‘my_key’)
 
// 判断缓存是还是不是存在
Cache::has(‘my_key’)
 
// 数据查询缓存
$users = DB::table(‘users’)->remember(10)->get();

但是出于 ACE 缓存对象自我的界定,只可以删除指定 key
的缓存对象,不能遍历、全量操作,由此 Cache::flush()
方法就无法应用。在地点的 AceMemcachedStore 对象中,flush
方法没有做别的操作,只是重临 false.

您可能感兴趣的篇章:

  • Laravel
    Memcached缓存驱动的配置与运用措施分析
  • Laravel中扩大Memcached缓存驱动完结应用阿里云OCS缓存
  • Laravel使用Caching缓存数据减轻数据库查询压力的方法
  • Laravel框架数据库CURD操作、连贯操作计算
  • PHP开发框架Laravel数据库操作方法总括
  • 跟我学Laravel之急速入门
  • Laravel框架中伸张函数、扩张自定义类的艺术
  • Laravel框架路由配置计算、设置技巧大全
  • Laravel中选用自己编辑类库的3种方法
  • Laravel使用memcached缓存对小说增删改查进行优化的主意

发表评论

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

网站地图xml地图