node.js - 抽奖码设计问题
问题描述
程序的逻辑:
程序事先生成了抽奖码存在mysql中,然后有用户来的以后,找到一个没有用过的抽奖码给他,然后把这个抽奖码设置成为已经使用过了
问题:当大量用户同时并发请求的时候,大部分用户返回同一个抽奖码
原因大概是这样子的
select codeid,codevalue from tb_code where isused=0 Limit 1
通过上面的sql找到一个没有使用过的抽奖码
update tb_code set isused=1 where codeid=codeid
然后上面的sql语句是更新为已经使用
当大量用过过来的时候,比如A先取到一个码XYBV,但是还没有更新,B用户也过来了的时候找到的也是这个码值了。
code的返回都是在执行完update以后返回
后来修改了下更新语句
update tb_code set isused=1 where isused=0 and codeid=codeid
根据affectedRows来判断是不是更新成功了,如果成功的话,则返回code,否返回一个null
这样虽然不会返回重复的值,但是会有一部分收不到码值
再后来的搜了下,使用直接更新查找到码值,最后再通过ranomno来查找刚才更新的码值,如下面所示的sql
update tb_code set isused=1,randomno=’+randomno+’ where codeid in ( select codeid from (select codeid from tb_code where isused=0 Limit 1) as arbitraryTableName)’;
刚开始本地测试的时候,没有问题,想着解决了。后来上线,检测日志的时候,发现很多请求长时间没有响应,应该是上面的sql语句执行的效率太低了。
最后换了一种方法使用redis缓存code
先从库里面取1000个code使用Lpush放去redis里面去,然后当用户有请求过来,直接从redis里面取Rpop
然后做一个定时任务,检测redis里面的code数量,如果少于设定的数量,就从库里面取1000个Lpush到redis里面去
现在项目跑了几个小时,暂时没有发现请求超时的问题和码值重复的问题。
但是感觉这种方式凑合能用,但不是最好的
想请问大家,对于类似的问题有没有最佳实践,比如在数据库设计和程序结构上
问题解答
回答1:你可以事先生成所有的code,放redis里,这样不用一千一千的再去弄了。
你也可以用mongodb,查询修改数据库并发性能也挺强的;
回答2:可以试试mysql 的事务呢?http://dwz.cn/3SrgGk
回答3:抽奖码即时根据uid算一个 加一点随机字符串
相关文章:
1. 为什么span的color非要内联样式才起作用?2. javascript - swiper.js嵌套了swiper 初始设置不能向下一个滑动 结束后重新初始3. python - Django ManyToManyField 字段数据在 admin后台 显示不正确,这是怎么回事?4. angular.js - angular-ui-bootstrap 报错无法使用?5. python - 如何修改twisted自带的日志输出格式?6. docker - 如何修改运行中容器的配置7. 求救一下,用新版的phpstudy,数据库过段时间会消失是什么情况?8. 请问一下各位老鸟 我一直在学习独孤九贱 现在是在tp5 今天发现 这个系列视频没有实战9. 在cmd下进入mysql数据库,可以输入中文,但是查看表信息,不显示中文,是怎么回事,怎新手,请老师10. 如何使用git对word文档进行版本控制?

网公网安备