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

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

  •  
  •   Waterchestnut · 192 天前 · 3529 次点击
    这是一个创建于 192 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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


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

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