直接用 cache::inc() 配合唯一可区分维度的 key(如 api:mobile:count:{path})实现高并发下准确计数,redis incr 原子操作保障线程安全,中间件统一拦截过滤无效请求,数据库仅用于定时归档。

直接用 Cache::inc() 配合合理 key 设计,就能在高并发下准确统计移动端接口请求量;数据库写入或文件日志只适合低频或审计场景,别在入口层硬扛。
用 Redis INCR 做原子计数(推荐)
移动端接口通常并发高、响应快,必须避免数据库锁和文件 I/O 竞争。ThinkPHP 自带的 Cache::inc() 底层调用 Redis 的 INCR 命令,天然线程安全。
- key 必须唯一且可区分维度:建议格式为
api:mobile:count:{接口路径}或加用户标识api:mobile:count:user_{uid}:{path} - 不要在 key 里塞时间戳(如
...:20260817),改用 TTL 控制生命周期:Cache::inc('api:mobile:count:/api/v1/order/list', 1, 3600) - 如果要按天汇总,不要靠 key 拆分,而是用定时任务(如每小时执行一次
php think api:sync-count)批量读api:mobile:count:*并写入数据库归档表 - 注意:Redis 连接必须配置为
redis://127.0.0.1:6379?database=2这类显式库号,避免和其他缓存 key 冲突
中间件中统一拦截并计数
把计数逻辑收口到中间件,避免每个控制器重复写。关键不是“记录”,而是“不漏、不重、不卡”。
- 在
app/middleware/MobileApiCounter.php的handle()方法里做判断:if (strpos($request->header('User-Agent'), 'Mobile') !== false || $request->isMobile()) - 只对
GET和POST接口计数,跳过OPTIONS预检请求:if (in_array($request->method(), ['GET', 'POST'])) { ... } - 用
$request->url(true)获取完整路径(含 query),但建议只取$request->path()作为 key 主体,否则带 token 或 timestamp 的 URL 会导致 key 泛滥 - 别在中间件里查数据库或发 HTTP 请求,会拖慢所有移动端接口响应
数据库落库仅用于归档,非实时统计
如果你需要导出报表、做审计或关联用户行为,才把 Redis 数据定时刷进数据库;日常看板数据应直接从 Redis 读。
- 建表字段至少包含:
id、api_path(VARCHAR 255)、date(DATE)、count(INT UNSIGNED) - 归档脚本里用
Cache::getMultiple(array_keys($keys))批量读,再用Db::name('api_mobile_daily')->insertAll($data)批量写,别单条 insert - 归档完成后必须调用
Cache::deleteMultiple($keys)清空对应 key,否则第二天数据会重复累加 - 千万别在每次请求时都写数据库——哪怕用了队列,也比 Redis 多出 2~3 倍延迟,移动端用户等不起
容易被忽略的移动端特有问题
移动端请求不像 PC 端稳定,网络抖动、App 后台保活、WebView 预加载都会导致异常调用,光计数不够,得加过滤。
- 微信内置浏览器、QQ 浏览器等常伪造
User-Agent,单靠字符串匹配不保险;建议配合$request->header('X-Requested-With') === 'XMLHttpRequest'辅助识别 - 某些安卓 App 会静默重试失败请求,可在中间件里检查
$request->header('X-Retry-Count')(需前端约定透传)并跳过计数 - 如果接口返回 401/403,说明是未登录或 token 过期,这类请求不应计入有效调用量,计数前先确认
$request->has('token')或检查 Auth 中间件是否已通过 - CDN 或网关层可能缓存了响应,导致真实后端没收到请求却有前端上报——此时计数必须放在网关层,ThinkPHP 层无能为力
真正难的不是怎么写那几行 Cache::inc(),而是想清楚哪些请求该计、哪些该滤、数据什么时候落库、以及当 Redis 宕机时有没有降级方案(比如临时切到文件计数并告警)。这些决策点,代码里不会自动告诉你。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











