在单体架构中,我们使用synchronize或者Lock就能完成上锁同步的操作,但是这些在分布式,微服务的今天,失去了作用。
分布式锁的实现一般有三种解决方案:
- 基于数据库表实现
- 基于缓存实现,比如redis
- 基于zookeeper实现
那么利用redisson就是基于redis来实现的分布式锁功能。
什么是redisson
官网:https://redisson.org
从首页的,我们可以大致看出redisson可以实现很多东西,在redisson的基础上,redisson做了超多的封装。
redisson可以完成很多功能,比如缓存各种队列,包括map等这些数据结构,也能完成分布式任务调度,还能完成今天我们说的分布式锁的功能。总之一句话:Redisson是非常强大。
利用redisson完成分布式锁功能
Quick start
我们先看看官网上是如何介绍快速使用redisson。
以上是官网的使用介绍。那么今天以官网的方式来实现我们自己的分布式锁
一,引入maven依赖
org.redisson redisson 3.11.5
二,创建分布式锁工具类
@Componentpublic class DistributedLockerUtil {
private RedissonClient redissonClient; @PostConstruct private void init() { if(redissonClient != null){ return; } //配置config,如果是单机版的redis,那么就是使用config.useSingleServer() //如果是集群,那么请使用config.useClusterServers() Config config = new Config(); config.useSingleServer().setAddress("redis://10.10.100.116:6379"); redissonClient = Redisson.create(config); } /** * 获取RedissonClient * @return */ public RedissonClient getRedissonClient(){ return this.redissonClient; } /** * 加锁 * @return */ public void lock(String lockKey){ redissonClient.getLock(lockKey).lock(); } /** * 释放锁 */ public void unLock(String lockKey){ redissonClient.getLock(lockKey).unlock(); } /** * 带超时的加锁 * @param lockKey * @param tomeout 秒为单位 */ public void lock(String lockKey, Long tomeout){ redissonClient.getLock(lockKey).lock(tomeout, TimeUnit.SECONDS); } /** * 带超市的加锁 * @param lockKey * @param unit 时间单位 * @param tomeout */ public void lock(String lockKey, TimeUnit unit,Long tomeout){ redissonClient.getLock(lockKey).lock(tomeout, unit); } /** * 尝试获取锁 * @param lockKey * @return */ public boolean tryLock(String lockKey){ return redissonClient.getLock(lockKey).tryLock(); } /** * 尝试获取锁 * @param lockKey * @param timeout 尝试等待多少秒时间 * @return * @throws InterruptedException */ public boolean tryLock(String lockKey,Long timeout) throws InterruptedException { return redissonClient.getLock(lockKey).tryLock(timeout, TimeUnit.SECONDS); } /** * * @param lockKey * @param unit 时间单位 * @param waitTime 最多等待多久时间 * @param leaseTime 上锁后多久释放 * @return */ public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) throws InterruptedException { return redissonClient.getLock(lockKey).tryLock(waitTime,leaseTime,unit); } }
创建好之后,就可以使用以上util进行分布式锁的操作
三,新建controller
简单点,我们实现增加库存的业务。每次走进controller增加库存的方法,我们就+1。为了演示效果,其中addStockYaGao方法不加分布式锁,而addStockYaShua加入分布式锁。
@RequestMapping("/stock") @RestController public class StockController { @Autowired private StockService stockService; @Autowired private DistributedLockerUtil distributedLockerUtil; @GetMapping("/addStockYaGao") public String addStockYaGao(){ Stock stock = stockService.getOne(1); stock.setCount(stock.getCount() + 1); stockService.save(stock); return "增加牙膏成功"; } @GetMapping("/addStockYaShua") public String addStockYaShua(){ try { distributedLockerUtil.lock("addStock"); Stock stock = stockService.getOne(2); stock.setCount(stock.getCount() + 1); stockService.save(stock); return "增加牙刷成功"; }catch (Exception e){ e.printStackTrace(); return "增加牙刷失败"; }finally { distributedLockerUtil.unLock("addStock"); } } }
四,表数据
原始数据如下:
表对应实体类以及dao,service这里就不贴出来了。
五,JMeter测试效果
测试并发参数:
先对不加锁的addStockYaGao进行测试,
结果:
明显数据不对,300个用户请求,按理来说最后的结果应该是300
再对加锁的addStockYaShua进行测试
结果:
数据正确,更新到了300
总结,使用redisson完成分布式锁功能还是很简单的,大家get得到了吗?
本人水平有限,难免有错误或遗漏之处,望大家指正和谅解,提出宝贵意见,愿与之交流。