PHP 高并发 统计网页点击次数

2019-03-02 00:30:15 +08:00
 hugee

一般的方法是: "UPDATE base SET hits = hits+1 WHERE id = '$id'";

一般的访问量都没什么问题,但高并发的情况下怎么做? 有什么好的方法可以实现,降低数据库的读写?

7911 次点击
所在节点    PHP
39 条回复
yuikns
2019-03-02 00:32:41 +08:00
stabc
2019-03-02 00:46:18 +08:00
首推 redis。非要放在 SQL 里的话,如果真的达到高并发,可以用个 random,随机每 10 次写入一次数据库,每次加 10。
hilbertz
2019-03-02 00:46:29 +08:00
限制数据库的写入频率,比如说在每个节点上,每隔 10s 才把 hits 写入数据库
hugee
2019-03-02 00:55:18 +08:00
@stabc @yuikns 谢谢,用 redis 防止频繁读取数据库这个我知道,但隔一段时间由 redis 写到数据库还没弄过。
还有,假如 id 为 233 的页面在某一个时间点后再也没人访问了,那缓存内的数据岂不是写不进数据库了?
KasuganoSoras
2019-03-02 00:57:14 +08:00
PHP 搞个队列系统就好了
SQL 语句丢过去,异步执行
ichou
2019-03-02 03:31:35 +08:00
队列
zjsxwc
2019-03-02 08:42:11 +08:00
用 nginx 的话,lua 有个接口叫做:`ngx.shared.stats:incr()` 可以直接用
gouchaoer
2019-03-02 08:59:43 +08:00
在 fpm 里面用 apcu 统计,然后每隔一段时间从 apcu 往数据库写,由于 apcu 在同一台主机上所以不同的 fpm 的时间戳是一样的。比如存 hits 变量,每次访问 apcu_incr 一下 hits,然后去检查 hits_timestamp 是否大于 60s,大于了的话就去 apcu
gouchaoer
2019-03-02 09:06:34 +08:00
在 fpm 里面用 apcu 统计,然后每隔一段时间从 apcu 往数据库写,由于 apcu 在同一台主机上所以不同的 fpm 的时间戳是一样的。比如存 hits 变量,每次访问 apcu_incr 一下 hits,然后去 apcu_add 检查 hits_lock 变量来实现锁的更新数据库逻辑,ttl 参数就是每隔多长时间往数据库里面刷

在 fpm 里面的话,我有自信这个是最优方案,连 Redis 走 tcp 有 io 的,这个没 io
gouchaoer
2019-03-02 09:08:53 +08:00
用队列不觉得扯么?你在 fpm 里面往队列写是不是有 io,然后这个队列还只是 incr 一下数据库一个字段。。。稍微靠谱一点的是直接发 udp 发完就走,不过还得写个接受 udp 的 server 太麻烦了
Maboroshii
2019-03-02 09:12:18 +08:00
进程同步,linux 不是有文件锁么。不知在 php 上是否可行
lestat
2019-03-02 09:13:45 +08:00
我这边的实现是:redis 设置一个 key,每次访问+1,在后台开一个定时任务,每隔一定时间批量写入一次数据库,然后清空 key
gouchaoer
2019-03-02 09:22:41 +08:00
不可以用文件锁,此外往 Redis incr 一个 key 的方案,然后后台开 cron 运维麻烦一点,觉得麻烦可以用 Redis 的 add expire 机制来把更新到数据库逻辑写到业务逻辑里
loveCoding
2019-03-02 09:41:03 +08:00
放队列 , 批量获取,合并更新
dawniii
2019-03-02 09:46:56 +08:00
@gouchaoer redis + cron 算是很简单的了。使用队列也还不错,因为往往不只是一个简单的+1 的操作,虽然有 io,但也是为了访问数据库削峰。您说的 udp 还是不建议的,毕竟可靠性要比其他方案低,之前听人说 udp 本机丢包都不稀奇。apcu 这种假如有 10w 个文章,是需要 10w 个 key 来计数吗? redis 的话用一个 hash 结构的 key 就够了,假如一篇文章被访问几次,然后长期不被访问,岂不是计数一直落不了库了,然后 fpm 重启这些计数都会丢失。
skymei
2019-03-02 09:47:12 +08:00
不去重去 redis 的 string,hash 即可,要去重用 hyperloglog,redis 是单线程的,不会出现并发的问题
leis1015
2019-03-02 09:52:41 +08:00
也可以用第三方的啊,挂个 js 就行了,还能很方便的查看数据

百度腾讯都有…
penghong
2019-03-02 11:24:11 +08:00
hyperloglog
bokchoys
2019-03-02 11:26:15 +08:00
我发现,我之前思考的问题,在 v 站都会出现🤔
ibegyourpardon
2019-03-02 11:33:28 +08:00
朋友,我觉得真的高并发的话,可能你的问题首先不是出在 MySQL 上,而是 php-fpm 上……

当然我不知道你怎么部署的,如果真的若干机器堆住,一般 hold 住也没问题,当然真是这样的话那 Redis 啥的也不算事了。

毕竟不知道你的高并发首先有多高 - -#

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/540212

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX