对TP5数据库缓存cache的一些思考

最近在优化代码的时候,突然想起来TP5的数据库操作中有个cache,之前也用过,印象里就是在缓存时间内,请求的速度会大大加快,但是修改数据会导致不能及时更新。当初还比较年轻,没有深入去搞清楚,只是不再使用cache了而已,现在刚好有机会,就来稍微学一学吧。

很可惜,不论是官方文档还是网上搜索出来的结果,基本上都只是告诉我们如何去使用它,完全没有说到它的工作原理之类的,无奈,只能去慢慢读源码了。

首先让我感到疑惑的是,这个cache和我们平常用的缓存Cache有什么区别?

如果单单从功能上看的话,好像两者没有任何区别,都能设置key值和有效期,以及打标签也都支持。随后我做了个实验,手动设置key名,然后用cache()助手函数去读取,结果如我所料,读取出来的结果果然是select的结果。

$result = db('my_table')->where($where)->cache('key',10)->select();

var_dump(cache('key'));  //结果和$result一样

不过实验归实验,还是得去源码里看看具体是如何实现的。

进入/thinkphp/library/think/db/Query.php中,找到cache方法,可以看到,这里只是设置了属性,真正的使用还不在这里,还得去select、find、value、column里面看。

//源码太长了,就不一一复制了public function cache($key = true, $expire = null, $tag = null){    // 增加快捷调用方式 cache(10) 等同于 cache(true, 10)    if ($key instanceof \DateTime || (is_numeric($key) && is_null($expire))) {        $expire = $key;        $key    = true;    }    if (false !== $key) {$this->options['cache'] = ['key' => $key, 'expire' => $expire, 'tag' => $tag];}    return $this;}public function select($data = null){    ......    if (empty($options['fetch_sql']) && !empty($options['cache'])) {        // 判断查询缓存        $cache = $options['cache'];        unset($options['cache']);$key      = is_string($cache['key']) ? $cache['key'] : md5($this->connection->getConfig('database') . '.' . serialize($options) . serialize($this->bind));        $resultSet = Cache::get($key);}    ......    if (isset($cache) && false !== $resultSet) {// 缓存数据集

        $this->cacheData($key, $resultSet, $cache);}    ......}protected function cacheData($key, $data, $config = []){    if (isset($config['tag'])) {        Cache::tag($config['tag'])->set($key, $data, $config['expire']);    } else {Cache::set($key, $data, $config['expire']);}}

结论:可以很明显地看出,不论是写入缓存还是从缓存中读取,都是与我们常用的Cache一样的,唯一不同的是,如果你不指定key名的话,他会根据操作的数据库名、表名以及主键ID等信息,帮你生成一个32位密文,你也不用担心万一key名重复导致缓存覆盖了。

疑惑二当数据更新时,缓存会怎么样呢?

按照文档上的说法,要么手动在update等更新操作中添加cache,来实现手动更新缓存;要么使用find方法并且使用主键查询,就会自动清理缓存。手动指定缓存倒没什么问题,除了不触及缓存操作的新增之外,在数据更新后缓存都会被清除,然后在查询时重新被写入。PS:增删改查中,新增操作是不触及缓存的,这也是缓存要谨慎使用的原因,虽然能够极大地增加效率,但是不能反映数据的及时更新。

然后就是什么情况下更新数据能够自动清除缓存的问题了。比较麻烦的是,涉及到缓存操作的话,是否使用主键作为查询条件还不一样。也就是说,会有以下2*2+2*2共八种组合。

用主键做条件进行查询+用主键做条件进行修改——清除

用主键做条件进行查询+用主键做条件进行删除——清除

用主键做条件进行查询+不用主键做条件进行修改——不清除

用主键做条件进行查询+不用主键做条件进行删除——不清除

不用主键做条件进行查询+用主键做条件进行修改——不清除

不用主键做条件进行查询+用主键做条件进行删除——不清除

不用主键做条件进行查询+不用主键做条件进行修改——不清除

不用主键做条件进行查询+不用主键做条件进行删除——不清除

虽然还有很多情况没有测试到,比如更新操作的数据是否为缓存的数据、查询和更新操作的条件是不是一样等等,即使测试的结果和文档上描述的一样,但是还是感觉说服力不够强,还得再去源码里找找原因。这里以update操作为例。

//如果有设置缓存名,则直接从cache中读取

if (isset($options['cache']) && is_string($options['cache']['key'])) {

    $key = $options['cache']['key'];

}

......

//如果没有手动设置缓存,则只能依靠主键ID以及操作的表来识别,否则没有办法识别出来

} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {

    $key = $this->getCacheKey($options['where']['AND'][$pk], $options, $this->bind);

}

结论:只有当查询和修改操作都使用主键ID作为条件时,才能实现自动清除缓存。

所以说,数据库缓存并不是随便用的,如果使用不当,很容易影响数据的时效性和用户的体验。如果真的有必要使用的话,最好还是不要偷懒用自动清除缓存,还是手动设置缓存名字,以及在更新操作时指定清除哪个缓存。

好了,不知不觉又花了半个晚上,今天就这样吧,洗洗睡了。

另外,如果你有兴趣,或者是有问题想要与我探讨,欢迎来访问我的博客:https:mu-mu.cn/blog

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容