复述,实现高并发分布式锁

  

分布式锁场景

在分布式环境下多个操作需要以原子的方式执行

首先启一个springboot项目,再引入复述,依赖包:

org.springframework。启动

spring-boot-starter-data-redis 2.2.2

。发布

以下是一个扣减库存的接口作为例子:

@RestController

公共类IndexController {

@ autowired

私人StringRedisTemplate StringRedisTemplate;

@RequestMapping (“/deduct_stock”)

公共Stirng deductStock () {

int股票=Integer.parseInt (stringRedisTemplate.opsForValue () . get(“股票”));//jedis.get(关键)

如果股票比;0){

int realStock=股票- 1;

stringRedisTemplate.opsForValue.set(“股票”,realStock + ");//jedis.set(键值)

system . out。println(扣减成功,剩余库存:" + realStock + ");其他

} {

System.out.println(扣减失败,库存不足!”);

}

返回“结束”;

}

}

1。单实例应用场景

以上代码使用JMeter压测工具进行调用,设置参数为:

[用户]的线程数量:100

增加周期(秒):0

循环数:2

用单个web调用,结果出现并发问题:

<中心> 复述,实现高并发分布式锁


解决方案:加入同步锁(同步)

@RestController

公共类IndexController {

@ autowired

私人StringRedisTemplate StringRedisTemplate;

@RequestMapping (“/deduct_stock”)

公共Stirng deductStock () {

同步(){

int股票=Integer.parseInt (stringRedisTemplate.opsForValue () . get(“股票”));//jedis.get(关键)

如果股票比;0){

int realStock=股票- 1;

stringRedisTemplate.opsForValue.set(“股票”,realStock + ");//jedis.set(键值)

system . out。println(扣减成功,剩余库存:" + realStock + ");其他

} {

System.out.println(扣减失败,库存不足!”);

}

返回“结束”;

}

}

}

2。多实例分布式场景

以上代码,比如有多个应用程序,用nginx做负载均衡,进行同时调用压测

两个程序存在同样的扣减,出现并发现象。

第一个应用扣减结果显示:

<中心> 复述,实现高并发分布式锁


第二个应用扣减结果显示:

<中心> 复述,实现高并发分布式锁


解决方案:复述的setnx方法(可参考setnx的api)

多个线程setnx调用时,有且仅有一个线程会拿到这把锁,所以拿到锁的执行业务代码,最后释放掉锁,代码如下:

@RestController

公共类IndexController {

@ autowired

私人StringRedisTemplate StringRedisTemplate;

@RequestMapping (“/deduct_stock”)

公共Stirng deductStock () {

字符串lockkey=發ockkey”;

布尔结果=stringRedisTemplate.opsForValue.setIfAbsent (lockkey lockvalue ");//能。setnx

如果(!结果){

返回";

}

int股票=Integer.parseInt (stringRedisTemplate.opsForValue () . get(“股票”));//jedis.get(关键)

如果股票比;0){

int realStock=股票- 1;

stringRedisTemplate.opsForValue.set(“股票”,realStock + ");//jedis.set(键值)

system . out。println(扣减成功,剩余库存:" + realStock + ");其他

} {

System.out.println(扣减失败,库存不足!”);

}

springRedisTemplate.delete (lockkey);

返回“结束”;

}

}

调用200次,压测结果显示还是有问题,只减掉了一部分:

<中心> 复述,实现高并发分布式锁


这时,加大压测次数,结果正常了:

第一个应用扣减结果显示:

<中心> 复述,实现高并发分布式锁


第二个应用扣减结果显示:

<中心> 复述,实现高并发分布式锁


这个只是因为加大了调用次数,执行业务代码需要一点时间,这段时间拒绝了很多等待获取锁的请求。但是,还是有问题,假如复述,服务挂掉了,抛出异常了,这时锁不会被释放掉,出现死锁问题,可以添加试试   抓处理,代码如下:

@RestController

复述,实现高并发分布式锁