行业资讯页面缓存未及时更新的排查分析
1、行业资讯页面缓存未及时更新 。当后台添加了新的文章后,前台的列表页面未及时更新,总是需要等上 5 分钟后才更新,感觉页面缓存的依赖未生效。后台的最新的两篇文章未同步在前台更新。如图1
2、但是同样的程序在本地环境是正常可用的。仔细分析差异,发现生产环境的后台的文章的更新时间要较之北京时间 早 8 小时。如果 updated_at 存的是 UTC 时间(即比北京时间晚 8 小时),而你用的是北京时间做判断(比如看页面没更新),会出现:
数据实际已更新(北京时间 15:30),
但 updated_at 是 2025-06-05 07:30:25(UTC),
所以缓存判断依赖的 MAX(updated_at) 没变化,页面继续用旧缓存。
public function behaviors()
{
$request = Yii::$app->request;
$alias = $request->get('alias');
$id = $request->get('id');
$categoryId = (int)$request->get('c', 0);
$keyword = trim($request->get('k'));
$tag = $request->get('tag');
$page = (int)$request->get('page', 1);
$detect = new MobileDetect();
$isMobile = $detect->isMobile() ? PageElementType::DEVICE_TYPE_MOBILE : PageElementType::DEVICE_TYPE_PC;
$behaviors = [];
// view 页面缓存
if (!empty($alias)) {
$dependency = new DbDependency([
'sql' => 'SELECT updated_at FROM articles WHERE alias = :alias LIMIT 1',
'params' => [':alias' => $alias],
]);
} elseif (!empty($id)) {
$dependency = new DbDependency([
'sql' => 'SELECT updated_at FROM articles WHERE id = :id LIMIT 1',
'params' => [':id' => $id],
]);
} else {
$dependency = null;
}
$behaviors['pageCacheView'] = [
'class' => PageCache::class,
'only' => ['view'],
'duration' => 300,
'variations' => [$id, $alias, $isMobile],
'dependency' => $dependency,
'cache' => 'fileCache',
];
// index 页面缓存,仅当无关键词和标签时启用
if ($keyword === '' && empty($tag)) {
$category = null;
if (!empty($alias) && UrlHelper::isValidAlias($alias)) {
$category = Yii::$app->db->cache(fn() => ArticleCategory::find()
->where(['alias' => $alias, 'status' => CommonArticleCategory::STATUS_NORMAL])
->limit(1)
->one(), 300);
} elseif (!empty($categoryId)) {
$category = Yii::$app->db->cache(fn() => ArticleCategory::find()
->where(['id' => $categoryId, 'status' => CommonArticleCategory::STATUS_NORMAL])
->limit(1)
->one(), 300);
}
if ($category !== null) {
// 有分类筛选,仅依赖该分类的文章更新时间
$indexDependency = new DbDependency([
'sql' => 'SELECT MAX(updated_at) FROM articles WHERE status = 1 AND category_id = :categoryId',
'params' => [':categoryId' => $category->id],
]);
} else {
// 无分类筛选,才依赖全表(不建议再进一步切分,否则复杂度会上升)
$indexDependency = new DbDependency([
'sql' => 'SELECT MAX(updated_at) FROM articles WHERE status = 1',
]);
}
$behaviors['pageCacheIndex'] = [
'class' => PageCache::class,
'only' => ['index'],
'duration' => 300,
'variations' => [
$categoryId,
$alias,
$page,
$isMobile,
],
'dependency' => $indexDependency,
'cache' => 'fileCache',
];
}
return $behaviors;
}
3、查看 php.ini 中的时区设置,其与 date.timezone = Asia/Shanghai 是等效的。决定修改为 date.timezone = Asia/Shanghai
date.timezone = PRC
4、设置 MySQL 连接时区,确保你的 PHP 连接数据库时设置了时区为 +08:00。在 Yii2 中可以这样做:
'components' => [
'db' => [
// ... 其他配置
'on afterOpen' => function($event) {
$event->sender->createCommand("SET time_zone = '+08:00'")->execute();
},
],
],
5、编辑一篇文章后,其更新时间已经是北京时区。如图2


近期评论