V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Waterchestnut
V2EX  ›  Java

老大让我做个红包雨的功能,主要写后端,暂时没想到好的实现思路~

  •  
  •   Waterchestnut · 2017-04-11 15:49:28 +08:00 · 7674 次点击
    这是一个创建于 2543 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我打算这么设计,给前端提供一个 htttp 接口,接口请求过来随便发放金额,诶,这个红包概率怎么控制?后面用原子计数器来计算红包数量,当达到老大给的数量上线和金额上线就告诉用户抢完了= =貌似 这样太粗糙。。暂时也想到好的解决方案

    第 1 条附言  ·  2017-04-12 00:34:39 +08:00
    1.目前金额也不是完全随机,有备选额度,比如 1 , 2 , 5 , 10 ,在这里面金额随机。
    2.红包雨一次下 50 个,用户最多点中 40 个,当然是点中也不一定有红包,概率我打算定在 5%
    3.抢红包总会会狂点,预计我上 redis ,做的队列啥的待我研究一下
    4.楼主渣后台 (﹁"﹁) ,没有高并发经验,害怕.jpg
    34 条回复    2017-04-12 11:05:57 +08:00
    MrFireAwayH
        1
    MrFireAwayH  
       2017-04-11 15:56:49 +08:00
    红包写最高 8888

    后端控制下随机生成 0~50 的数
    subdued
        2
    subdued  
       2017-04-11 15:59:21 +08:00
    关注一波
    torbrowserbridge
        3
    torbrowserbridge  
       2017-04-11 15:59:29 +08:00
    上线后请 @ 我 URL 页面,谢谢
    Troevil
        4
    Troevil  
       2017-04-11 15:59:41 +08:00
    奖池机制,先分配好奖池,然后在奖池里面随机抽取.
    xgfan
        5
    xgfan  
       2017-04-11 16:02:44 +08:00
    先把红包生成好。再随机发出去。发完就暂停。搞得细的话,还可以按小时分。
    A3m0n
        6
    A3m0n  
       2017-04-11 16:03:06 +08:00   ❤️ 1
    前些天做了个巨粗糙的抢红包
    https://ooo.0o0.ooo/2017/04/11/58ec8cc8b4243.png
    就是想模拟一下微信的抢红包算法
    算法参考下面这个回答
    https://www.zhihu.com/question/22625187
    bramblex
        7
    bramblex  
       2017-04-11 16:05:12 +08:00
    @MrFireAwayH 花雅酱上班摸鱼~
    jianzhiyao020
        8
    jianzhiyao020  
       2017-04-11 16:30:02 +08:00
    第一步:离线生成相应数量和金额上线的红包队列
    第二步:写代码去抢啊,控制好冲突
    第三步:也是最重要的一步,上线后请通知我。
    xiaoyang7545
        9
    xiaoyang7545  
       2017-04-11 16:33:27 +08:00
    @jianzhiyao020 这种东西如果用数据库实现好像就会有 冲突(后一个查询请求到来时,前面的未更新)。用什么方式防止冲突比较好?
    gamexg
        10
    gamexg  
       2017-04-11 16:51:25 +08:00
    预先生成红包,然后抢的时候直接 UPDATE 一条所有者是空的红包,将所有者设置为当前用户。
    之后在执行次查询找到被更新的红包。

    如果允许抢多个红包,那么更新时记得加个随机数,查询时带上好区分多个红包。

    当然上 Redis ,用队列功能更简单。
    rswl
        11
    rswl  
       2017-04-11 16:54:06 +08:00
    上线记得喊一下
    AlisaDestiny
        12
    AlisaDestiny  
       2017-04-11 17:03:05 +08:00
    可以预计算一个分配数组比如[0,1,0,,0,1].这样的话就是第二个人和第四个人有红包。可以控制概率。但是要做好每个用户抢的次数限制。
    AlisaDestiny
        13
    AlisaDestiny  
       2017-04-11 17:04:13 +08:00
    尴尬。写错了。是[0,1,0,0,1] 第二个和第五个。
    jianzhiyao020
        14
    jianzhiyao020  
       2017-04-11 17:36:22 +08:00   ❤️ 2
    @xiaoyang7545
    redis 单线程帮到你,
    可以用队列的形式存储红包数据,
    速度快,
    且数据不会有冲突。

    mysql 的话,
    首先可能想到的是锁:
    可以在事务中 select ... for update 锁住该行队列数据,
    不让别人修改。
    并在 update 的条件中中做好控制即可。
    这样的话可能会产生这个队列阻塞问题,
    需要用哈希随机碰撞红包,
    但是这样也同样会可能红包比较难碰撞的问题。

    其实还可以这样做,
    用一个新表去做,
    主键子增,
    通过插入记录获得 last_insert_id ,
    再去红包表获取数据,
    简单容易实现,
    且不会有冲突的问题。


    mysql 最好结合 redis ,
    redis 计数, mysql 存储。

    有错希望能够及时提出,感谢。
    banksiae
        15
    banksiae  
       2017-04-11 17:41:05 +08:00   ❤️ 1
    不需要预分配,只要设置总额和个数就行了,金额随机生成, redis 做原子控制,防止刷红包,算法参考 A3m0n 提到的。
    有个问题,抢红包人数多的话,就成了秒杀场景,所以抢之前要做下类似红包结束的判断。
    最后就是异步发红包的问题,流水不能出错,保证幂等,基本就 OK 了
    luluuulu4848
        16
    luluuulu4848  
       2017-04-11 17:41:23 +08:00   ❤️ 1
    @xgfan 好主意啊
    luluuulu4848
        17
    luluuulu4848  
       2017-04-11 17:43:25 +08:00
    @banksiae 为什么不需要预分配,我觉得挺好的 先生成出来,求教
    banksiae
        18
    banksiae  
       2017-04-11 17:57:38 +08:00
    @luluuulu4848 浪费存储空间,如果有 mysql 做,会有点性能问题;如果用 redis 预存储,浪费空间
    x7395759
        19
    x7395759  
       2017-04-11 23:55:33 +08:00
    多少的量?少的话预分配最稳。
    Waterchestnut
        20
    Waterchestnut  
    OP
       2017-04-12 00:15:31 +08:00 via Android
    @MrFireAwayH 金额随机数为 1 , 2 , 3 , 5 , 10 ,在这几个数中随机,当然小额红包中奖率高一些
    Waterchestnut
        21
    Waterchestnut  
    OP
       2017-04-12 00:15:38 +08:00 via Android
    @torbrowserbridge 好的😄
    Waterchestnut
        22
    Waterchestnut  
    OP
       2017-04-12 00:17:05 +08:00 via Android
    @Troevil 奖金池是个思路,但是这也相当于是个库存模块了,怎么防止超卖
    Waterchestnut
        23
    Waterchestnut  
    OP
       2017-04-12 00:17:37 +08:00 via Android
    @xgfan ok ,感谢
    Waterchestnut
        24
    Waterchestnut  
    OP
       2017-04-12 00:18:19 +08:00 via Android
    @A3m0n 谢谢大神的 demo
    Waterchestnut
        25
    Waterchestnut  
    OP
       2017-04-12 00:19:16 +08:00 via Android
    Waterchestnut
        26
    Waterchestnut  
    OP
       2017-04-12 00:22:32 +08:00 via Android
    @AlisaDestiny 目前一个人抢红包的数量没有限制,在 30 秒内能抢多少是多少
    Waterchestnut
        27
    Waterchestnut  
    OP
       2017-04-12 00:23:35 +08:00 via Android
    @AlisaDestiny 这意思是提前就定好哪个次序的用户可以得到红包哈?
    Waterchestnut
        28
    Waterchestnut  
    OP
       2017-04-12 00:24:24 +08:00 via Android
    @jianzhiyao020 非常感谢(❁´ω`❁)
    Waterchestnut
        29
    Waterchestnut  
    OP
       2017-04-12 00:28:41 +08:00 via Android
    @banksiae 确实就是秒杀场景了,预计 20 万个红包,,一次红包雨 50 个,单个用户最多领取 40 ,里面有的是空的,这种情况下,用户一定会狂点。
    Waterchestnut
        30
    Waterchestnut  
    OP
       2017-04-12 00:36:59 +08:00 via Android
    @x7395759 老大说预计 20 万个红包,当然有没有这么多人点我就不知道了。。。😳
    azh7138m
        31
    azh7138m  
       2017-04-12 08:24:59 +08:00 via Android
    @A3m0n 知乎那个太假,不如直接拿分做单位,浮点太坑
    liuxu
        32
    liuxu  
       2017-04-12 09:29:23 +08:00
    这我得写脚本抢了
    jason19659
        33
    jason19659  
       2017-04-12 10:10:26 +08:00
    预计好人数,提前生成好红包扔进一个线程安全的队列,怎么样
    hongcha
        34
    hongcha  
       2017-04-12 11:05:57 +08:00
    艺术来源于生活,
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1065 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:44 · PVG 06:44 · LAX 15:44 · JFK 18:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.