关于用 redis 判断库存的问题

2020-07-15 16:36:16 +08:00
 Ashenone0

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

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

你提前建立好库存不就行了, 又不是一边秒杀一边建,时间长一点没什么. 而且用 pipeline,别一个一个添加到 list 里.
wudila
2020-07-15 18:02:43 +08:00
@Ashenone0 看你并发流量有多大了.一般情况下这样就行了.流量很大的话可以增加一个队列 异步处理.其实像其他人说的用 incr 的返回值判断下也可以.因为 redis 是单线程的
312ybj
2020-07-15 19:34:17 +08:00
流量不大,都可以。 大的话,就得加锁了,肯定会有效率的问题,redis 可以用 redisson 实现分布式群
yc8332
2020-07-16 09:25:08 +08:00
redis 只保存自增啊,看你是要减还是加,最后的判断是在业务逻辑,比如减到小于 0,那说明库存不足,然后给加回去。。报库存不足就行了
Ashenone0
2020-07-16 22:57:25 +08:00
@huntcool001 😂刚接触 redis,不知道有 pipeline 。一条条创建发现太慢了,用了 pipeline 基本是无延迟创建 list 。谢谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/690282

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX