您的位置:首页 > 编程语言 > PHP开发

TP模型增删改后cache查询缓存无法更新问题的解决办法

2018-03-06 22:19 344 查看
TP模型连贯操作cache方法用于select、find和getField方法,以及其衍生方法,使用cache方法后,在缓存有效期之内不会再次进行数据库查询操作,而是直接获取缓存中的数据。
第一次查询结果会被缓存,第二次查询相同的数据的时候就会直接返回缓存中的内容,而不需要再次进行数据库查询操作。

默认情况下, 缓存有效期和缓存类型是由DATA_CACHE_TIME和DATA_CACHE_TYPE配置参数决定的,但cache方法可以单独指定。

例如:
$Model->where('id=5')->cache(true)->find(); // 自动命名缓存ID,使用系统默认DATA_CACHE_TIME(0=永久有效)
$Model->cache('key',60)->find(); // 自定义缓存ID,60秒后失效

问题:
缓存有效期当然是越久越好,所以默认DATA_CACHE_TIME=0,也就是永久有效。那么问题来了,数据表增删改操作后,如何使查询缓存的数据更新呢?
用S('key',null),那不行,因为查询中用了cache(true),你根本不知道key的具体值,而且如果查询中包含了动态的where查询,那可能会产生多个缓存。

如果设置了缓存有效期cache(true,5),也就是5秒后没有命中该查询缓存的话,缓存会自动失效。这是比较简单的两头兼顾的方法,但是也有问题,在高并发情况下,缓存持续被命中,则缓存持续生效,就没有机会重新从数据表获取增删改后的新数据。对增删改后要求数据查询也立即生效的情景中,缓存刷新成了一个大问题。

综上所述,需改造一下Model类,在select(),find(),getField()方法中,有启用缓存的情况下,增加一个缓存记录逻辑。在add(), save(), delete(), setField()方法中,在有启用缓存的情况下,增加一个清理缓存的逻辑。

==================方法如下:(可作为公开方法放在Model类中,也可以作为函数放在公共函数库function.php中)===================

/**
* 清理数据表查询缓存

* 用于解决数据表增删改操作无法刷新查询缓存(特别是cache(true)自动命名的缓存)的问题
* 只需在增删改操作成功时,调用clear_table_caching($table);
* 即可使对应此表的所有查询缓存失效.

* 默认在模型的add,save,delete,setField等操作中会自动调用

* @param string $table 数据表名称
* @since 1.0 <2015-4-30> SoChishun Added;
*/
function clear_table_caching($table = '') {
$table_caching_keys = F('table_caching_keys');
if (!$table_caching_keys) {
return;
}
// 清理指定表的缓存
if ($table) {
if (isset($table_caching_keys[$table])) {
$values = $table_caching_keys[$table];
foreach ($values as $id) {
S($id, null);
}
unset($table_caching_keys[$table]);
F('table_caching_keys', $table_caching_keys);
}
return;
}
// 清理所有表的缓存
foreach ($table_caching_keys as $values) {
foreach ($values as $id) {
S($id, null);
}
}
F('table_caching_keys', null);
}

/**
* 添加缓存键名到数据表查询集合中

* 用于提供clear_table_caching()方法的数据调用

* 默认在getField,select,find等方法中自动调用

* @param string $table 数据表名称
* @param string $id 缓存键名
* @since 1.0 <2015-4-30> SoChishun Added.
*/
function log_table_cacheing($table, $id) {
$table_caching_keys = F('table_caching_keys');
if ($table_caching_keys && isset($table_caching_keys[$table]) && in_array($id, $table_caching_keys[$table])) {
return; // 如果已经存在则退出
}
$table_caching_keys[$table][] = $id;
F('table_caching_keys', $table_caching_keys);
}
============
使用方法(Model类中):
$this->log_table_cacheing($options['table'], $key); // 记录数据表的缓存键
$this->clear_table_caching($options['table']); // 清除数据表的所有查询缓存
============
希望官方考虑到此问题,发布官方解决方案:)
转载链接    http://www.thinkphp.cn/topic/29716.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  thinkphp 缓存
相关文章推荐