并发太大导致的数据库“溢出”问题

我做了一个扫码签到软件,其基本的逻辑如下:

1、判断扫码者是否扫码过,如果已经扫码过禁止重复扫码,如果没有扫码过进入步骤2;

2、扫码,写入数据,返回成功。

问题是:

同一秒扫码的人数可能有点多(高峰期在一两百人左右),服务器有点反应不过来,

很多人的扫码请求卡在了步骤一和步骤二之间(验证通过,等待写入扫码数据),问题就出在这里:

因为手机上一直转圈圈,很多人没有耐心,于是重新扫码,因为其前一个请求处于等待写入的状态,此时步骤一的判断依然会对其放行(因为还没写入成功扫码的表中),让其第二个请求成功进入步骤二,这就造成写入了两个扫码成功,造成签到重复。请问有啥好办法能解决这个问题呢?

评论区

杜福忠

2019-07-15 21:06

这个业务, 要是我来做, 并发200多, 这个不多啊, 不用列队吧, 目前云数据库最低配置也都有600连接数,应该是SQL写的或表结构有问题. 假定就支持200, 那应该做成异步的, 扫完后, 让等待结果通知就好了. 或者二次扫描时发现已经签到成功, 返回提示已经签到成功, 是有什么问题吗?

flash866

2019-07-15 21:10

此问题已经解决,换了思路,通过数据库的多字段unique索引解决了。。。java端只需要抛异常即可

快乐的蹦豆子

2019-07-16 12:32

请求来了先获取单例lock, 然后lock.trylock锁住代码, 返回false就代表上一个请求还在执行,直接返回异常就行,如果可以锁住,再判断是否已经扫码了,如果没扫就插入,扫了返回异常。

简单代码

2019-07-19 12:23

用队列不是最简单吗?请求来了全部插入队列,一个一个处理。

flash866

2019-07-23 21:07

@快乐的蹦豆子 这样是不是把多线程变成了单线程呢?这样会不会造成并发能力变差?

flash866

2019-07-23 21:09

@简单代码 jfinal的队列用什么比较好呢?我对于web方式的队列感觉也不太理解,比如同一个人,连续发了两个请求,那么队列里面,第一个请求的socket已经断开连接了,里面的代码还会继续执行吗?

简单代码

2019-07-23 23:33

@flash866 队列都是服务器,同一个人,连续发了两个请求,那么队列里面,第一个请求和第二个都会推送到队列服务器,队列服务器再依次或者同时调用注册的处理程序(自己选择是否并行处理)。

快乐的蹦豆子

2019-07-24 09:22

@flash866 锁是针对用户的,不是都锁了,每个用户一个锁

flash866

2019-07-24 17:22

@快乐的蹦豆子 能否来一段简短的示例代码学习下

快乐的蹦豆子

2019-07-24 17:29

@flash866 看下 com.jfinal.plugin.ehcache.CacheInterceptor 这个类吧,思路类似

flash866

2019-07-24 19:39

zeroabc

2019-07-25 14:09

Guava RateLimiter

flash866

2019-07-31 05:05

@zeroabc 这个不错,第一次听说