PHP接口高并发有什么简单的解决思路?

问题描述

目前我们有一个虚拟卡密提取接口,时常会有高并发请求的情况,每个请求进来后,必须马上返回分配的卡密数据,并标记为已提取。

当遇到高并发时候,就会出现同一卡密发给多人的情况。

问题出现的平台版本及自己尝试过哪些方法

查阅资料后,尝试过flock的文件锁,但是并发上来后,CPU马上跑满了,所有请求都堵死了,根本无法执行下去。

考虑如果使用消息队列的话,虽然能马上完成一次请求,避免重复领取,但是实际的出队和数据库的修改操作都是异步执行了,请求结束后,不能马上得到提取结果,一个提取动作只能分成两个步骤去完成了(效率比较低)

你期待的结果是什么?实际看到的错误信息又是什么?

有没有什么办法,能让每次请求都能得到结果,并且避免重复领取(偶尔出现个别重复是可接受的)简单办法?

阅读 5.5k
5 个回答

利用 Redis 的Queue处理即可

  1. 将卡密数据的 ID同步一份到 Redis
  2. 处理请求时使用LPOP从Redis 获取卡密的 ID,获取失败则证明没卡密了
  3. 获取到卡密 ID 之后正常发号即可。

LPOP是经常用来处理秒杀、抽奖之类场景的

做一个卡密池,无限循环保证卡密池有数据,用户从卡密池里拿数据行吗

设计思路可以这样。请求并发高的话,已经决定了,只能用队列削峰。
你可以做一个设计,做一个预生成的功能,预先把生成的卡密存储到数据和队列A。假设队列A存储了卡密(card-no,card-secret),
用户请求的时候,消费队列A,同时向队列B(保存卡密-用户映射关系)push一条数据,数据有(card-no,user-id)
队列A 可以做个统计,当数量不够的时候,触发批量预生成。然后队列B可以酌情根据服务器的负载,数据的IO决定啥时候做持久化入库。

什么消息队列都是扯淡。因为这是需要同步返回数据的。

先想想,目前的瓶颈在哪?肯定是数据库啊。

你每次都去数据库查询,数据库才是瓶颈。所以从这里入手。

你为什么不把卡密数据放到redis里面?

10万个人的卡密数据,都存进redis,多大的成本?占多大的空间呢?

1秒钟多少并发?1000次?5000次?就算不用redis,用mongo之类的数据库,这点并发,一台普通的云服务器都能轻松胜任吧?所需要的成本也不过一个月几百块钱。

可以试试在卡密表上增加用户uid。

领取的时候一条sql查询出一条不存在uid的记录把uid存进去。这样就不会把同一个卡密分配给不同用户。

卡密表:card,用户字段:uid(默认值0)

update card set uid=1 where id=(select minid from (SELECT min(id) as minid FROM card WHERE uid=0) as a)

如果一个用户只能领取一次的话,执行前先判断一下卡密表中是否已经存在用户uid。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题