集成redisson分布式锁

折月煮酒 提交于 2019-12-04 05:44:38

一、redisson是什么

      Redisson是架设在redis基础上的一个Java主内存网络,并且是redis官方推荐的。Redisson在基于NIO的Netty框架上,充分利用了redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。这样就使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和压法大规模分布式系统 的难度。同时结合丰富的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
      我们下面介绍的分布式锁,只是其中的一个应用。

二、为什么要用redisson分布式锁

(一)为什么用锁

      锁一般用在并发情况下,我们用抢红包这个场景来分析,假设有100个人抢10个红包,假如现在还剩1个红包,但是有10个人都来抢这之后一个包,因为是并发的所有这10个人抢的时候都判断还剩一个包,但是我们的红包只剩下一个10个人都抢到了,这就会导致我们发了100个红包,但是一共抢了110个红包。为了解决这个问题我们就需要在真正抢红包的代码前加锁,这样就算10个人都进来了,但是第一个人加锁之后剩下的九个月都会直接返回,不会走抢红包的代码,这样就可以避免超发问题。

(二)为什么用分布式锁

      如果我们的程序采用分布式部署的话,我们必须保证我们的锁对分配到不同服务器上的请求都是起作用的。
      之前的方式是自己写的加锁解锁方法,是根据时间来判断时候可以解锁,这样存在的问题就是解锁不严谨,而且必须保证每台服务器的时间都是一致的,存在很多漏洞。

(三)为什么用redisson分布式锁

      实现中使用了lua脚本,保证原子性执行,而且redisson比较成熟全面。可以更好地解决我们的问题。因为redisson不光是针对于分布式锁,还提供了很多客户端操作redis的方法,所以会依赖一些其它的框架,比如netty,如果只是简单的使用锁也可以自己去实现。

三、redisson分布式锁怎么用

(一)引入相关jar包

<!--Redisson分布式锁-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.6.5</version>
</dependency>

(二)编写配置文件

1、一般spring项目

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:redisson="http://redisson.org/schema/redisson"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://redisson.org/schema/redisson
       http://redisson.org/schema/redisson/redisson.xsd
">
    <!--Redis实现分布式锁 -->
    <redisson:client>
        <redisson:single-server address="redis://192.168.22.64:6379"/>
    </redisson:client>

</beans>

2、springboot项目

/**
 * redisson分布式锁配置文件
 * @author
 * @Date 
 */
@Configuration
public class RedissonConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.database}")
    private int database;

    @Bean
    public RedissonClient getRedisson(){

        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port);
        //一共有三种模式:单击、哨兵、集群,根据实际需要配置即可
        return Redisson.create(config);
    }
}

(三)加锁解锁代码

1、加锁

RLock rlock = redissonClient.getLock("redisson:lock:redPacketID" + normalRedPacket.get(i).getRedPacketId());

“redisson:lock1:redPacketID" + normalRedPacket.get(i).getRedPacketId()”是加锁设置的key值,根据自己的需要设置即可,可以将同一批次的id设置为key键,如果每个人的key键都不一样,那么加锁就没有意义了。

2、解锁

这里将解锁代码放在finally中将保证即使程序出现异常,解锁代码也会执行,当然我们也可以在我们的业务逻辑中也加上解锁,但是在finally加解锁代码以及给锁设置失效时间都可以在一定程度上避免死锁的发生,来让我们的程序更加健壮。

try {
   //业务逻辑
} finally {
    //解锁
    rlock.unlock();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!