天天看点

抽奖实现方式

具体步骤:

1、我们是根据用户积分抽奖的,每5积分抽一次,每天限制最多抽奖5次。(积分获取方式:每天签到获取积分,做任务赠积分)

2、用户访问抽奖页面,有个大转盘,用户点击大转盘中间按钮,开始访问后台

3、前台必须往后台传送jwt字符串,后台校验jwt字符串并解析出用户信息,根据用户id判断用户积分是否足够抽奖

4、如果用户没能力抽奖,告诉用户积分不足,给个链接让用户挣积分

5、如果用户有能力抽奖,判断用户今天抽了几次奖,如果超过5次,提示用户今天抽奖次数已用完

6、如果用户可以继续抽奖,使用mq往抽奖微服务发送一个抽奖请求

7、抽奖微服务需要接收到用户的id和时间戳,从redis当中获取数据,判断是第几个用户在抽奖,如果是30000次在抽奖送小米手机一部,如果是50000次在抽奖送联想手机,如果是第70000次抽奖送苹果手机。

8、如果是其它次数抽奖,送3、5、10积分不等。这里涉及到一个奖池初始化的操作

redis奖池的设计:

通过redis的

BoundListOperations

这个类用于存放积分奖品,第一次抽奖先初始化奖池,创建一个list,里面存放28000个1积分,20000个3积分,16000个5积分,6000个10积分,使用

Collections.shuffle

这个方法把list里存放值的顺序打散,再把打散后的奖品放到BoundListOperations这个redis栈中,然后从栈最左边取出一个值返回给用户。

第一次初始好奖池后,下面再进来抽奖的用户判断BoundListOperations中有没有值,就初始化一个奖池,奖池的奖品是7万个积分奖品。

如果有值就从BoundListOperations的最左侧抽出一个值,这个值取出后BoundListOperations就会减掉这个值,这个目的是为了让奖品不重复。

抽到的奖品如何返回:

抽到的奖品放入到redis当中,key是以lottery+userid+时间戳组成的,目的是为了确定奖品的唯一性,因为一个用户一天抽5次奖,如果不给用户id加时间戳,那用户抽中同一个奖就会覆盖上次抽奖。抽奖微服务执行完毕。

回到抽奖的方法中,发送mq之后,返回到前台,

前台是个while循环,循环5次,循环中有个sleep睡眠,一秒执行一次访问后台一个抽奖结果方法,目的是为了让一秒中往redis中获取一次数据,看看抽奖微服务是否执行完成,如果redis在5秒内能够查询到数据,说明抽奖微服务执行完成,并往数据库中插入一条数据,让当前用户的抽奖次数加1,再给用户返回抽奖结果。前台大转盘拿到这个奖品以后,把转盘指针指向奖品的位置,并提醒用户您抽到了什么奖,用户点击进入个人中心,就可以看到奖品记录了。

1、前台抽奖系统讲解

如何获得抽奖机会?

用户每次充值会员获得5次抽奖机会,

每答题一次获得三次抽奖机会

每天签到获得一次抽奖机会

抽奖机会可以累加,但每天抽奖次数限制三次

每次抽奖耗费5积分

抽奖送课程大礼包。

每天签到送积分(话术)

用户在个人中心点击签到按钮,送5积分,每个用户只能签到一次,每次根据签到的日期状态判断,只要用户今天签到过一次,就不允许再签到了,这个用户每次点击签到时在后台判断。这个状态存入到redis当中

抽奖完成后如何给用户邮寄过去?

如果是电商的话本身就对接了快递公司,让用户填写邮寄地址即可。

如果是在线教育类的送课程大礼包,就直接兑换成课程。

如果既不是兑换课程,又不是电商平台,那就直接在个人中心做个抽中奖品的页面连接按钮,点击那个按钮,到中奖页面,让用户填写个人信息和地址,邮寄过去,邮寄后只需要在那个页面显示正在邮寄中就行了。

抽奖模块是如何做的?

你重点说下你们的抽奖算法是如何写的?

通过redis的BoundListOperations这个类用于存放积分奖品,第一次抽奖先初始化奖池,创建一个list,里面存放28000个1积分,20000个3积分,16000个5积分,6000个10积分,使用Collections.shuffle这个方法把list里存放值的顺序打散,再把打散后的奖品放到BoundListOperations这个redis栈中,然后从栈最左边取出一个值返回给用户。

