php laravel 抢红包防止并发(超卖也是同理)
匿名 · 更新于 2019/12/7
方案1:
原理:后台创建红包后,将红包个数存入redis,采用常量键名拼接红包id 作为key,红包个数为value存入redis,然后当用户领取红包的时候,前端肯定传红包id到后端,后端 先加redis锁,然后根据接收的红包id 读取key对应的值就是红包剩余个数,然后减1后再存入。
具体代码如下(php--laravel)
方案2:(不加锁利用redis原子性,还是建议使用方案一)
首先要了解的是:1.Redis如何保证原子性?
答案很简单,因为redis是单线程。
一、看下面代码(仅仅是看,后面贴的有代码可复制)

分析:通过jmeter并发测试发现仍然出现类似超卖情况,
上图中 llen 和 lpush 两次操作如果单独执行是具备原子性的,但是这两个操作组合起来才算是完成一个业务,那么这2个命令组合起来就不具备原子性,所有在两个操作之间其他客户端会出现脏读。
二、再优化代码如下:
在后台设置红包的时候执行以下操作,

然后用户领取红包请求接口的时候只做一步redis操作。
-
<div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">public</span> <span class="hljs-function" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">function</span> <span class="hljs-title" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(64, 120, 242); overflow-wrap: break-word;">getPacket</span><span class="hljs-params" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;">(Request $request)</span> </span>{</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="2" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"> </div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="3" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">$packet_id = $request->input(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'packet_id'</span>,<span class="hljs-number" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(152, 104, 1); overflow-wrap: break-word;">0</span>);</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="4" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">if</span>(!$packet_id){</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="5" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">return</span> Response::error(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'缺少参数:packet_id'</span>) ;</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="6" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"> </div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="7" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">}</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="8" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">$redisConfig = config(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'database.redis.default'</span>);</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="9" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">$redis = <span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">new</span> Client($redisConfig);</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="10" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">$count = $redis->lpop(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'red_packet_id:'</span>.$packet_id);</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="11" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">if</span>(!$count){</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="12" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">return</span> Response::error(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'已经抢光了哦'</span>) ;</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="13" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">}</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="14" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;"><span class="hljs-keyword" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(166, 38, 164); overflow-wrap: break-word;">return</span> Response::success(<span class="hljs-string" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(80, 161, 79); overflow-wrap: break-word;">'恭喜您,抢到了哦!'</span>) ;</code></div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="15" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"> </div> </div> </li> <li style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; list-style: none; overflow-wrap: break-word; height: 22px;"> <div class="hljs-ln-numbers" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px; width: 24px; border-right: 1px solid rgb(197, 197, 197);"> <div class="hljs-ln-line hljs-ln-n" data-line-number="16" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px 8px 0px 0px; text-align: right; overflow-wrap: normal;"> </div> </div> <div class="hljs-ln-code" style="box-sizing: border-box; outline: 0px; margin: 0px 0px 0px 8px; padding: 0px; overflow-wrap: break-word; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; float: left; height: 22px;"> <div class="hljs-ln-line" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;"><code class="hljs php" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; display: block; overflow-x: auto; color: rgb(56, 58, 66); background: rgb(250, 250, 250); border-radius: 4px; line-height: 22px; white-space: pre; overflow-wrap: break-word;">}</code></div> </div> </li>
总结:
这里利用 redis 操作的原子性来实现。首先我们把 红包个数或者库存 存在“red_packet_id:1”这个列表中,假设id=1的这个红包的可领取个数为10个,就往列表中push10个数,这个数没有实际意义,仅仅只是代表红包的可被领取次数。抢购或者红包到开始领取时间后,每到来一个用户,就从“red_packet_id:1”中 pop 一个数,表示用户抢购成功。当列表为空时,表示已经被抢光了。因为列表的pop操作是原子的,即使有很多用户同时到达,也是依次执行的。
缺陷:1、单纯依靠这总办法解决并发是不够的。
2、这种办法如果红包个数1000个是要往队列插入1000条,方案有点low,
3、队列一般都是用来异步处理,上面方案是同步消费队列返回给前端,所以这种方案不是很完美,但是能够实现。
