从三十万观众中选出 30 个人作为中奖用户,还要在前端展示滚动抽奖的效果 ,后台的思路应该是怎样的呢?

2020-03-19 13:18:41 +08:00
 kaigong

如题 : 观众数量预计 30-40 万人 ,数据可以存储在 mysql/redis 中 需要前端页面点击抽奖,然后开始滚动观众数据 点击停止,返回给前端中奖的观众数据,展示

问题一 : 前台滚动的全量观众数据如何返回给前端。我的方案是做一个大分页,前端分页调取,追加到他的滚动的那个数据 list 里面,如果网络延迟导致后面的分页没有及时加载,就回到开始重新滚动。

问题二 : 中奖的逻辑该怎样实现? 业务方没有指定规则。我的方案是 从点击开始的那一刻开始,就按照一定的概率过滤每一个用户。遍历到该用户时,该用户的随机数如果在概率区间之内,就中奖。知道中奖用户数量足够为止。 需要注意的是,可能前端页面点击停止的时候,后台仍然没有足够的中奖人数,此时提高中奖概率,尽快返回结果 ?

因为是第一次做这种抽奖 ,所以想不到太好的方案,请教有没有做过的大神,给说一下思路?

4518 次点击
所在节点    程序员
36 条回复
jasamboro
2020-03-19 15:40:03 +08:00
小张啊,从单位找出 30 个电话号码给我一下
saulshao
2020-03-19 15:59:11 +08:00
直接读最近的 200 个名字给前端,让它拿去玩,中奖用户则随机...
murmur
2020-03-19 16:01:28 +08:00
30 个用户都是随机的,反正姓名电话都是**,还真的去抽啊,傻才那么做
Maboroshii
2020-03-19 16:05:07 +08:00
提前选好结果,前端写死滚动的范围,最后显示你的结果就好了。。
pmispig
2020-03-19 17:55:52 +08:00
滚动还不随便,从 30W 里面取几百几千个,让前端循环滚动就行了
gerrard000
2020-03-19 18:09:09 +08:00
srandmember key 30
veike
2020-03-19 18:26:58 +08:00
前提是你得报名,别没报名被抽中就搞笑了
christin
2020-03-19 18:32:50 +08:00
让我想到某个公司年会因为全是程序员中奖全体现场看代码,后门还是算了吧
aguesuka
2020-03-19 18:35:51 +08:00
只讨论真随机,也就是展示的所有中和不中的用户都是随机的,不会出现用户 aa 中奖,陪跑的全是 ab,ac,ad,据我所知 sql 必须遍历(欢迎打脸)。

既然这样把所有用户取出来放到 list 里。list 的前 n 位保存已经取出来的用户,后 m 位保存没取的用户,每次取用户随机一个 n 到 m 的数 x,所指向的用户就是中将的用户,然后把 list[n]和 list[x]做交换,n++;m--。

只要这样取,不管是取出的前 30 位,后 30 位中奖,都是随机的,都是公平的。而且中奖的用户和陪跑的用户没有关系。
kaigong
2020-03-19 18:58:08 +08:00
@aguesuka 感谢您的答案,关于陪跑的概念我不是很懂,如果方便可以请您再仔细讲讲吗。
gemini767
2020-03-19 18:58:23 +08:00
给你一些思路,实现不是难题,问题是场景,一个是如何做后门如何去做,有可能现场临时加后门,另一个是 30w 人确定都来?如何保证抽中的肯定是现场观众而不是走的人,如果轮空 如何补位
Junn
2020-03-19 23:57:18 +08:00
做个真的,直接展示的时候就从 30W 里随机取一些滚动,最后停到哪就是哪,不就完了么。
相当于最后中奖者,抽了 2 次。
致于随机取多少,看滚屏速度和每屏展示的数量决定了。
另外每次循环时再随机重排一下顺序。

做假的,就上面的,一开始就定了中奖者和陪跑的。前端自己玩,总能实现说停就停在中奖的地方的。
aguesuka
2020-03-20 08:26:21 +08:00
@kaigong
陪跑就是滚动但是没有中奖的用户。

抽奖最关键的是要实现一个接口 List<User> randomUser(int batch)。只要这个接口返回的每个用户是真随机的,那么前端只要一直显示,等到按停止按钮的时候,不管是当前的用户中奖,还是在请求一个后台中奖,每个用户中奖的概率是相等的。

真随机和伪随机的区别是,伪随机需要一个种子,在种子相同的情况下,伪随机的每个随机数都是一样的。如果是随机分页的话,随机到的分页 offset 就是种子。(当然在这个抽奖里伪随机也可以)
libook
2020-03-20 11:47:12 +08:00
一般有物理随机会比较让人信服,比如主持人嘉宾喊滚动和暂停。

总的思路是最好放在内存数据库中,提升读数据的实时性;有条件的话可以先对数据库里的数据做随机排序;如果数据库有游标 Cursor 之类的功能的话,可以创建一个遍历所有数据的游标,前端下令开始滚动就从游标上遍历取数据,喊停就暂停,然后喊继续就再继续;前后端用 WebSocket 通信,比如 Socket.io ,前端与服务器一次连接就可以,持续到抽奖结束;前端以 WebSocket 事件的形式来控制后端,后端实时返回数据。
windychen0
2020-03-20 14:59:14 +08:00
我寻思你想在前端显示的是名字还是 ID,如果是 ID 就好办了,数据库设置( id 主键自增,姓名,其他),然后前端页面显示 6 位数,3xxxxx,每一位随机上下滚动,第一位在 0-3 之间取值,其他在 0-9 之间取值,再给个停止按钮,你可以考虑一停一位还是一停全部,然后带着 ID 查询数据库出姓名部门数据不就好了?
ajaxfunction
2020-03-20 17:01:44 +08:00
我做过:
前台滚动就是从数据库里拉出来几百个人的个头像或姓名, 这些信息仅仅做动画滚动用,给大家一种滚动抽奖视觉

主持人喊开始:css 动画开始滚动这些的信息,主持人喊停止,然后 ajax 从数据库里随机 rand 几条中奖人员出来 ,并把中奖人信息展现到大屏幕上


实际滚动多久,开始和结束间隔多久,和中奖没有任何关系,中奖是点结束那几毫秒里直接生成的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/654212

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX