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

再问秒杀锁问题

  •  
  •   cevincheung ·
    cevin · 2017-09-04 04:14:29 +08:00 · 6041 次点击
    这是一个创建于 2646 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现成的技术解决方案太多,redis 的并发性能真的是没得说,关键是想问问都是怎么处理数据同步的问题的。

    发布秒杀活动,发布成功后就直接入 redis ?

    if (insert ok) redis.set('ms:itemid',stock) ?

    入 redis 失败了呢? redis 挂掉这阶段的数据没保存呢(还没来得及 fsync)?

    活动结束后 怎么删除(不能用 setnx 的场景,没过期时间,售完算完)?

    if(decr('ms:itemid')<0) del('ms:itmeid') ?

    怎么及时的删除脏数据?

    大半夜睡不着不知道自己在纠结什么。 :(

    22 条回复    2018-05-10 20:44:05 +08:00
    hareandlion
        1
    hareandlion  
       2017-09-04 07:17:40 +08:00 via iPhone
    额,启用热备,一个备份不够就多上几个?剩下的就是预防成本高于实际需求的小概率情况了吧?
    jalja27
        2
    jalja27  
       2017-09-04 07:31:20 +08:00 via Android
    ‘ 1
    linpf
        3
    linpf  
       2017-09-04 09:09:35 +08:00   ❤️ 9
    讲道理,业务上改一改规则的话,没必要完全实现秒杀,假设同一秒有 1 万个用户抢购 100 件商品,nginx 直接按照 97%的几率抛弃请求,返回“抢购失败,还有机会,请重新抢购”,省下大约 300 个请求,直接用 mysql 就行了。这样购买时间都是同一秒的请求,用户也不知道他到底在这 1 秒之内的顺序。对活动方来说,活动效果也实现了。毕竟运气也是实力的一部分。
    esile
        4
    esile  
       2017-09-04 12:45:46 +08:00 via iPhone
    @linpf 666 啊 先随机排除,然后在进行计算😂
    xrlin
        5
    xrlin  
       2017-09-04 12:53:09 +08:00
    @linpf 这想法很不错。
    jyz19880823
        6
    jyz19880823  
       2017-09-04 13:55:49 +08:00
    @linpf 666
    TheLamb
        7
    TheLamb  
       2017-09-04 14:07:28 +08:00
    @linpf 很 6 的想法
    t333st
        8
    t333st  
       2017-09-04 15:09:47 +08:00
    @linpf 套路深,学习了
    cevincheung
        9
    cevincheung  
    OP
       2017-09-04 15:26:54 +08:00
    @linpf #3 23333
    cevincheung
        10
    cevincheung  
    OP
       2017-09-04 15:27:09 +08:00
    @linpf #3 就直接 select for update 了?
    paragon
        11
    paragon  
       2017-09-04 15:44:37 +08:00
    前面加验证码 后面提交验证的验证码就丢了
    kamushin
        12
    kamushin  
       2017-09-04 16:02:17 +08:00
    @linpf 然后出现一件商品非常冷门, 很少有人愿意抢, 唯一一个客户需要下单 33 次才能购买到. 这个用户体验炸裂
    MrFireAwayH
        13
    MrFireAwayH  
       2017-09-04 16:24:35 +08:00
    @kamushin #12 虽然不是很懂 但是我觉得判断一下并发请求数目后再进行 97%概率抛弃是能做到的吧
    yexiangyang
        14
    yexiangyang  
       2017-09-04 17:14:13 +08:00
    1.if(decr('ms:itemid')<0) del('ms:itmeid') ?
    可以修改为
    if(decr('ms:itemid')=0) del('ms:itmeid')
    2.入 redis 失败了呢? redis 挂掉这阶段的数据没保存呢(还没来得及 fsync)?
    建议采用 sentinel 模式
    挂掉后故障转移,时间不会很久,期间可以业务失败
    caijihui11
        15
    caijihui11  
       2017-09-04 19:27:42 +08:00
    @linpf 这个实现 6,但我们也要维护参与活动的公平性,不能以运气来搞
    qiyuey
        16
    qiyuey  
       2017-09-04 21:20:31 +08:00
    @caijihui11 随机难道不公平吗
    linpf
        17
    linpf  
       2017-09-05 08:18:43 +08:00
    @kamushin 没看到返回的文字吗“抢购失败,还有机会,请重新抢购”,也就是可以再点啊。
    linpf
        18
    linpf  
       2017-09-05 08:19:32 +08:00
    @caijihui11 这就要看为了这点公平性,提升的成本能不能接受了
    linpf
        19
    linpf  
       2017-09-05 09:24:09 +08:00
    @caijihui11 而且每个用户访问请求接口,网络环境的不同也会存在延迟也有几毫秒到几秒的随机,其实请求到达服务器的顺序本身就已经不是按照点按钮的顺序了。
    tausi0661
        20
    tausi0661  
       2017-09-05 10:57:33 +08:00
    @qiyuey 吹毛求疵的说, "秒杀"的意思是"比谁快". 而随机意味着"我比你快, 但我被随机掉了"
    (3#666, 我也打算这么实现...)
    zhengwenk
        21
    zhengwenk  
       2017-09-05 13:24:08 +08:00
    @caijihui11 其实也可以把请求入队列,只消费前 300 个,之后的请求都抛弃掉。
    1cming
        22
    1cming  
       2018-05-10 20:44:05 +08:00
    3#666
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2771 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:21 · PVG 23:21 · LAX 07:21 · JFK 10:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.