兩行程式碼 完成分散式鎖
阿新 • • 發佈:2018-11-19
springboot + lombock + redission 實現分散式
1 緣起
由於工作中需要用到分散式鎖,在檢視很多部落格以後,發現很多部落格都是錯誤的,於是就完成了 《Java 正確實現 redis 分散式鎖》(下面有連結) ,但是心中一直不大滿意,直到我發現了 redission, 愛折騰的我有了下面的故事。。。
- 通過 jedis 實現的分散式鎖, 參照之前的文章
Java 正確實現 redis 分散式鎖https://blog.csdn.net/qq_35704236/article/details/80406916
2 效果
技術服務業務,當然是越簡單越好
RedissLockUtil.lock("ORDER_123456");
// TODO 業務邏輯
RedissLockUtil.unlock("ORDER_123456");
3 實現
3.1 二話不說,直接導包
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId >
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
3.2 RedissonProperties rediss配置類
package com.study.redission;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* rediss 配置類 請根據實際情況調整
*/
@Data
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
/**
* Redis伺服器響應超時
*/
private int timeout = 3000;
private String address;
private String password;
private int connectionPoolSize = 64;
private int connectionMinimumIdleSize = 10;
private int slaveConnectionPoolSize = 250;
private int masterConnectionPoolSize = 250;
private String[] sentinelAddresses;
private String masterName;
}
3.3 RedisstionConfig
package com.study.redission;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author: huangwenjun
* @Description:
* @Date: Created in 18:09 2018/6/8
**/
@Configuration
@EnableConfigurationProperties(RedissonProperties.class)
public class RedisstionConfig {
@Autowired
private RedissonProperties redssionProperties;
/**
* 單機模式自動裝配
* @return
*/
@Bean
RedissonClient redissonSingle() {
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redssionProperties.getAddress())
.setTimeout(redssionProperties.getTimeout())
.setConnectionPoolSize(redssionProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize());
if(redssionProperties.getPassword() != null && !"".equals(redssionProperties.getPassword().trim())) {
serverConfig.setPassword(redssionProperties.getPassword());
}
RedissonClient redissonClient = Redisson.create(config);
// 將client注入
RedissLockUtil.setLocker(redissonClient);
return redissonClient;
}
}
3.4 RedissLockUtil 分散式鎖工具類
package com.study.redission;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
/**
* @Author: huangwenjun
* @Description:
* @Date: Created in 18:15 2018/6/8
**/
public class RedissLockUtil {
private static RedissonClient redissonClient;
protected static void setLocker(RedissonClient locker) {
redissonClient = locker;
}
/**
* 加鎖
* @param lockKey
* @return
*/
public static RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
/**
* 釋放鎖
* @param lockKey
*/
public static void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/**
* 釋放鎖
* @param lock
*/
public static void unlock(RLock lock) {
lock.unlock();
}
/**
* 帶超時的鎖
* @param lockKey
* @param timeout 超時時間 單位:秒
*/
public static RLock lock(String lockKey, int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 帶超時的鎖
* @param lockKey
* @param unit 時間單位
* @param timeout 超時時間
*/
public static RLock lock(String lockKey, TimeUnit unit ,int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 嘗試獲取鎖
* @param lockKey
* @param unit 時間單位
* @param waitTime 最多等待時間
* @param leaseTime 上鎖後自動釋放鎖時間
* @return
*/
public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
}
3.5 配置
redisson.address=redis://127.0.0.1:6379
redisson.password=
4 好的程式碼一定要有測試
4.1 測試程式碼
@RequestMapping("lock")
public void lock() {
System.out.println(Thread.currentThread().getName() + ",搶佔鎖");
RedissLockUtil.lock("ORDER_123456");
System.out.println(Thread.currentThread().getName() + ", 獲取鎖");
// TODO 業務邏輯
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
RedissLockUtil.unlock("ORDER_123456");
System.out.println(Thread.currentThread().getName() + ", 釋放鎖");
}
4.2 輸出
http-nio-8080-exec-1,搶佔鎖
http-nio-8080-exec-1, 獲取鎖
http-nio-8080-exec-5,搶佔鎖
http-nio-8080-exec-1, 釋放鎖
http-nio-8080-exec-5, 獲取鎖
http-nio-8080-exec-2,搶佔鎖
http-nio-8080-exec-5, 釋放鎖
http-nio-8080-exec-2, 獲取鎖
http-nio-8080-exec-2, 釋放鎖
5 進階修煉
當然身為高手的你肯定你僅僅滿足與此, 下面安利一下 redisson 的官網
https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
6 結束
搞完收工,如果你喜歡博主的文章的話麻煩點一下關注,如果發現博主文章的錯誤的話 麻煩指出, 謝謝大家。
ref: