集成redisson分佈式鎖

一、redisson是什麼

      Redisson是架設在redis基礎上的一個Java主內存網絡,並且是redis官方推薦的。Redisson在基於NIO的Netty框架上,充分利用了redis鍵值數據庫提供的一系列優勢,在Java實用工具包中常用接口的基礎上,爲使用者提供了一系列具有分佈式特性的常用工具類。這樣就使得原本作爲協調單機多線程併發程序的工具包獲得了協調分佈式多機多線程併發系統的能力,大大降低了設計和壓法大規模分佈式系統 的難度。同時結合豐富的分佈式服務,更進一步簡化了分佈式環境中程序相互之間的協作。
      我們下面介紹的分佈式鎖,只是其中的一個應用。

二、爲什麼要用redisson分佈式鎖

(一)爲什麼用鎖

      鎖一般用在併發情況下,我們用搶紅包這個場景來分析,假設有100個人搶10個紅包,假如現在還剩1個紅包,但是有10個人都來搶這之後一個包,因爲是併發的所有這10個人搶的時候都判斷還剩一個包,但是我們的紅包只剩下一個10個人都搶到了,這就會導致我們發了100個紅包,但是一共搶了110個紅包。爲了解決這個問題我們就需要在真正搶紅包的代碼前加鎖,這樣就算10個人都進來了,但是第一個人加鎖之後剩下的九個月都會直接返回,不會走搶紅包的代碼,這樣就可以避免超發問題。

(二)爲什麼用分佈式鎖

      如果我們的程序採用分佈式部署的話,我們必須保證我們的鎖對分配到不同服務器上的請求都是起作用的。
      之前的方式是自己寫的加鎖解鎖方法,是根據時間來判斷時候可以解鎖,這樣存在的問題就是解鎖不嚴謹,而且必須保證每臺服務器的時間都是一致的,存在很多漏洞。

(三)爲什麼用redisson分佈式鎖

      實現中使用了lua腳本,保證原子性執行,而且redisson比較成熟全面。可以更好地解決我們的問題。因爲redisson不光是針對於分佈式鎖,還提供了很多客戶端操作redis的方法,所以會依賴一些其它的框架,比如netty,如果只是簡單的使用鎖也可以自己去實現。

三、redisson分佈式鎖怎麼用

(一)引入相關jar包

<!--Redisson分佈式鎖-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.6.5</version>
</dependency>

(二)編寫配置文件

1、一般spring項目

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:redisson="http://redisson.org/schema/redisson"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://redisson.org/schema/redisson
       http://redisson.org/schema/redisson/redisson.xsd
">
    <!--Redis實現分佈式鎖 -->
    <redisson:client>
        <redisson:single-server address="redis://192.168.22.64:6379"/>
    </redisson:client>

</beans>

2、springboot項目

/**
 * redisson分佈式鎖配置文件
 * @author
 * @Date 
 */
@Configuration
public class RedissonConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.database}")
    private int database;

    @Bean
    public RedissonClient getRedisson(){

        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port);
        //一共有三種模式:單擊、哨兵、集羣,根據實際需要配置即可
        return Redisson.create(config);
    }
}

(三)加鎖解鎖代碼

1、加鎖

RLock rlock = redissonClient.getLock("redisson:lock:redPacketID" + normalRedPacket.get(i).getRedPacketId());

“redisson:lock1:redPacketID" + normalRedPacket.get(i).getRedPacketId()”是加鎖設置的key值,根據自己的需要設置即可,可以將同一批次的id設置爲key鍵,如果每個人的key鍵都不一樣,那麼加鎖就沒有意義了。

2、解鎖

這裏將解鎖代碼放在finally中將保證即使程序出現異常,解鎖代碼也會執行,當然我們也可以在我們的業務邏輯中也加上解鎖,但是在finally加解鎖代碼以及給鎖設置失效時間都可以在一定程度上避免死鎖的發生,來讓我們的程序更加健壯。

try {
   //業務邏輯
} finally {
    //解鎖
    rlock.unlock();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章