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個線程將獲取不到。說明鎖起做用了~

相關文章
相關標籤/搜索