redis rua解决库存问题

编程入门 行业动态 更新时间:2024-10-10 03:26:04

redis rua解决<a href=https://www.elefans.com/category/jswz/34/1762884.html style=库存问题"/>

redis rua解决库存问题

项目总结59:Redis分布式锁解决电商订单库存并发问题

在电商分布式项目中,需要考虑提交订单时,因为并发的原因导致库存异常的情况。

其中一个解决方案是:使用redis锁,因为Redis是单线程的,即线程安全的;在提交订单的时候,先通过Redis锁进行库存判断,如果库存校验通过,则正常提交顶顶那,否则返回失败。

具体逻辑如下:

1- 用户请求提交订单接口,接口内先通过Redis锁进行库存校验(如果第一次获取锁失败,则会继续请求锁,但不超过5次);

2- Redis锁进行库存校验,从订单层面具有排他性(即一个订单在进行Redis锁库存校验时),其它提交的订单只能等待。

3- 且Redis锁进行库存校验,做两件事:(1)进行Redis库存校验,如果库存不够,则返回false;否则继续(2);(2)进行Redis减库存操作。

4-Redis锁进行库存校验通过后,订单信息被正常提交。

具体代码如下

@AutowiredprivateCommonRedisHelper commonRedisHelper;public final static String PREFIX_LOCK_ORDER_SUBMIT = "lock_orderSubmit";//校验并更新库存

public Boolean updateStockToRedis(ListcartIdList){boolean lock =commonRedisHelper.lock(PREFIX_LOCK_ORDER_SUBMIT);if(lock){//更新redis中sku的库存//代码略... reduceMultiSkuStock(cartIdList)//删除锁

commonRedisHelper.delete(PREFIX_LOCK_ORDER_SUBMIT);return true;

}else{//设置失败次数计数器, 当到达5次时, 返回失败

int failCount = 1;while(failCount <= 5){//等待100ms重试

try{

Thread.sleep(100);

}catch(InterruptedException e) {

e.printStackTrace();

}if(commonRedisHelper.lock(PREFIX_LOCK_ORDER_SUBMIT)){//执行逻辑操作//更新redis中sku的库存//代码略... reduceMultiSkuStock(cartIdList)//删除锁

commonRedisHelper.delete(PREFIX_LOCK_ORDER_SUBMIT);return true;

}else{

failCount++;

}

}return false;

}

}//判断并更新某个SKU库存

private boolean reduceMultiSkuStock(ListcartIdList){//2-判断秒杀商品SKU是否足够//代码略...//2-更新秒杀商品的库存//代码略...

}

CommonRedisHelper 类

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisCallback;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importjava.util.Objects;

@Componentpublic classCommonRedisHelper {//锁名称

public static final String LOCK_PREFIX = "redis_lock";//加锁失效时间,毫秒

public static final int LOCK_EXPIRE = 300; //ms

@Autowired

RedisTemplate redisTemplate;/*** 最终加强分布式锁

*

*@paramkey key值

*@return是否获取到*/

public booleanlock(String key){

String lock= LOCK_PREFIX +key;//利用lambda表达式

return (Boolean) redisTemplate.execute((RedisCallback) connection ->{//当前锁的过期时间

long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;//当锁不存在时,设置锁,key为锁名称,value为过期时间

Boolean acquire =connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());if(acquire) {//如果设置成功,则返回true

return true;

}else{//如果锁没有设置成功//获取已经存在的锁的value(即已经存在的锁的过期时间)

byte[] value =connection.get(lock.getBytes());//当已经存在的旧锁的过期时间存在时

if (Objects.nonNull(value) && value.length > 0) {long expireTime = Long.parseLong(newString(value));//如果旧锁已经过期,则重新加锁

if (expireTime

byte[] oldValue = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());//判断:如果旧锁已经过期,则返回true,否则返回false

return Long.parseLong(new String(oldValue))

}

}

}return false;

});

}/*** 删除锁

*

*@paramkey*/

public voiddelete(String key) {

String lock= LOCK_PREFIX +key;

redisTemplate.delete(lock);

}

}

更多推荐

redis rua解决库存问题

本文发布于:2024-03-06 01:01:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1713944.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:库存   redis   rua

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!