问题解决:增加分布式锁
使用redis的setnx可以实现分布式锁
Redis的setnx方法解析:
SETNX key value
将 key 的值设为 value ,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
代码块:
####################### 分布式应用商品减库存 redis实现分布式锁#######################
@RequestMaping("/delete_stock")
public String deductstock(){
String lockKey = "product_101";
String clientId =UUID.randomUUID().toString();
Boolean result = springRedisTemplate.opsForValue().setIfAbsent(lockKey ,clientId ,10,TimeUnit.SECONDS);
if(!result ){
return "false"
}
try{
int stock = Integer.parseInt(springRedisTemplate.opsForValue().get("stock"));
if(stock >0){
int realStock = stock -1;
springRedisTemplate.opsForValue().set("stock",realStock +"");
system.out.println("扣减成功,剩余库存:"+realStock );
}else{
system.out.println("扣减失败,库存不足" );
}
}finally{
if(clientId .equals(springRedisTemplate.opsForValue().get(lockKey ))){
springRedisTemplate.delete(lockKey );
}
}
}
Redisson实现分布式锁:
简介:Redisson 在基于 NIO 的 Netty 框架上,充分的利⽤了 Redis 键值数据库提供的⼀系列优势,在
Java 实⽤⼯具包中常⽤接⼝的基础上,为使⽤者提供了⼀系列具有分布式特性的常⽤⼯具
类。使得原本作为协调单机多线程并发程序的⼯具包获得了协调分布式多机多线程并发系统
的能⼒,⼤⼤降低了设计和研发⼤规模分布式系统的难度。同时结合各富特⾊的分布式服
务,更进⼀步简化了分布式环境中程序相互之间的协作
Redisson加锁是通过lua脚本实现
if (redis.call('exists', KEYS[1]) == 0) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
"return redis.call('pttl', KEYS[1]);"
代码块:
\\ 加锁
Rolck redissinLock = redisson.getLock(lockkey);
redissinLock.lock();
\\ 解锁
redissinLock.unlock();
网友评论