高并发-「抢红包案例」之一:SSM环境搭建及复现红包超发问题

* * <br> <br> $(document).ready(function () {<br> //模拟30000个异步请求,进行并发<br> var max = 30000;<br> for (var i = 1; i <= max; i++) {<br> //jQuery的post请求,请注意这是异步请求<br> $.post({<br> //请求抢id为1的红包<br> //根据自己请求修改对应的url和大红包编号<br> url: "./userRedPacket/grapRedPacket.do?redPacketId=1&userId=" + i,<br> //成功后的方法<br> success: function (result) {<br> }<br> });<br> }<br> });<br>






这里我们使用了 JavaScript 去模拟 3 万人同时抢红包的场景 . 请使用 Firefox进行测试(Chrome老是丢失请求,IE慢)

JavaScript 的 post 请求是一个异步请求,所以这是一个高并发的场景,它将抢夺 id 为1的红包 , 依据之前 SQL 的插入 , 这是一个 20 万元的红包 , 一共有两万个,那么在这样高并发场景下会有什么问题发生呢?

注意两个点 : 一个是数据的一致性,另外一个是性能问题


运行测试

启动tomcat,前端访问 http://localhost:8080/ssm_redpacket/grap.jsp

如果有日志,记得调成error级别,或者不打印日志。

我这里的mysql是部署在虚拟机中,CPU和内存的配置都不高。 内存1G。


超量发送的BUG验证

模拟高并发场景的抢红包后,两个维度进行统计

  • 1:数据一致性
  • 2: 性能

抢红包一致性统计:

SELECT
a.id,
a.amount,
a.stock
FROM
T_RED_PACKET a
WHERE
a.id = 1
UNION ALL
SELECT
max(b.user_id),
sum(b.amount),
count(*)
FROM
T_USER_RED_PACKET b
WHERE
b.red_packet_id = 1;
高并发-「抢红包案例」之一:SSM环境搭建及复现红包超发问题

使用 SQL 去查询红包的库存、发放红包的总个数、总金额,我们发现了错误,红包总额为 20 万元,两万个小红包,结果发放了 200020元的红包, 20002 个红包。现有库存为-2,超出了之前的限定,这就是高并发的超发现象,这是一个错误的逻辑 。


抢红包性能统计:

SELECT
(
UNIX_TIMESTAMP(max(a.grab_time)) - UNIX_TIMESTAMP(min(a.grab_time))
) AS lastTime
FROM
T_USER_RED_PACKET a;
高并发-「抢红包案例」之一:SSM环境搭建及复现红包超发问题

一共使用了 190 秒的时间,完成 20002 个红包的抢夺,性能一般。。。但是逻辑上存在超发错误,还需要解决超发问题 。


超发问题解决思路

超发现象是由多线程下数据不一致造成的,对于此类问题,如果采用数据库方案的话,主要通过悲观锁和乐观锁来处理,这两种方法的性能是不一样的。

接下来我们分别使用悲观锁、乐观锁、Redis+lua的方式来解决这个超发问题。

关注我:私信回复“架构资料”获取高并发抢红包直播视频


分享到:


相關文章: