行业资讯页面缓存未及时更新的排查分析
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
近期评论