Redis做库存扣减

Redis的incrby 命令可以用做库存扣减,扣减项可能多个,我们使用Hash结构的hincrby命令,先用Reids原生命令模拟整个过程,为了简化模型我们演示一个数据项的操作,多个数据项原理完全等同。

127.0.0.1:6379> hset iphone inStock 1 #设置苹果手机有一个可售库存
(integer) 1
127.0.0.1:6379> hget iphone inStock   #查看苹果手机可售库存为1
"1"
127.0.0.1:6379> hincrby iphone inStock -1 #卖出扣减一个,返回剩余0,下单成功
(integer) 0
127.0.0.1:6379> hget iphone inStock #验证剩余0
"0"
127.0.0.1:6379> hincrby iphone inStock -1 #应用并发超卖但Redis单线程返回剩余-1,下单失败
(integer) -1
127.0.0.1:6379> hincrby iphone inStock 1 #识别-1,回滚库存加一,剩余0
(integer) 0
127.0.0.1:6379> hget iphone inStock #库存恢复正常
"0"

如果应用调用Redis扣减后,不知道是否成功,可以针对批量扣减命令增加一个防重码,对防重码执行setnx命令,当发生异常的时候,可以根据防重码是否存在来决定是否扣减成功,针对批量命名可以使用pipeline提高成功率。

// 初始化库存
127.0.0.1:6379> hset iphone inStock 1 #设置苹果手机有一个可售库存
(integer) 1
127.0.0.1:6379> hget iphone inStock   #查看苹果手机可售库存为1
"1"

// 应用线程一扣减库存,订单号a100,jedis开启pipeline
127.0.0.1:6379> set a100_iphone "1" NX EX 10 #通过订单号和商品防重码
OK
127.0.0.1:6379> hincrby iphone inStock -1 #卖出扣减一个,返回剩余0,下单成功
(integer) 0
//结束pipeline,执行结果OK和0会一起返回

如果调用中发生网络抖动,调用Redis超时,应用不知道操作结果,可以通过get命令来查看防重码是否存在来判断是否扣减成功。

127.0.0.1:6379> get a100_iphone   #扣减成功
"1"
127.0.0.1:6379> get a100_iphone   #扣减失败
(nil)

待思考:pipeline和事务哪个更靠谱?为什么?

你可能感兴趣的:(互联网)