假设一个抢购系统,每天 16:16:00 到 16:17:00 的 1分钟 内 每10s 放出一个产品进行抢购,中奖用户的计算是 单次每轮(每 10 s内),第一个点击 我要抢购 按钮的人为中奖用户。
情况是:在短暂的 10s 内假设有 5千万个用户 参与了,且在 短短的 第1s内 ,集中了 4千万个用户 点击了 我要抢购按钮。
由于 php 只能够精确到 us(微妙,microtime 函数可获取),1s = 100 0000us ,而在短暂的 1s 内却集中了 4千万个用户同时点击我要抢购按钮。
于是,并发问题就来了。
总会发生在 1us内有多个用户同时点击我要抢购按钮,于是这轮抢购结束后,统计结果,就会出现错误的现象:一轮抢购居然有多个人同时中奖了!
所以,我一开始还打算用 microtime() 来解决并发问题,但是如果出现了我上面描述的情况时,先不论数据库能不能再短时间内承受住如此大量的插入操作,即使承受住了,程序也照样会出错!
我听说 redis 是解决并发的良药,不知道他解决这种问题的原理是什么??
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
题主总是过于纠结 “时间精确度”,这个是没有意义而且是错误的用词。
我们看看题主真正的问题。
我们假设服务器的处理速度是100并发每秒。而现在有一个商品,在某一秒开启抢购。有2个用户参与抢购,按照题主的理解,这就可以直接无压力搞定了。
但是实际上并不是,哪怕只是两个用户抢购一个商品。甚至一个用户抢购一个商品,也要需要借助数据库并发锁实现防止重复读取数据。
所以,抢购程序的开发,关键在于
锁,而不是并发数,或者“时间精确度”你需要解决的不是「高并发」,而是在并发时会发生的竞态。跟多线程编程一样的,所以也可以用类似的思路:用锁。
你用 SQL 数据库的话,可以用事务来解决。但是你这么高的并发交给数据库显然会太慢。Redis 作为内存数据库,实现得又好,所以速度飞快。然后呢,解决竞态,还是靠人来编程解决。Redis 只是提供了足以解决问题的工具。
推荐《Redis 实战》一书,写得很好。你可以直接跳过基础(或者扫两眼,如果你没用过的话),看后边实践的部分(这部分在我给的链接上不能试读。下单吧,值得的。)
仔细读了一下你的需求,好像解决起来挺容易的。你到时间把一个 token 放到特定的 list 里去,然后大家来取(lpop 或者 rpop),谁取到算谁的。(单个)Redis 是不支持并行的,所以不会取重。不过 40m/s 的请求,单个 Redis 实例搞不定的样子……你先试试看吧。不知道你 PHP 是怎么搞定这么高的并发的。
去年,在做
pv|uv统计的时候我采用了redis,看了一些书,因为其操作都是内存中进行的,并且拥有表的概念,所以速度飞快,只是解决了数据库压力,楼主说的4000w并发...倒是没有真正应用上,其实楼下知道的麻烦告知大家,贴一个以前写的redis类帮助各位大佬快速回忆一下redis实现了一个异步库,有人把它拿出来了叫libae,感兴趣可以看一下代码,GitHub上有。另外,我觉得,4000w的并发,redis也hold不住吧
自己看REDIS的源码吧。