Tencent / Biny

Biny is a tiny, high-performance PHP framework for web applications
BSD 3-Clause "New" or "Revised" License
1.69k stars 258 forks source link

数据库缓存的问题想请教一下 #118

Open 3DMXM opened 4 years ago

3DMXM commented 4 years ago

抱歉,我不太懂数据库缓存方面的知识, 之前也没做数据库缓存(也没考虑到), 最近网站浏览量有点大,高峰期的时候数据库有点撑不住了, 然后才考虑来整个缓存。。。

我设置了$_pkCache = true;

然后我看wiki上有个 //参数为pk值 返回 ['id'=>10, 'name'=>'test', 'time'=>1461845038] $data = $this->testDAO->getByPk(10);

这个是在单表的情况下通过id(我猜是通过$_pk = 'id'来设置的)来获取, 如果我需要leftJoin多个表的时候,要怎么办

billge1205 commented 4 years ago

是的 你理解的没问题 pkCache开启后 就是根据pk进行自动单表单行数据缓存 如果你要复杂查询或者连表查询的话 ,建议自己redis设key处理

$cache = $redis->get('xxxx');
if (!$cache){
    $cache = $this->xxxService->getData();
    $redis->set('xxxx', $cache);
}
3DMXM commented 4 years ago

您好,再问个问题,wiki上说 开启$_pkCache的DAO不允许再使用update和delete方法,这样会导致缓存与数据不同步的现象; 是不是需要用 updateByPk和deleteByPk 这两个方法来代替的意思

billge1205 commented 4 years ago

对的 你可以这么理解update 和 delete是不走缓存直接操作的数据库 如果要保证db 和 cache一致 就都需要用updateByPk 和 deleteByPk替代 否者就可能存在getByPk时数据不一致的情况

3DMXM commented 4 years ago

啊~那岂不是之前写的update全部都得改一遍。。。

billge1205 commented 4 years ago

这种其实不建议全局修改了 如果有遗留可能会有风险 还是针对部分功能额外自行添加缓存操作比较好

3DMXM commented 4 years ago

在原有的update后面再加个updateByPk 会有影响吗

billge1205 commented 4 years ago

那数据库其实是更新了两遍 第二遍的影响行数可能就是0了 update失败会不更新缓存 不建议这么使用 另外如果有遗漏未修改的 出现问题也不好查 因为这个原因 所以Biny在新版本里默认都设为false了 一般都是项目初期就全走dbcache比较保险

3DMXM commented 4 years ago

那我还是把之前的update全换成updateByPk 吧,方法应该都通用支持的吧,比如说 // update DATABASE.TABLE set type=type+5 $result = $this->testDAO->filter(["id"=>10])->update(['type'=>['+'=>5]]); 改成 $result = $this->testDAO->updateByPk (10,['type'=>['+'=>5]]);

billge1205 commented 4 years ago

卧槽 发现['type'=>['+'=>5]] 这种会有问题 稍等 我修改支持一下

3DMXM commented 4 years ago

诶,诶~

我之前写在浏览量+1上面,没有问题呀

billge1205 commented 4 years ago

baseDAO.php 里修改一下 支持+-*/算法 试试

/**
     * 更新主键
     * @param $pk
     * @param $sets
     * @return bool
     */
    public function updateByPk($pk, $sets)
    {
        $cond = $this->buildPK($pk);
        $flag = $this->filter($cond)->update($sets);
        if ($flag && $this->_pkCache && $cache = $this->getCache($pk)){
            foreach ($sets as $k => $v) {
                if (is_array($v)) {
                    // ['type'=>['+'=>5]]
                    foreach ($v as $cal => $num) {
                        $cache[$k] = eval("return {$cache[$k]} $cal $num;");
                    }
                } else {
                    $cache[$k] = $v;
                }
            }
            $this->setCache($pk, $cache);
        }
        return $flag;
    }
3DMXM commented 4 years ago

好的

3DMXM commented 4 years ago

我发现个问题,如果: 数据库click_cnt的值是10 缓存click_cnt的值是9;

使用 $this->modsDAO->updateByPk($id,array('click_cnt'=>array('+'=>1))); 后, 数据库click_cnt的值是11 缓存click_cnt的值是10;

它不统一。。。

billge1205 commented 4 years ago

那是因为之前不统一导致的 如果使用pkcache的话必须保证db 和 cache一直是同步的 所以不能再用update和delete操作了 你测试环境可以先用clearCache方法先清理下缓存保持一致后再试