略提及Cache工具的规律,Cache组件原理

前文连接,讲了es是何许运行swoole服务的。

前文提到的在系统安装Cache组件
Cache::getInstance()的时候,会去调用processManager去成立Cache的进度,然后以管道通讯的艺术展开设置缓存和获得缓存。

上文:至于php的共享内部存款和储蓄器的选拔和探讨之由起
下文:
至于php的共享内部存款和储蓄器的行使和切磋之深切剖析swoole
table

入门辅导 [编写本页]

Swoole即便是业内的PHP扩大,实际上与日常的恢弘不一样。普通的恢宏只是提供三个库函数。而swoole扩充在运作后会接管PHP的控制权,进入事件循环。当IO事件产生后,swoole会自动回调钦命的PHP函数。

  • 略提及Cache工具的规律,Cache组件原理。新手入门教程:

Swoole供给使用者必须拥有一定的Linux/Unix环境编制程序基础,《学习Swoole要求精晓哪些基础知识》
本文列出了基础知识清单。

个中有三个工具类TableManager。这一个类为了处理进程间数据共享。是对swoole_table的一层封装
swoole_table八个依照共享内部存款和储蓄器和锁完结的超高品质,并发数据结构。用于缓解多进度/三十二线程数据共享和共同加锁难点。

Cache是以单例形式达成的。构造器会实行如下操作

上文中提到了针对性php的共享内部存款和储蓄器方案的品尝,最后发现它并不适用于自家的地方,尽管想要包容多进程或二十四线程并发读写的景色下可信,一定要有适当的机制来担保能源的唯一性。

swoole_server

强硬的TCP/UDP
Server框架,二十多线程,伊夫ntLoop,事件驱动,异步,Worker进程组,Task异步任务,飞秒定时器,SSL/TLS隧道加密。

  • swoole_http_serverswoole_server的子类,内置了Http的支持
  • swoole_websocket_serverswoole_http_server的子类,内置了WebSocket的支持
  • swoole_redis_serverswoole_server的子类,内置了Redis服务器端协议的帮忙

子类能够调用父类的具有办法和性质

TableManager首要做了上面几件事
add方法
假使$list数组中有其一表名($name是贰个表名大概叫做集合名),就初叶化swoole_table,然后配置的字段类型数组进行创办

//根据配置创建指定数目的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);
    }
}

加锁肯定是想到的第壹取舍,对于每一趟共享内部存款和储蓄器的时候,先获得1个锁,只有取得成功理解后才同意开始展览读和写,那应该是最简易的方案,不过共同锁对品质的费用也是相比大的。APC的user
data
cache的积存机制对数码需求从严科学,锁比较多,它的功用与本土的memcache万分。既然那样,不如把意见投向产业界,看看大牛们采取什么的方案来化解那一个难点。

swoole_client

TCP/UDP/UnixSocket客户端,支持IPv4/IPv6,扶助SSL/TLS隧道加密,帮助SSL客户端整数,辅助同步并发调用,也支撑异步事件驱动编制程序。

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

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

YAC

原稿链接:http://www.laruence.com/2013/03/18/2846.html

laurance为明白决如下的七个难点,设计出了这几个cache:

  • 想让PHP进度之间共享一些简练的多寡
  • 目的在于万分赶快的缓存一些页面

再者也是依照如下的经历假如:

  • 对此多个用到来说, 同名的Cache键, 对应的Value, 大小差不多非凡.
  • 分歧的键名的个数是容易的.
  • Cache的读的次数, 远远超乎写的次数.
  • Cache不是数据库, 即便Cache失效也不会带来沉重错误.

贯彻这一个cache,关键是无锁化的设计.
根据laurance的说教,他消除读锁的主意是因而不加锁的读,然后CRAV4C校验。
看了瞬间她代码的落到实处,是对key中蕴藏的固定size的值实行了CCRUISERC的总计,然后把key中附带存款和储蓄的crc新闻和剧情总计出来的crc音讯实行校验。假使校验成功了,那么认为查询成功,假诺校验失败了,那么认为查询退步。其实本质上那是一种选拔CPU来换锁的措施,大多数的服务器是多核的,一旦加锁,对CPU是相当大的浪费。下边那张图形象的注明了那或多或少:

美高梅开户网址 1

yac_lock.png

那几个是个正确的trick,能够化解的题材正是在八个经过频仍的写入的时候,恐怕引致的读出错不会带来错误的结果,因为只要crc校验不通过,那么读出来的结果正是失效了。那明显比上一篇小说中的共享内部存款和储蓄器的读的办法要得力一些。可是据他们说自家的考察,使用共享内部存款和储蓄器的点子,由于直接是向后不停的写入,出现被遮盖的票房价值大致从不,而laurance那里之所以要校验,则是因为她会开始展览内部存款和储蓄器的回收和巡回写入,那点在下文中会继续注明。

