这段时间做一个抽奖项目,具体需求分三步:
1)用户输入一个产品的唯一号。
2)进入抽奖界面。
3)抽奖返回结果。
很简单的需求,但是由于是个网络版,所以有几个问题不得不考虑:
1)一个用户,输入一个产品唯一号,进入抽奖界面(还未抽奖),这时另一个用户也输入相同的产品唯一号,如何处理?
一个用户进入抽奖界面后,该产品应该锁定,其他人员输入产品号后,不能进入抽奖界面。
2)一个用户,输入一个产品唯一号,进入抽奖界面,这时浏览器忽然挂了,这个时候如何处理?
一个用户进入抽奖界面后,该产品应该锁定,但如果在规定时间内没有抽奖,则该产品放弃锁定,其他人员可以输入产品号继续抽奖。
3)极限情况,有n多的用户,在某一个时间点,大批量的输入同一个产品的唯一号,又如何处理?
第一条已经回答。
虽然在实际情况的应用场景里面,以上情况基本不可能出现,但衍生到了另一个话题,如果要做秒杀活动呢?
以前没有做过类似的项目,一开始只是单纯的想用数据库的主键来规避多个用户,抽同一个产品号的问题(即用一张表,以产品号为主键,不管你如何开抽,保证能够成功插入该表的用户为成功的那一个),但是当出现第3种情况后,采用数据库来实现,估计数据库会爆掉。。。
在网上查阅了一下资料,说最好的方式,是放到内存来解决。由于前段时间粗浅的研究了一下Redis,忽然发现这东西真的太满足我的需求了!原因如下:
1)Redis是一个Key value的内存数据库(我所使用的StaticExchange类,能够解决Key存在的情况下,相同Key无法介入)。
2)自带失效时间机制(满足锁定时间的需求)。
3)内存数据库,速度应该可以应付一般性的抽奖和秒杀。
虽然Redis已经可以解决了,但是为了保证同样一份产品ID不能抽两次奖,又增加了一下东西,最后的解决方法如下:
1)用户进入输入产品号界面的时候,给他分配一个UUID。
2)输入产品号后,对没有抽奖的产品,首先判断该产品号在Redis中是否存在,如果不存在,则向Redis中写入该产品ID, KEY:产品ID,VALUE:UUID.并设置失效时间,比如5分钟。如果Redis中已存在,则判定UUDI是否和自己的UUID相同,如果相同,则进入抽奖界面,如果不同,则提示奖品被他人锁定。
3)在抽奖环节同样会在Redis中进行验证UUID,已保证不会超时。比如一个用户进入了抽奖界面很久而不抽奖(超过了有效时间),这时就应该回到输入产品号界面,重新抽奖。
4)在数据库中,还是建立一个表,采用产品号为关键字,确保,最后写库的时候,不会出现同一个产品号,抽奖两次。
如果以后做秒杀的项目,也可能会采用这样的思路。
第一次做,有可能不成熟,希望大家共同探讨!