Spring Integration實現分佈式鎖

學習本篇以前,能夠先看下文章 什麼是分佈式鎖,瞭解下基本概念。html

以前都是手寫一個分佈式鎖,其實Spring早就提供了分佈式鎖的實現。早期,分佈式鎖的相關代碼存在於Spring Cloud的子項目Spring Cloud Cluster中,後來被遷移到Spring Integration中。redis

Spring Integration提供的全局鎖,目前爲這幾種存儲提供了實現:Gemfire、JDBC、Redis、Zookeeperspring

它們使用相同的API抽象--這正是Spring最擅長的。這意味着,不論使用哪一種存儲,你的編碼體驗都是同樣的,有一天想更換實現,只須要修改依賴和配置就能夠了,無需修改代碼app

 

下面以Redis爲例,講解Spring Integration如何使用分佈式鎖。分佈式

一、增長依賴:spring-boot

<dependency>
    <!-- spring integration -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
    <!-- spring integration與redis結合,實現redis分佈式鎖 -->
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-redis</artifactId>
</dependency>
<dependency>
    <!-- redis -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

二、配置文件增長redis配置:工具

spring:
  redis:
    port: 6379
    host: localhost

三、增長RedisLock的配置類:學習

@Configuration
public class RedisLockConfiguration {

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

}

四、增長測試方法:測試

@RestController
@RequestMapping("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個線程,循環一次:編碼

先測試一下沒有加鎖,會出現什麼結果。請求 http://localhost:18081/redis/testUnLock:

http-nio-18081-exec-22排號成功,號碼是:20
http-nio-18081-exec-28排號成功,號碼是:19
http-nio-18081-exec-16排號成功,號碼是:18
http-nio-18081-exec-30排號成功,號碼是:17
http-nio-18081-exec-26排號成功,號碼是:16
http-nio-18081-exec-15排號成功,號碼是:15
http-nio-18081-exec-15排號成功,號碼是:14
http-nio-18081-exec-3排號成功,號碼是:14
http-nio-18081-exec-26排號成功,號碼是:12
http-nio-18081-exec-15排號成功,號碼是:11
http-nio-18081-exec-3排號成功,號碼是:10
http-nio-18081-exec-15排號成功,號碼是:9
http-nio-18081-exec-30排號成功,號碼是:8
http-nio-18081-exec-26排號成功,號碼是:7
http-nio-18081-exec-3排號成功,號碼是:6
http-nio-18081-exec-15排號成功,號碼是:5
http-nio-18081-exec-3排號成功,號碼是:4
http-nio-18081-exec-26排號成功,號碼是:3
http-nio-18081-exec-15排號成功,號碼是:2
http-nio-18081-exec-3排號成功,號碼是:1
http-nio-18081-exec-30排號失敗,號碼已經被搶光
http-nio-18081-exec-22排號成功,號碼是:14
http-nio-18081-exec-28排號成功,號碼是:14
http-nio-18081-exec-15排號成功,號碼是:1
http-nio-18081-exec-16排號成功,號碼是:12

從上面結果能夠看到,num變量的有些值被多個線程同時獲取,致使20個號被24個線程獲取

再來試下加鎖的,請求 http://localhost:18081/redis/testLock:

http-nio-18081-exec-2排號成功,號碼是:20
http-nio-18081-exec-142排號成功,號碼是:19
http-nio-18081-exec-141排號成功,號碼是:18
http-nio-18081-exec-171排號成功,號碼是:17
http-nio-18081-exec-152排號成功,號碼是:16
http-nio-18081-exec-159排號成功,號碼是:15
http-nio-18081-exec-154排號成功,號碼是:14
http-nio-18081-exec-156排號成功,號碼是:13
http-nio-18081-exec-142排號成功,號碼是:12
http-nio-18081-exec-158排號成功,號碼是:11
http-nio-18081-exec-172排號成功,號碼是:10
http-nio-18081-exec-161排號成功,號碼是:9
http-nio-18081-exec-160排號成功,號碼是:8
http-nio-18081-exec-164排號成功,號碼是:7
http-nio-18081-exec-162排號成功,號碼是:6
http-nio-18081-exec-171排號成功,號碼是:5
http-nio-18081-exec-170排號成功,號碼是:4
http-nio-18081-exec-152排號成功,號碼是:3
http-nio-18081-exec-165排號成功,號碼是:2
http-nio-18081-exec-157排號成功,號碼是:1
http-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個線程將獲取不到。說明鎖起做用了~

相關文章
相關標籤/搜索