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

我被京东到家的抢购机制惊呆了,第一个人抢不到,第二个人才能抢到?

  •  
  •   jadec0der · 2017-10-26 14:24:00 +08:00 · 7622 次点击
    这是一个创建于 2589 天前的主题,其中的信息可能已经有所发展或是发生改变。

    《库存系统难破题?京东到家来分享》

    多人同时购买 1 件商品,如何安全地库存扣减?

    海量的用户秒杀请求,本质上是一个排序,先到先得。但是如此之多的请求,注定了有些人是抢不到的,可以在进入上述伪代码 Dao 层之前增加一个计数器进行控制,比如有 50% 的流量将直接告诉其抢购失败,伪代码如下:

    count++;
    if (count%2==1) {
       Thread.sleep(1000);
       return new BuyResult("抢购失败");
    } else {
       return doBuy();
    }
    

    这样真的合适吗?

    23 条回复    2017-10-27 09:35:39 +08:00
    invoke
        1
    invoke  
       2017-10-26 14:39:52 +08:00
    事实上很多队列都是这样的。

    直接按照某种规则 告诉你你这次排队没抢到。或者告诉你一个排队次数,但是实际上你是没有购买权限的。以缓解压力。
    airyland
        2
    airyland  
       2017-10-26 14:40:44 +08:00
    本质上就是限流策略,上面是伪代码具体也可能不是这样。
    ScotGu
        3
    ScotGu  
       2017-10-26 14:43:49 +08:00
    看过一个段子,
    HR 收集了一批建立,然后分成两份,丢掉一份……
    并说:“来我们公司,首先要有好运气”。
    ScotGu
        4
    ScotGu  
       2017-10-26 14:44:15 +08:00
    @ScotGu #3 更正:
    “建立” = “简历”
    cnTangLang
        5
    cnTangLang  
       2017-10-26 15:01:22 +08:00
    你这话题让我想起,12 年京东 618 时秒杀了一个 coach 的太阳镜,好像 1000 多的样子,99 抢购到的。页面写明一个地区的仓库只有一个。结果我付了款了,过了几天也没发货,说库存没了。钱到现在也没退给我。
    est
        6
    est  
       2017-10-26 15:05:58 +08:00
    所以之前 bbs 里的要参与活动的人每人回帖,最后随机抽一个楼层,这样是最公平的。
    jadec0der
        7
    jadec0der  
    OP
       2017-10-26 15:08:32 +08:00
    @invoke
    @airyland 抢购和抽奖是两码事,先到先得是抢购的基本要求,否则和前端直接 alert("抢购失败") 有什么区别
    n2ex2
        8
    n2ex2  
       2017-10-26 15:10:26 +08:00 via Android
    @ScotGu 还有版本是拿电风扇吹,吹走的简历就扔了
    invoke
        9
    invoke  
       2017-10-26 15:13:41 +08:00
    @jadec0der

    不啊,有些就是这么做的。
    之前我抢美图的一个手机也有类似的措施。
    更别提最近的大麦网了。直接给你某些时段某些人刷出来的就是个 html 页面。
    你能不能抢到,还是排队。根本不是他关心的,因为销售方知道肯定是几秒内就全卖光了。
    而且这么处理成本极低,不是吗?
    vjnjc
        10
    vjnjc  
       2017-10-26 15:13:49 +08:00
    感觉合理啊。
    如果改成第一个人抢得到,第二个人抢不到,第三个人抢得到。这种情况也有 [第二个人抢不到,第三个人抢得到] 这种不公平的现象发生。而如果把简单暴力的二分限流去掉的话 doBuy()很容易挂啊,以京东到家的用户来说。
    jadec0der
        11
    jadec0der  
    OP
       2017-10-26 15:31:16 +08:00   ❤️ 2
    @invoke 大麦网确实是技术能力不行,我看了他那个技术总监的文章了,但是京东也这样确实是让友商惊诧。

    @vjnjc 是啊,所以正常的秒杀系统都是搞个 FIFO 的排队模块,把先到的那部分放出去而不是随机放出去一部分。比如:
    http://www.infoq.com/cn/articles/solution-to-the-architecture-of-spike-system
    http://www.infoq.com/cn/articles/flash-deal-architecture-optimization
    http://www.infoq.com/cn/articles/yhd-11-11-queuing-system-design/
    http://www.infoq.com/cn/articles/how-to-design-a-small-and-beautiful-spike-system
    Shura
        12
    Shura  
       2017-10-26 15:37:05 +08:00
    从概率上看都一样,所以很合理的措施。
    nopy
        13
    nopy  
       2017-10-26 15:37:58 +08:00 via Android
    小米商城也是这样,之前抢小米 6 怎么抢都是直接排队中,同学进去一抢就抢到了...感觉我的号已经黑号了,直接告诉我不好吗!
    eloah
        14
    eloah  
       2017-10-26 15:42:27 +08:00   ❤️ 1
    因为它不在乎谁抢到,公平不公平,反正它赚的钱是一样的
    它只在乎利用抢来促销而已
    GOOD21
        15
    GOOD21  
       2017-10-26 15:52:51 +08:00
    做这个策略一定是触发了某个阈值的,不可能上来就直接 50%这样大概率的“抢购失败”。

    能想到的场景,比如用户的抢购请求全部进入 MQ,消费的时候判断一下 Message 的 count 值,超过 xxx,再 50%的失败
    jadec0der
        16
    jadec0der  
    OP
       2017-10-26 16:29:31 +08:00
    @GOOD21 你看我发的那几个链接,正常设计都是阈值比库存总量大一些,这样超过阈值直接失败就可以了。
    doskoi
        17
    doskoi  
       2017-10-26 17:07:38 +08:00
    如果前面最快抢到的都是非人类行为,一开放没多久,就被黄牛用软件抢光了。
    这样还是会跳出来说不公平。

    公平是相对于规则所限制的人群的。
    daysv
        18
    daysv  
       2017-10-26 17:21:58 +08:00
    的确, 这种代码让人难以接受
    6IbA2bj5ip3tK49j
        19
    6IbA2bj5ip3tK49j  
       2017-10-26 17:55:54 +08:00
    我记得之前看小米的分享,好像是先排满 1000 的队列,其余直接返回失败,然后等着 1000 人下单或者时间达到阈值,再放 1000 人进来,这样循环。
    kwkwkkk
        20
    kwkwkkk  
       2017-10-26 18:06:52 +08:00
    @ScotGu 让我想到华为校招了,当年随机抽取简历。。。
    watzds
        21
    watzds  
       2017-10-26 20:43:38 +08:00
    @jadec0der 你好,你列的第一篇文章中“增加分配 ID 标志,去掉行锁”,请问你知道什么意思吗?怎么会去掉行锁的

    http://www.infoq.com/cn/articles/solution-to-the-architecture-of-spike-system
    jadec0der
        22
    jadec0der  
    OP
       2017-10-27 03:20:10 +08:00
    @watzds 我也没看明白,按理说每行一个库存在修改状态的时候也需要行锁的。
    watzds
        23
    watzds  
       2017-10-27 09:35:39 +08:00 via Android
    @jadec0der 嗯,最多不用锁在同一行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3606 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:46 · PVG 18:46 · LAX 02:46 · JFK 05:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.