关于用 redis 判断库存的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Ashenone0
V2EX    PHP

关于用 redis 判断库存的问题

  •  
  •   Ashenone0 2020-07-15 16:36:16 +08:00 4174 次点击
    这是一个创建于 1926 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前看到两种方法。 一种是用 string 类型直接存库存大小,减库存减掉数字的大小就可以了。有人说在高并发时,库存有可能减到负数。 一种是用 list 类型创建与库存大小一致的数据。减库存移除 list 中的元素,这样不会出现第一种的库存为负的问题。 我自己试了下了,使用第二种方法,如果库存量特别大时,创建缓存的会特别慢 请大佬指教一下

    16 条回复    2020-07-16 22:57:25 +08:00
    wudila
        1
    wudila  
       2020-07-15 16:45:35 +08:00
    感觉只是计数的话 用第一种就好了.至于并发问题 可以增加一个分布式锁来解决
    Ashenone0
        2
    Ashenone0  
    OP
       2020-07-15 16:57:21 +08:00
    @wudila 类似抢购的那种的话,用第一种+分布式锁是吗?
    colia
        3
    colia  
       2020-07-15 16:59:08 +08:00
    redis 集群做的吗
    TypeErrorNone
        4
    TypeErrorNone  
       2020-07-15 16:59:38 +08:00
    第一种,incr 操作,用 incr 返回的值做是否有剩余库存的判断
    zhongjun96
        5
    zhongjun96  
       2020-07-15 17:01:31 +08:00
    incr 返回值大于 0 就行了
    xuanbg
        6
    xuanbg  
       2020-07-15 17:02:25 +08:00   1
    @Ashenone0 抢购可以先用令牌桶限流,只有有资格的才能购买。你见过电影院检票口阻塞吗?因为卖票的地方给挡住了流量,所以检票就可以很从容。
    TypeErrorNone
        7
    TypeErrorNone  
       2020-07-15 17:04:17 +08:00
    @xuanbg 套娃...抢票怎么处理,如果超发了很多,都过来检票了
    nicreve
        8
    nicreve  
       2020-07-15 17:07:37 +08:00
    如果本身没有扣减库存后购买失败需要加回库存的需求的话,单纯执行 DECR,业务侧判断返回值是否>=0 就可以了。
    稍微复杂点的话就通过 Lua 脚本在 Redis 侧做下简单的处理,只有库存大于 0 时可以 DECR,然后把是否扣减了返回给业务侧。
    xuanbg
        9
    xuanbg  
       2020-07-15 17:10:52 +08:00
    @TypeErrorNone 令牌桶里面令牌发完了就完了啊,怎么可能超发?不过为了避免有些人拿到令牌不下单,一般都会合理设置一些余量,譬如商品 100,那就发 150 个令牌。然后下单减库存加锁避免超卖就行了。
    sujin190
        10
    sujin190  
       2020-07-15 17:13:46 +08:00
    @nicreve #8 不可能没有下单失败补回库存的情况吧,存件减又必须在下单前
    Philippa
        11
    Philippa  
       2020-07-15 17:39:32 +08:00 via iPhone
    我从没做过这类业务,但感觉抢购主要是超售,售少了几个没关系可以继续卖。用一个 list,来订单就 pop,pop 失败了就返回失败。成功了再生成订单。有些人不付款,超时后把队列填回去就好了。用 incrby 还是 decrby 都要查询,查询这个动作会消耗额外一次网络传输。即使用 pipeline,那也要做两个操作。相反,list 做修改时它本来就是用 quicklist 的,pop 的时候就必须检查长度。同时两端 pop 和 append 操作都是 O(1)操作。当然 load balance 首先要限制 ratelimit,不要直接把 redis 打爆了。订单一定要用 acid 的数据库来保存。中间还可以加个队列。
    huntcool001
        12
    huntcool001  
       2020-07-15 17:55:33 +08:00
    "如果库存量特别大时,创建缓存的会特别慢 "

    你提前建立好库存不就行了, 又不是一边秒杀一边建,时间长一点没什么. 而且用 pipeline,别一个一个添加到 list 里.
    wudila
        13
    wudila  
       2020-07-15 18:02:43 +08:00
    @Ashenone0 看你并发流量有多大了.一般情况下这样就行了.流量很大的话可以增加一个队列 异步处理.其实像其他人说的用 incr 的返回值判断下也可以.因为 redis 是单线程的
    312ybj
        14
    312ybj  
       2020-07-15 19:34:17 +08:00 via Android
    流量不大,都可以。 大的话,就得加锁了,肯定会有效率的问题,redis 可以用 redisson 实现分布式群
    yc8332
        15
    yc8332  
       2020-07-16 09:25:08 +08:00
    redis 只保存自增啊,看你是要减还是加,最后的判断是在业务逻辑,比如减到小于 0,那说明库存不足,然后给加回去。。报库存不足就行了
    Ashenone0
        16
    Ashenone0  
    OP
       2020-07-16 22:57:25 +08:00
    @huntcool001 刚接触 redis,不知道有 pipeline 。一条条创建发现太慢了,用了 pipeline 基本是无延迟创建 list 。谢谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     924 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 20:16 PVG 04:16 LAX 13:16 JFK 16:16
    Do have faith in what you're doing.
    ubao msn 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