You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Varnish时,如何统计基于PHP Laravel MySQL的新闻网站页面浏览量?

针对高访问量新闻站的浏览量统计方案(适配Laravel+Varnish技术栈)

咱先对齐你的核心诉求:高并发场景下的新闻浏览量统计,要靠谱、不拖垮性能,还要用成熟的标准方案,别自己瞎折腾轮子。结合你用的PHP/Laravel/MySQL/Varnish技术栈,给你整理几个工业界常用的路子:

1. Varnish侧异步统计(首推,完美适配你的架构)

既然你已经用上了Varnish做前端缓存,那直接在缓存层处理统计请求是最高效的——不用让请求穿透到后端Laravel,避免给后端加压力。具体玩法:

  • 在VCL的vcl_deliver阶段,判断当前请求是新闻详情页(比如匹配/news/[0-9]+这样的URL规则),然后异步发起一个统计请求到后端的轻量接口(别阻塞主请求!)
  • 后端不用直接写MySQL,先把浏览量打到Redis里——Redis的incr命令性能拉满,扛几万QPS都没问题
  • 最后用Laravel的任务调度(Schedule),比如每5分钟跑一次脚本,把Redis里累计的浏览量批量同步到MySQL主表,这样既保证了性能,又能让数据落地供业务使用

举个VCL代码片段参考:

sub vcl_deliver {
    # 匹配新闻详情页的GET请求
    if (req.url ~ "^/news/\d+" && req.method == "GET") {
        # 标记要统计的请求
        set req.http.X-News-View = "1";
        # 用异步请求发送统计数据到后端接口,不阻塞主响应
        async(0, "POST", "/api/log-news-view", 
              "Content-Type: application/json", 
              "{\"news_id\":\"" + regsub(req.url, "^/news/(\d+)$", "\1") + "\"}");
    }
}

Laravel端的统计接口逻辑也很简单:

// routes/api.php
Route::post('/log-news-view', function(Request $request) {
    $newsId = $request->input('news_id');
    // 用Redis累加浏览量
    Redis::incr("news:views:$newsId");
    return response()->json(['status' => 'ok']);
});

然后在app/Console/Kernel.php里加个定时任务:

protected function schedule(Schedule $schedule) {
    // 每5分钟同步一次浏览量到MySQL
    $schedule->call(function() {
        // 遍历所有有累计浏览量的新闻ID
        $keys = Redis::keys('news:views:*');
        foreach ($keys as $key) {
            $newsId = str_replace('news:views:', '', $key);
            $count = Redis::get($key);
            if ($count > 0) {
                // 批量更新到MySQL
                DB::table('news')->where('id', $newsId)->increment('views', $count);
                // 清空Redis里的累计数
                Redis::del($key);
            }
        }
    })->everyFiveMinutes();
}

2. Google Analytics(GA4):适合宏观分析,不适合业务实时展示

如果你的需求只是看整体流量、用户行为这类宏观数据,GA4是现成的工具,不用自己开发。但它有个硬伤:数据有延迟,而且没法直接和你的业务数据库联动——比如你想在新闻页显示“XX次浏览”,用GA数据就不太现实,因为它的API导出数据慢,而且统计逻辑和业务需求不一定匹配。所以这个方案适合做报表分析,不适合业务层面的实时统计。

3. 前端非阻塞上报(优化你之前的AJAX思路)

你之前想的随机AJAX其实可以优化成更靠谱的版本:用navigator.sendBeacon()来发送统计请求——这个API是浏览器专门为异步上报设计的,不会阻塞页面卸载,比普通AJAX更可靠。还可以加个本地存储缓存,比如用户浏览3条新闻后再批量上报,减少请求数。

但这个方案的问题也很明显:如果用户禁用JS、页面没加载完就关闭,统计数据会丢;而且高并发下前端请求太多,不如Varnish侧处理高效。所以适合流量不大的场景,你的高访问量站不太推荐。

4. MySQL批量更新:万不得已的兜底方案

如果不想用Redis,也可以直接在MySQL层面做优化:别每次请求都直接更新新闻表的views字段,而是把浏览请求放到Laravel队列里,攒够100条或者等个1分钟,再批量更新到数据库。或者用中间表过渡:先把浏览记录写到news_view_logs表,再定时把日志表的数据聚合到主表。但这个方案的性能不如Redis,高并发下还是会给DB加压力。


总结一下:结合你的高访问量场景,Varnish+Redis+Laravel定时任务是最成熟的标准方案——既保证了性能,又能准确统计,还完全适配你的技术栈,不用自己造轮子。

内容的提问来源于stack exchange,提问作者alex toader

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:37:12