我司的面试题目公开诚聘 Java 工程师入坑 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
外包信息请发到 /go/outsourcing 节点。
不要把相同的信息发到不同的节点
jiansihun
V2EX    酷工作

我司的面试题目公开诚聘 Java 工程师入坑

  •  
  •   jiansihun 2019-05-24 12:17:34 +08:00 6379 次点击
    这是一个创建于 2333 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在抽奖场景中,最高峰值为 2w QPS,运营部现有 20000 部 iPhone 手机,决定每 100 人随机抽中一台,覆盖人数 200w 人,送完即止。请如何技术上如何实现该机制。

    如有能回答上述问题的 Java 工程师请考虑一下我司广州工作: https://www.lagou.com/gongsi/j29385.html,或者站内私我简历。
    33 条回复    2019-05-27 09:43:54 +08:00
    woahishui
        1
    woahishui  
       2019-05-24 12:59:49 +08:00 via Android
    创建一个数据表(可以用数据库或者 nosql),记录用户的的抽奖记录,每 100 个人分一个标识,使用随机函数标识查询到的记录作为中奖着,这样可以吗
    NewDraw
        2
    NewDraw  
       2019-05-24 13:03:37 +08:00 via Android
    @woahishui


    缓存+限流+消息队列,200wQPS 都没问题。
    mooncakejs
        3
    mooncakejs  
       2019-05-24 13:04:53 +08:00
    2w QPS redis 就可以撑住,hset 用户 id 去重,抽奖形式就很多了,increment value % 100,pull list,或者干脆队列化单线程抽奖。
    woahishui
        4
    woahishui  
       2019-05-24 13:13:30 +08:00 via Android
    呵呵
    woahishui
        5
    woahishui  
       2019-05-24 13:14:08 +08:00 via Android
    都行,方案应该都可行吧
    zyue
        6
    zyue  
       2019-05-24 13:15:00 +08:00
    按奖品数量分为 20000 场,对用户 id hash 落到 1-20000 中的某个场次,检查缓存,看对应场次是否因有人抽中而结束,结束的话直接返回未抽中,没有的话执行抽奖等逻辑,可以同步抽取,也可以走 mq 异步处理。
    zz656565
        7
    zz656565  
       2019-05-24 13:16:10 +08:00
    这点羊毛够黑产薅吗?
    woahishui
        8
    woahishui  
       2019-05-24 13:17:59 +08:00 via Android
    不过我倒觉得这个想法有问题,那么快就完了容易导致服务器压力突然增大,不如让大家先报名,然后在一周后统一抽奖,这样关注度高,时间长,而且还能降低技术难度,降低技术难度意味着可以省去 5000 部手机的钱,相当于只要 15000 部就够了。这是我的建议
    lihongming
        9
    lihongming  
       2019-05-24 13:29:36 +08:00 via iPhone
    200W 用户总不能是一下来的吧?何不换个姿势,把抽奖过程放到用户入库的过程中?

    比如分个随机数给它,根据这个随机数把用户放入一个长度为 2W 的数组,数小的顶走数大的,最后剩下的都是中奖的。
    woahishui
        10
    woahishui  
       2019-05-24 13:32:37 +08:00 via Android
    参加抽奖是参加抽奖,不要将抽奖混合在一起,我是这么想的
    matrix1986
        11
    matrix1986  
       2019-05-24 13:56:08 +08:00
    消息队列,削峰不二之选
    LuciferGo
        12
    LuciferGo  
       2019-05-24 13:59:56 +08:00
    刚好前两天在掘金看了这个问题,https://juejin.im/post/5ce1975af265da1bd42450b5
    9684xtpa
        13
    9684xtpa  
       2019-05-24 14:32:23 +08:00
    @NewDraw #2
    基础之上只要保证,如何覆盖面达到 200W,毕竟是 100:1,这个利用 redis 的 incr 和缓存也能搞定,每个购买的人分配一个数值 ID,每 id%100=0 的人具有购买资格。
    Leigg
        14
    Leigg  
       2019-05-24 14:54:39 +08:00 via iPhone
    记得奖品抽完后告诉前端请求不要发到后端。
    qwerthhusn
        15
    qwerthhusn  
       2019-05-24 15:41:35 +08:00
    当然是内定啊,a 这个是老板的意思。。。。
    vincel
        16
    vincel  
       2019-05-24 15:47:07 +08:00
    这种场景小米很有发言权,直接前端砍掉 2/3 的请求。
    myself659
        17
    myself659  
       2019-05-24 16:08:19 +08:00
    套方案吗?
    horace1117
        18
    horace1117  
       2019-05-24 16:13:50 +08:00
    不是应该直接 redis 缓存未抽中就行了嘛,抽奖什么的当然是内定
    cyndihuifei
        19
    cyndihuifei  
       2019-05-24 17:11:26 +08:00
    随机拒绝 1 / 200 的概率,让用户进行后面的请求,直接削减大部分请求
    CRVV
        20
    CRVV  
       2019-05-24 17:49:48 +08:00
    1. 给登录用户一个 jwt,客户端在发的请求的一个 HTTP header 里带上用户 id
    2. 在 load balancer 上,拿用户 id 来决定路由,让同一个用户的请求只会被路由到同一台机器上
    3. 接到请求的机器验证 jwt,并且记下来发过请求的用户,如果这个用户已经发过请求就直接返回
    4. 随机决定 1% 的用户中奖,然后把数据库上把剩余奖品的数量 atomic x--,如果 x>0 就给用户返回中奖了

    数据库上只有 200 QPS 的请求,只要是支持 atomic 操作的数据库应该都能用
    其它的部分互不依赖可以无限加机器

    没做过类似的东西,大概想了一下这样应该能用
    c4f36e5766583218
        21
    c4f36e5766583218  
       2019-05-24 18:13:34 +08:00
    我看成要送手机,结果只是个题目。
    petelin
        22
    petelin  
       2019-05-24 20:15:49 +08:00 via iPhone
    这个题我觉得没描述好 应该改成需要用户实时看到结果
    要不然做成批次(够 100 人开一次奖)或者 200w 人都参与完在开奖就太简单(技术上太简单了 我会认为这公司很水)

    @woahishui 每秒就 10 个人抽奖.难道让他们等 10 秒才知道中没中?
    @NewDraw 200w QPS 过来 服务端延迟多少? 分布式机器怎么从队列取数据决定谁中奖?
    @CRVV 这个思路不错 不过为什么要路由到同一台机器?那台机器挂了呢 扩容了呢? 抽奖结束直接记录信息是不是更好 还有这个算法太简单了 可能抽不到 200w 所以要参考微信红包算法
    murmur
        23
    murmur  
       2019-05-24 20:19:15 +08:00
    如果是微博抽奖,就丢弃掉所有请求,反正这种东西一定是虚假抽奖
    577322753
        24
    577322753  
       2019-05-24 20:25:55 +08:00 via Android
    开个线程,一直阻塞到够 200 万人,不够就 sleep 一会,然后把这两百万人存到 list 里,存够了遍历 list,i %100==0,那 i 这个 b 就中奖了,让我们恭喜这 20000 个 b。贵公司缺 cto 吗?
    largecat
        25
    largecat  
       2019-05-24 22:54:51 +08:00 via Android
    上面答内定的同学你可以发简历过去了,
    woahishui
        26
    woahishui  
       2019-05-24 23:28:59 +08:00 via Android
    @petelin 我后面的回复是从活动的角度想的,并非从技术,如果活动很快就结束了,感觉活动效果可能打折比较多,如果搞成彩票类型的感觉时间长,用户关注度高,更适合推广
    wpzero
        27
    wpzero  
       2019-05-25 09:04:56 +08:00 via iPhone
    其实我感觉就只需要事先生成获奖的 2 万列表存在 redis 的 set 好了,每一个 request 的电话号产生一个 unique key,用 redis 来检测是否已经抽过,incr pk,然后得到的值是否在 set 中,在就中奖了。redis 这些操作应该都是 10 万每秒级别,如果你认为还不够 OK,多个 redis,用电话号 hash mod 来 map.至于服务器这种没有 rds 的操作用 nodejs golang java 几台服务器撑一下都可以。消息队列来解题也很合适。
    lychnis
        28
    lychnis  
       2019-05-25 09:49:28 +08:00 via Android
    要什么自行车,蓄水池算法。

    其实楼主在筛选你们会不会算法和数据结构
    Kylinsun
        29
    Kylinsun  
       2019-05-25 10:29:40 +08:00 via iPhone
    CRVV
        30
    CRVV  
       2019-05-25 11:45:45 +08:00
    @petelin

    > 为什么要路由到同一台机器?

    如果同一个用户的请求会被路由到不同的机器上,就需要一个中心的数据库来记录哪些用户发过请求,这个数据库会成为瓶颈

    > 那台机器挂了呢 扩容了呢?

    这里的点是按照用户的 id 来分请求,减少后面每一台机器上的负担
    后面的“一台机器”可以不是一台机器,你改成若干台机器加 Redis, 是一样的
    这个若干台机器加 Redis 的东西可以继续扩容,但是 load balancer 上的后端不能增加
    另外楼主给定了请求数量的上限,在这个题目的范围里不需要考虑扩容

    > 还有这个算法太简单了 可能抽不到 200w

    能抽到多少数字和算法简不简单没有关系
    如果你觉得不行,请直接指出来哪里有问题
    larve
        31
    larve  
       2019-05-26 20:34:15 +08:00
    1. 库存控制:防止超发
    redis 自减或者 redis 队列出栈都能做到
    2. 随机用户
    200w 用户随机:若是同一场抽奖,有两百万个用户参与,可 redis 通过一个 key 自增,每自增 100 则对应用户是抽中的,抽中的用户再进入后续入库操作即可,最高时 2w redis QPS 应该是可以的,真正能入库的数据也不多
    zc1249274251
        32
    zc1249274251  
       2019-05-27 09:29:35 +08:00
    1、限流
    2、利用 redis 做自增或者自减操作 提交请求到队列
    3、创建有界队列,如果队列满了,直接拒收请求
    4、让队列里边的请求 mysql 来做最终一致性
    jiansihun
        33
    jiansihun  
    OP
       2019-05-27 09:43:54 +08:00
    @petelin 考虑一下我司的的位置不。#这个题我觉得没描述好 应该改成需要用户实时看到结果# 这个问题要看到最高峰值 2w QPS,也就是 QPS 是 0 - 2w,另外要注意随机字眼,以及仅有的 2k 部手机,方案并不一定都可以实时(我有可能也不对),确实需要从用户端体验开始考虑的起。当然大力出奇迹的答复在上面的答案已经有了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     918 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 18:50 PVG 02:50 LAX 1:50 JFK 14:50
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86