spring整合redisson實現分散式鎖
阿新 • • 發佈:2019-02-15
在單程序的系統中,當存在多個執行緒可以同時改變某個變數(可變共享變數)時,就需要對變數或程式碼塊做同步,使其在修改這種變數時能夠線性執行消除併發修改變數。
而Java提供的同步鎖synchronized只能解決單臺伺服器上的併發問題,一般線上環境都是多臺伺服器部署同時執行,跨jvm的環境下synchronized的作用就不大了。這個時候redis就可以作為分佈鎖來使用了,一般都是基於redis setNx命令來實現自己的鎖,建出來的鍵值一般都是有一個超時時間的(這個是Redis自帶的超時特性),所以每個鎖最終都會釋放
這裡介紹的是github上的一個開源專案,國外大神些的演算法畢竟比自己實現的靠譜點
專案原始碼地址,裡面不光有分佈鎖,還有分佈鎖佇列等等一系列模組
https://github.com/redisson/redisson
pom.xml配置檔案引人redisson相關包
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-all</artifactId>
<version>2.10.5</version>
</dependency>
2. 配置方法
2.1. 程式化配置方法
Redisson程式化的配置方法是通過構建Config物件例項來實現的。例如:
public class RedissonUtils {
private static RedissonClient redissonClient;
static{
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword(null);
redissonClient = Redisson.create(config);
}
public static RedissonClient getRedisson(){
return redissonClient;
}
public static void main(String[] args) throws InterruptedException{
RLock fairLock = getRedisson().getLock("TEST_KEY");
System.out.println(fairLock.toString());
// fairLock.lock();
// 嘗試加鎖,最多等待10秒,上鎖以後10秒自動解鎖
boolean res = fairLock.tryLock(10, 10, TimeUnit.SECONDS);
System.out.println(res);
fairLock.unlock();
//有界阻塞佇列
// RBoundedBlockingQueue<JSONObject> queue = getRedisson().getBoundedBlockingQueue("anyQueue");
// 如果初始容量(邊界)設定成功則返回`真(true)`,
// 如果初始容量(邊界)已近存在則返回`假(false)`。
// System.out.println(queue.trySetCapacity(10));
// JSONObject o=new JSONObject();
// o.put("name", 1);
// if(!queue.contains(o)){
// queue.offer(o);
// }
// JSONObject o2=new JSONObject();
// o2.put("name", 2);
// 此時容量已滿,下面程式碼將會被阻塞,直到有空閒為止。
// if(!queue.contains(o2)){
// queue.offer(o2);
// }
// // 獲取但不移除此佇列的頭;如果此佇列為空,則返回 null。
// JSONObject obj = queue.peek();
// //獲取並移除此佇列的頭部,在指定的等待時間前等待可用的元素(如果有必要)。
// JSONObject ob = queue.poll(10, TimeUnit.MINUTES);
//獲取並移除此佇列的頭,如果此佇列為空,則返回 null。
// Iterator<JSONObject> iterator=queue.iterator();
// while (iterator.hasNext()){
// JSONObject i =iterator.next();
// System.out.println(i.toJSONString());
// iterator.remove();
//
// }
// while(queue.size()>0){
// JSONObject ob = queue.poll();
// System.out.println(ob.toJSONString());
// }
//
// JSONObject someObj = queue.poll();
// System.out.println(someObj.toJSONString());
}
2 spring整合的方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://redisson.org/schema/redisson
http://redisson.org/schema/redisson/redisson.xsd">
<context:component-scan base-package="component.controller.RedisServiceImpl" />
<!-- redis連線池 -->
<bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis_max_idle}"></property>
<property name="testOnBorrow" value="${redis_test_on_borrow}"></property>
</bean>
<!-- redis連線工廠 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis_addr}"></property>
<property name="port" value="${redis_port}"></property>
<property name="password" value="${redis_auth}"></property>
<property name="poolConfig" ref="jedisConfig"></property>
</bean>
<!-- redis操作模板,這裡採用儘量面向物件的模板 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<!-- 如果不配置Serializer,那麼儲存的時候只能使用String,如果用物件型別儲存,那麼會提示錯誤 can't cast to String!!!-->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>
<!--redisson配置的例項 單臺redis機器配置 -->
<redisson:client id="redissonClient">
<redisson:single-server address="redis://127.0.0.1:6379" connection-pool-size="30" />
</redisson:client>
</beans>
引入RedissonClient就可以使用了
@Autowired
private RedissonClient redissonClient;
//獲取redissson分散式鎖
RLock fairLock = redissonClient.getLock("TEST_KEY");
//嘗試加鎖 最多等待100秒 20秒後自動銷燬
boolean res = fairLock.tryLock(100, 20, TimeUnit.SECONDS);
//釋放鎖
fairLock.unlock();
提醒:redis版本一定要3.0以上的 不然會報錯,redis lua指令碼