当今最紧要说说那一个YAC的写入的题材,首先运维的时候key空间尺寸鲜明,能够经过安插来调整分配给存款和储蓄key的轻重缓急,从而扩充key的个数。4M大概约等于327七十一个Cache值。首先第三个很重点的点正是什么样统一筹划哈希方法来幸免写入争论,那里他运用的是双散列法的
MurmurHash.

对于小于4M的内部存款和储蓄器块的操作由于key分裂,根据哈希出来的伊始位置也不一样。不一样key之间争论的概率,等同于哈希算法争持的几率,那一个依旧相比较低的。对于大的内部存款和储蓄器块,那里运用了segment->pos指针来支配内部存款和储蓄器的分块。和共享内部存储器扩张的贯彻格局照旧比较像样了,反正正是一个pos指针,找得到就update,找不到就向后写。

那么一旦发生抵触呢,laurance给出了一个例证:

比如A进度申请了40字节, B进度申请了60字节, 不过Pos只扩充了60字节.
那一个时候有如下两种情景:

  1. A写完了多少, 再次回到成功, 不过B进度又写完了数据重返成功,
    最终B进程的Cache种上了, 而A进度的被踢出了.
  2. B进度写完了数量, 再次来到成功, A进度又写完了数码重返成功,
    末了A进度的Cache种上了, B进度的被踢出.
  3. A进度写2/4, B进程写1/2, 然后A进度又写二分一, B进度又写五成,
    都重回成功, 但最后, 缓存都失效.

足见, 最要紧的一无所能, 正是A和B的缓存都失效,
不过Yac不会把错误数据重返给用户, 当下3回来查询Cache的时候,
因为存在crc校验, 所以都miss.

观看那儿终于领悟了,并从未化解多进程写的题材,多进程的写依旧只怕会有冲突,不仅仅是单key的冲突,差别key之间也说不定会有争持。然而冲突了即使,会经过校验的艺术确定保障client端能够看清出来本人争执了,这一点对应用程序确实不行关键,因为这不是cache
error,而单独是cache
miss而已,那三种意况的要紧程度和拍卖体制真正完全两样。

除此以外还有多个优点是内部存款和储蓄器的循环分配,借使一个内部存储器块用完了,那么能够重置pos,从而从头先河分配,有了那种体制,即便现身写导致pos向来后移,也不会出现内部存款和储蓄器耗尽的情景了,那诚然是个正确的特点。

总计来看,yac四个正确的性状:

  • 读的CEscortC校验,保险最沉痛是cache miss
  • 写的pos重置,保险内存不被写满

只是针对本身的选用情状,多并发情况下的同key的多写多读,它并从未很好的缓解这几个题材,而是比较适用于低频的用户数量的缓存,比如登陆用户的头像、别名那类消息。拉取频次不高,miss了也能向后端请求。所以咋做呢,只可以三番五次开始展览求索。

ps:laurance在篇章初叶群嘲了弹指间APC的品质,也就是地点的memcache,结果文末贴出的性质相比较,yac完全没有apc。。有点莫名

swoole_event

伊芙ntLoop
API,让用户能够直接操作底层的事件循环,将socket,stream,管道等Linux文件加入到事件循环中。

eventloop接口仅可用以socket类型的文书描述符,无法用于磁盘文件读写

get方法
直白重回swoole_table的实例。

ProcessManager::getInstance()这句话主要做了上面包车型大巴操作
ProcessManager
的__construct构造函数成立了3个swoole_table,表名是process_hash_map

Swoole table

接过来说说这两年在社区在那之中比较火,近期恰巧发布了内置协程2.0本子的swoole.
github地址:https://github.com/swoole/swoole-src

swoole
table是swoole中的一个基于共享内部存款和储蓄器和锁达成的超高品质的产出数据结构,用来缓解多进度、十二线程数据共享和协助举行加锁的题材。那不正是我们苦苦追寻的消除方案么?

先来看一下swoole table的常见的运用模式,首先它援救两种基本的品种:

  • swoole_table::TYPE_INT 整形字段
  • swoole_table::TYPE_FLOAT 浮点字段
  • swoole_table::TYPE_STRING 字符串字段

一旦想要在依次进度之间共享高质量的当地数据,那么使用的范例如下:

// 新建swoole table,并且指定类型
$table = new swoole_table(1024);
$table->column('id', swoole_table::TYPE_INT, 4);       //1,2,4,8
$table->column('name', swoole_table::TYPE_STRING, 64);
$table->column('num', swoole_table::TYPE_FLOAT);
$table->create();

// 新建swoole的server
$serv = new swoole_server('127.0.0.1', 9501);
//将table保存在serv对象上
$serv->table = $table;
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    // 使用swoole table存储全局的数据
    $ret = $serv->table->set($key, array('from_id' => $data, 'fd' => $fd, 'data' => $data));
});

