分布式锁的在分布式集群环境中有着至关重要的作用,为了保证高并发场景下数据的一致性,确保业务能够安全的运行,为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程进行调度。而这个分布式协调技术的核心就是来实现这个分布式锁。
首先我们看一段很普通的代码:
@Autowired
StringRedisTemplate stringRedisTemplate;
protected final static String product = "123456789";
@RequestMapping("/order")
public String submitOrder(){
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
if(stock>0){
stock = stock -1;
stringRedisTemplate.opsForValue().set("stock",stock+"");
System.out.println("扣减库存成功"+stock);
}else{
System.out.println("失败");
return "error";
}
return "end";
}
上面的代码想必一看就知道了,就是个简单的扣减库存的操作,从缓存中拿到库存量,然后每次请求去获取到库存进行对应的扣减,但是当我们写完代码之后应该从几个方面做一个思考:
1.代码运行的角度
实际情况下,如果多个请求同时过来,都从缓存中读取数据,能不能正确的扣减库存呢?显然是不能保证,肯定会有线程不安全问题,这里我们采用jemeter进行一个简单的并发测试。
这里简单做个测试,在0秒内同时发起5个请求,观察库存扣减是否正确。
结果清晰可见,明显出现数据扣减出错,我们该如何去解决呢?开始分布式锁的引入,首先介绍一个redis的命令
setnx:if not exists key,如果redis中不存在该key的时候才能后设置成功,这样我们就可以利用这个指令去实现锁,第一个线程到了之后,该命令正常执行,redis中多了一对键值对,其他线程来的时候则无法正确设置,也就是无法拿到锁。
我们对上面代码做一个改进,添加锁机制。
@Autowired
StringRedisTemplate stringRedisTemplate;
protected final static String product = "123456789";
@RequestMapping