公司做抽奖或者红包活动,总有人恶意大访问量请求,查询mysql去做重复验证在大并发上限制不住,总会有重复插入,会造成多发奖品。
想用redis做mysql的缓存,但是现在遇到的问题是如何把redis的数据写回mysql,不可能每次校验的时候就写回mysql,那样的话根本没有解决问题。
现在的想法是能否利用php,或者其他什么技术,定时将redis中的数据写回mysql。程序只与redis交互。
希望能给出具体的逻辑或者解决方案,网上的回答都太笼统了,根本解决不了问题。
谢谢。
1月16日补充:
我问题描述的不太清晰。
我把遇到的问题详细的说一下吧,并不是发奖时候脏读的问题,而是判断这个人是否有机会抽奖。
有一个抽奖的表,如果这个人抽过奖了,就在表中插入一条记录。
目前的实现方式是:
1.读取抽奖表判断这个人是否抽过奖
2.如果表中有记录,那就是抽过了,直接告诉没机会
3.如果表中没有记录,走抽奖逻辑,然后插入抽奖表
正常情况下是没有问题的,
但是有人用恶意脚本进行刷奖,也就是同一个人发起大量请求,1秒可能一两百的请求甚至更多,而且不只一个人刷奖。
问题出在1这一步
举个例子,假设每人只能抽一次奖,因为请求太快,同一人的a,b两个请求几乎同时来,a走完抽奖逻辑了,并且在抽奖表中插入记录的过程时,因为mysql的性能的问题,b去走1这一步是读不到表中的记录的,因为a的插入根本没有完成。所以b请求会再走一次抽奖逻辑。造成同一人抽奖两次,然后再插入抽奖表。
我关心的是能否a插入抽奖表的瞬间,b就能判断出抽奖表有数据。
所以我觉得问题是mysql写入的不够快,读取的不够快,所以我要采用redis做一层快速缓存。
我们做的抽奖是单一奖品百分之百中奖,只限制奖品数量,所以必须保证每人只能抽一次,而且尽量在程序层面去解决。
1月20日补充
看了大家的回答很受启发,非常感谢。
至于有人提到并发没想象的那么大这件事,是这样的,我们的服务器是阿里云单台的ECS,配置4核8G 独享50m宽带,centos,只做对外活动。
这是12月24号上线的一个不到4小时活动的抽奖活动的浏览量。
这是当时TCP连接数的监控
抽奖不同于网站访问,这些参与者基本绝大多数是同一时间段来访问服务器。我个人觉得在服务器配置不升级的情况下,软件层面的优化完全能扛住这些访问。我目前觉得瓶颈在mysql。
题主你之所以会出现这么多问题,是因为你思路混乱,根本没搞清楚这些问题到底是怎么回事,并且得病后还自己乱下药。
1.【总有人恶意大访问量请求】,这是系统安全问题,你需要做的是防攻击。
2.【查询mysql去做重复验证在大并发上限制不住】:这是功能缺失。既然有缺失,就立即做新功能研发。
3.【总会有重复插入,会造成多发奖品】:这是已有系统的Bug,需要通过调试来修正问题。
综上,这些问题与redis有什么关系?