天天看点

redission分布式锁实现_Spring Integration实现分布式锁

作者 | 仅此而已-远方

来源 | urlify.cn/b2umMv

学习本篇之前,可以先看下文章 什么是分布式锁,了解下基本概念。

之前都是手写一个分布式锁,其实Spring早就提供了分布式锁的实现。早期,分布式锁的相关代码存在于Spring Cloud的子项目Spring Cloud Cluster中,后来被迁移到Spring Integration中。

Spring Integration提供的全局锁,目前为这几种存储提供了实现:Gemfire、JDBC、Redis、Zookeeper

它们使用相同的API抽象--这正是Spring最擅长的。这意味着,不论使用哪种存储,你的编码体验都是一样的,有一天想更换实现,只需要修改依赖和配置就可以了,无需修改代码

下面以Redis为例,讲解Spring Integration如何使用分布式锁。

1、增加依赖:

        org.springframework.boot    spring-boot-starter-integration        org.springframework.integration    spring-integration-redis        org.springframework.boot    spring-boot-starter-data-redis           

2、配置文件增加redis配置:

spring:  redis:    port: 6379    host: localhost           

3、增加RedisLock的配置类:

@Configurationpublic class RedisLockConfiguration {    @Bean    public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {        return new RedisLockRegistry(redisConnectionFactory, "spring-cloud");    }}           

4、增加测试方法:

@[email protected]("redis")public class RedisController {    @Autowired    private RedisLockRegistry redisLockRegistry;    private int num = 20;    /**     * 测试redis分布式锁(没有锁)     */    @GetMapping("testUnLock")    public void testUnLock() throws InterruptedException {        String s = Thread.currentThread().getName();        if (num > 0) {            System.out.println(s + "排号成功,号码是:" + num);            num--;        } else {            System.out.println(s + "排号失败,号码已经被抢光");        }    }    /**     * 测试redis分布式锁(有锁)     */    @GetMapping("testLock")    public void testLock() throws InterruptedException {        Lock lock = redisLockRegistry.obtain("lock");        boolean isLock = lock.tryLock(1, TimeUnit.SECONDS);        String s = Thread.currentThread().getName();        if (num > 0 && isLock) {            System.out.println(s + "排号成功,号码是:" + num);            num--;        } else {            System.out.println(s + "排号失败,号码已经被抢光");        }        lock.unlock();    }}           

使用压测工具(如:JMeter),开启25个线程,循环一次:

redission分布式锁实现_Spring Integration实现分布式锁

先测试一下没有加锁,会出现什么结果。请求 http://localhost:18081/redis/testUnLock:

http-nio-18081-exec-22排号成功,号码是:20http-nio-18081-exec-28排号成功,号码是:19http-nio-18081-exec-16排号成功,号码是:18http-nio-18081-exec-30排号成功,号码是:17http-nio-18081-exec-26排号成功,号码是:16http-nio-18081-exec-15排号成功,号码是:15http-nio-18081-exec-15排号成功,号码是:14http-nio-18081-exec-3排号成功,号码是:14http-nio-18081-exec-26排号成功,号码是:12http-nio-18081-exec-15排号成功,号码是:11http-nio-18081-exec-3排号成功,号码是:10http-nio-18081-exec-15排号成功,号码是:9http-nio-18081-exec-30排号成功,号码是:8http-nio-18081-exec-26排号成功,号码是:7http-nio-18081-exec-3排号成功,号码是:6http-nio-18081-exec-15排号成功,号码是:5http-nio-18081-exec-3排号成功,号码是:4http-nio-18081-exec-26排号成功,号码是:3http-nio-18081-exec-15排号成功,号码是:2http-nio-18081-exec-3排号成功,号码是:1http-nio-18081-exec-30排号失败,号码已经被抢光http-nio-18081-exec-22排号成功,号码是:14http-nio-18081-exec-28排号成功,号码是:14http-nio-18081-exec-15排号成功,号码是:1http-nio-18081-exec-16排号成功,号码是:12           

从上面结果可以看到,num变量的有些值被多个线程同时获取,导致20个号被24个线程获取

再来试下加锁的,请求 http://localhost:18081/redis/testLock:

http-nio-18081-exec-2排号成功,号码是:20http-nio-18081-exec-142排号成功,号码是:19http-nio-18081-exec-141排号成功,号码是:18http-nio-18081-exec-171排号成功,号码是:17http-nio-18081-exec-152排号成功,号码是:16http-nio-18081-exec-159排号成功,号码是:15http-nio-18081-exec-154排号成功,号码是:14http-nio-18081-exec-156排号成功,号码是:13http-nio-18081-exec-142排号成功,号码是:12http-nio-18081-exec-158排号成功,号码是:11http-nio-18081-exec-172排号成功,号码是:10http-nio-18081-exec-161排号成功,号码是:9http-nio-18081-exec-160排号成功,号码是:8http-nio-18081-exec-164排号成功,号码是:7http-nio-18081-exec-162排号成功,号码是:6http-nio-18081-exec-171排号成功,号码是:5http-nio-18081-exec-170排号成功,号码是:4http-nio-18081-exec-152排号成功,号码是:3http-nio-18081-exec-165排号成功,号码是:2http-nio-18081-exec-157排号成功,号码是:1http-nio-18081-exec-168排号失败,号码已经被抢光http-nio-18081-exec-159排号失败,号码已经被抢光http-nio-18081-exec-166排号失败,号码已经被抢光http-nio-18081-exec-163排号失败,号码已经被抢光http-nio-18081-exec-177排号失败,号码已经被抢光           

从上面结果可以看到,20个号挨个被20个线程获取,剩下5个线程将获取不到。说明锁起作用了~

继续阅读