第一次初始好奖池后,下面再进来抽奖的用户判断BoundListOperations中有没有值,就初始化一个奖池,奖池的奖品是7万个积分奖品。

如果有值就从BoundListOperations的最左侧抽出一个值,这个值取出后BoundListOperations就会减掉这个值,这个目的是为了让奖品不重复。

你们代码中没用到线程锁吗?

用到了,判断用户有能力抽奖以下代码,发送mq之前加了线程锁,让用户进行排队执行发送mq消息。

如果我们想给员工做一个抽奖系统,我们要让百分之20的人抽中三等奖,百分之15的人抽中二等奖,百分之5的人抽中一等奖,你这个奖池应该怎么做?

很简单,后台代码把奖品数量写死,然后用shuffle打散就可以了。比如一百个人,5个人一等奖,就写个list放一等奖的值,15个二等奖,就写个list放15个二等奖的值,最后打散,以此类推。

你们是如何防止高并发抽奖的,如何防止同一个用户抽中奖

我们用了mq去处理,抽奖服务每次只能接受一个用户请求数据抽奖,其它用户都会在mq中排队,只有第一个抽完放入redis后,第二个才能进来抽奖。

你们抽奖管理加mq那样做不会影响性能吗?并发来的时候怎么办?

不影响性能,我们项目目前最高承受并发是一千一百多(这个数自己说,只要不超过一千五就行),一点问题都没有,我们只有十几万用户,并没有那么大用户量,处理并发也不是在一台机器上优化,我们也搭建了3台集群处理,一台了可接受一千五左右,三台就是4千多。

你们奖池前台是如何做防刷的?后台是如何做防刷的?如果别人做个循环就是刷你的产品,你怎么处理?

前台不需要做防刷,我们后台有判断呀,判断用户积分够不够和今天是否抽奖次数到三次,这两个条件判断的,如果他在做刷奖操作,最起码用户根据用户id判断这关就过不了。

如果对方获取了你用户中所有的id,乱刷呢?

第一,他获取所有用户id刷奖品无意义,因为说不定哪个用户获取了奖品,又不会到暴力乱刷者手中。

第二,用户抽中奖后,我们会先人工确认抽奖情况,然后再进行发货。

第三,如果真要防止乱刷,可以检测IP,如果有IP短时间内高速访问就用redis记录下,半小时内不允许它访问。

如何做奖池管理?比如多个地区组成一个区,华北、华南、华东、华西四个区,四个区里都有小奖池,最后又有一个统一的大奖池,如果要用奖池管理你怎么思考的?

这得需要先创建一个最大奖池,然后通过大奖池随机给其它区的小奖池分发奖品,就如同抽奖一样,整个过程都是随机的,比如大奖池生成了3个一等奖,6个二等奖,四个区分,肯定有一个区没有一等奖,两个区只有一个二等奖,整体靠大奖池做总管理分发。

你们第几次抽什么奖是固定好的对吧?你们为什么要固定某个数量抽到某个奖,你们如何考虑的?

这个可以随意设置的,想让固定就固定,不固定也可以,如果不固定第多少个人来了抽中某个奖品,那这个奖品抽中就不可控了,具体为什么选在10万、15万等数才能抽中奖,是根据我们用户量来决定的,比如我们活跃用户有3万个,抽奖时间是三天,如果设置的比较靠前,一天就抽中了,那就没意义了。(注意这个抽奖数、抽奖天数几天、活跃用户数自己想,不要按我的来,我只是给思路)

你们内部员工也可以去抽的对吧?那员工抽中怎么办?

当然可以,我们没做限制。如果员工抽中就给员工了,没限制的。

你们对抽奖次数有限制吗?你们抽奖周期有多长时间呢?

抽奖次数一天三次。抽奖周期为(3天、1周、1月、3月都可以),比如抽课程大礼包就是1-3个月比较好。

你们是如何防止多个用户抽奖的时候并发问题的?如何防止多个用户同时抽中一个奖品?

我们在抽奖时用到了mq,这样就能够很好的给mq进行排队执行,防止用户并发抽中同一个奖品。我们目前可承受并发是1千多,整体速度还是可以的,如果有问题可以加集群处理。

上一篇: 桥模式 Bridge
下一篇: 安装npm cnpm

继续阅读