问答

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

作者:admin 2021-07-19 我要评论

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

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

问题描述

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

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

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

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

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

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

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

###

利用 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。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • PHP接口高并发有什么简单的解决思路?

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

  • 时段块鼠标按下、拖动、释放 jquery 正

    时段块鼠标按下、拖动、释放 jquery 正

  • 如何让 react-native start 不显示log

    如何让 react-native start 不显示log

  • python比较类型不匹配

    python比较类型不匹配

腾讯云代理商
海外云服务器