Ashenone0
V2EX  ›  PHP

关于用 redis 判断库存的问题

  •  
  •   Ashenone0 · Jul 15, 2020 · 4576 views
    This topic created in 2155 days ago, the information mentioned may be changed or developed.

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

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

    你提前建立好库存不就行了, 又不是一边秒杀一边建,时间长一点没什么. 而且用 pipeline,别一个一个添加到 list 里.
    wudila
        13
    wudila  
       Jul 15, 2020
    @Ashenone0 看你并发流量有多大了.一般情况下这样就行了.流量很大的话可以增加一个队列 异步处理.其实像其他人说的用 incr 的返回值判断下也可以.因为 redis 是单线程的
    312ybj
        14
    312ybj  
       Jul 15, 2020 via Android
    流量不大,都可以。 大的话,就得加锁了,肯定会有效率的问题,redis 可以用 redisson 实现分布式群
    yc8332
        15
    yc8332  
       Jul 16, 2020
    redis 只保存自增啊,看你是要减还是加,最后的判断是在业务逻辑,比如减到小于 0,那说明库存不足,然后给加回去。。报库存不足就行了
    Ashenone0
        16
    Ashenone0  
    OP
       Jul 16, 2020
    @huntcool001 😂刚接触 redis,不知道有 pipeline 。一条条创建发现太慢了,用了 pipeline 基本是无延迟创建 list 。谢谢
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2873 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 49ms · UTC 15:23 · PVG 23:23 · LAX 08:23 · JFK 11:23
    ♥ Do have faith in what you're doing.