1. 程式人生 > >spring整合redisson實現分散式鎖

spring整合redisson實現分散式鎖

在單程序的系統中,當存在多個執行緒可以同時改變某個變數(可變共享變數)時,就需要對變數或程式碼塊做同步,使其在修改這種變數時能夠線性執行消除併發修改變數。

而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指令碼