// 这里需要注意的就是一定要在server启动之前创建swoole table,从而保证它能够被全局共享
$serv->start();

假若只是你自身的3个历程在分化的伸手之间共享高品质的当地数据,那么使用的范例如下:

class LocalSwooleTable {
    private static $_swooleTable;// 静态变量,单个进程内共享

    const SWOOLE_TABLE_SET_FAILED = -1001;
    const SWOOLE_TABLE_GET_FAILED = -1002;

    // swoole table初始化
    private function __construct() {
        //预估数据量 100个服务,每个长度30 需要3000个字节,这里申请64k
        self::$_swooleTable = new \swoole_table(65536);
        self::$_swooleTable->column('ip',\swoole_table::TYPE_STRING, 64);
        self::$_swooleTable->column('port',\swoole_table::TYPE_INT, 4);
        self::$_swooleTable->column('timestamp',\swoole_table::TYPE_INT, 4);
        self::$_swooleTable->column('bTcp',\swoole_table::TYPE_INT, 4);
        self::$_swooleTable->create();
    }

    // 获取单个swoole的实例
    public static function getInstance() {
        if(self::$_swooleTable) {
            return self::$_swooleTable;
        }
        else {
            new LocalSwooleTable();
            return self::$_swooleTable;
        }
    }
}
// 获取唯一的实例
$swooleTableIns = LocalSwooleTable::getInstance();
$key = "sample";
$routeInfo['timestamp'] = time();
$routeInfo['ip'] = '10.25.22.33';
$routeInfo['port'] = 1000;
$routeInfo['bTcp'] = 1;

// 设置swoole table中的内容
$flag = $swooleTableIns->set($key,$routeInfo);

// 获取swoole table中的内容
$routeInfo = $swooleTableIns->get($key);

当然,第③种方法应该是我们最好的采用,可是因为我们使用了TSF框架(大概其他不是团结开班裸写swoole的框架),都不会把成立server这一步暴露到事情代码中,那就给大家接纳全局的swoole的table带来了相当的大的难度。换句话说,知道好用,不过就是事情用起来11分的不便于,不负有业务扩展性。

所以不得已之下,我们依旧选用了第两种方案,从性质方面来讲的话,确实是有升高的,倒霉的地点便是存款和储蓄能源浪费了部分,每一种进度都用了依附自个儿的swoole
table,那本来是可望而不可及之举。照旧希望能够之后通过有个别改建,把全局的swoole
table这种力量能够开放出来。

美高梅开户网址 2

显示屏快速照相 2017-01-24 清晨5.28.17.png

大多访问2次是0.03ms,那天性子照旧相比杰出的。

swoole_async

异步IO接口,提供了
异步文件系统IO,定时器,异步DNS查询,异步MySQL等API,异步Http客户端,异步Redis客户端。

  • swoole_timer 异步飞秒定时器,能够达成间隔时间或贰次性的定时职责
  • swoole_async_read/swoole_async_write 文件系统操作的异步接口

美高梅开户网址,行使的地方有为数不少
前文提到的在系统设置Cache组件 Cache::getInstance()的时候

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

swoole_process

经过管理模块,能够方便的成立子进度,进度间通讯,进度管理。

构造方法做了如下事情

addProcess($this->generateProcessName($i),CacheProcess::class);
$this->generateProcessName($i)这么些代码相当的粗略正是依据$i来设置进度名称
addProcess 是在processList存款和储蓄CacheProcess::class的实例,具体代码如下

swoole_buffer

有力的内部存款和储蓄器区管理工科具,像C一样实行指针总括,又无需关怀内部存款和储蓄器的提请和刑满释放解除劳教,而且不用担心内部存款和储蓄器越界,底层全部搞好了。

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

swoole_table

基于共享内部存款和储蓄器和自旋锁达成的超高质量内部存款和储蓄器表。彻底化解线程,进度间数据共享,加锁同步等题材。

swoole_table的属性可以高达单线程每秒读写100W次

实际帮扶文书档案地址:

ProcessManager也是三个很重点的定义。其实正是一个管制职分映射的工具。

那么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::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class)

$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,让swoole服务添加了二个历程。swoole的addProcess方法,文书档案链接

__start方法首假若给swoole_table,表名为process_hash_map插入当前CacheProcess的经过名为key,进度IDpid为value。并且注册进程退出的轩然大波。

美高梅开户网址 3

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

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

$this->run($this->swooleProcess)那些函数是CacheProcess借使配置了persistentTime,就会张开1个定时器定时去取$file

Config::getInstance()->getConf(‘TEMP_DI奥德赛’).”/{$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方法加深概念
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和它的相关作用.
}

发表评论

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

网站地图xml地图