java村支书 · 2019年10月30日

绝对干货:利用redisson完成分布式锁功能

在单体架构中,我们使用synchronize或者Lock就能完成上锁同步的操作,但是这些在分布式,微服务的今天,失去了作用。

分布式锁的实现一般有三种解决方案:

  • 基于数据库表实现
  • 基于缓存实现,比如redis
  • 基于zookeeper实现

那么利用redisson就是基于redis来实现的分布式锁功能。

什么是redisson

官网:https://redisson.org

从首页的,我们可以大致看出redisson可以实现很多东西,在redisson的基础上,redisson做了超多的封装。

file

redisson可以完成很多功能,比如缓存各种队列,包括map等这些数据结构,也能完成分布式任务调度,还能完成今天我们说的分布式锁的功能。总之一句话:Redisson是非常强大。

利用redisson完成分布式锁功能

Quick start

我们先看看官网上是如何介绍快速使用redisson。

file
file

以上是官网的使用介绍。那么今天以官网的方式来实现我们自己的分布式锁

一,引入maven依赖

    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.11.5</version>
    </dependency>
            

二,创建分布式锁工具类

@Component
public 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");
        }
    }
}

四,表数据

原始数据如下:

file

表对应实体类以及dao,service这里就不贴出来了。

五,JMeter测试效果

测试并发参数:

file

先对不加锁的addStockYaGao进行测试,

file

结果:

file

明显数据不对,300个用户请求,按理来说最后的结果应该是300

再对加锁的addStockYaShua进行测试

file

结果:

file

数据正确,更新到了300

总结,使用redisson完成分布式锁功能还是很简单的,大家get得到了吗?

本人水平有限,难免有错误或遗漏之处,望大家指正和谅解,提出宝贵意见,愿与之交流。

推荐阅读
关注数
0
文章数
16
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息