SpringBoot2與Redisson 分布式鎖與消息訂閱代碼實(shí)現(xiàn)

一、Redisson 是什么蜀肘?

來(lái)看看百度百科怎么說(shuō)的扮宠。

Redisson是架設(shè)在Redis基礎(chǔ)上的一個(gè)Java駐內(nèi)存數(shù)據(jù)網(wǎng)格(In-Memory Data Grid)坛增。【Redis官方推薦】

Redisson在基于NIO的 Netty 框架上薄腻,充分的利用了Redis鍵值數(shù)據(jù)庫(kù)提供的一系列優(yōu)勢(shì),在Java實(shí)用工具包中常用接口的基礎(chǔ)上罢艾,為使用者提供了一系列具有分布式特性的常用工具類昆婿。使得原本作為協(xié)調(diào)單機(jī)多線程并發(fā)程序的工具包獲得了協(xié)調(diào)分布式多機(jī)多線程并發(fā)系統(tǒng)的能力蜓斧,大大降低了設(shè)計(jì)和研發(fā)大規(guī)模分布式系統(tǒng)的難度睁冬。同時(shí)結(jié)合各富特色的分布式服務(wù)豆拨,更進(jìn)一步簡(jiǎn)化了分布式環(huán)境中程序相互之間的協(xié)作施禾。

然后【Redisson官方WiKi】是這樣說(shuō)的

Redisson 不僅提供了一系列的分布式的Java常用對(duì)象,還提供了許多分布式服務(wù)邮绿。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最簡(jiǎn)單和最便捷的方法船逮。Redisson的宗旨是促進(jìn)使用者對(duì)Redis的關(guān)注分離(Separation of Concern)粤铭,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務(wù)邏輯上。

功能太強(qiáng)大了酱鸭,我都有點(diǎn)不會(huì)用了A堇薄1馐摹!

二捷泞、開(kāi)始使用

1寿谴、導(dǎo)入依賴

 <!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<!-- redisson -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.11.0</version>
</dependency>

2 咏瑟、配置文件配置Redis

Springboot2 中,redis 默認(rèn)用的是lettuce連接池

spring:
  # redis config
  redis:
    host: 127.0.0.1
    password:
    port: 6379
    database: 0
    lettuce:
      pool:
        max-idle: 8
        min-idle: 0
        max-active: 8
        max-wait: -1ms
    timeout: 10000ms

3码泞、配置Redisson

有兩種方法

第一種:程序化配置方法

Config config = new Config();
config.setTransportMode(TransportMode.EPOLL);
config.useClusterServers()
      //可以用"rediss://"來(lái)啟用SSL連接
      .addNodeAddress("redis://127.0.0.1:7181");

第二種:文件方式配置

// json 文件
Config config = Config.fromJSON(new File("config-file.json"));
RedissonClient redisson = Redisson.create(config);

# yaml 文件
Config config = Config.fromYAML(new File("config-file.yaml"));
RedissonClient redisson = Redisson.create(config);

配置文件的具體內(nèi)容,就不多介紹了悯森,官方的聽(tīng)詳細(xì)的,下面給傳送門(mén)
點(diǎn)我?guī)泔w:傳送門(mén)

我個(gè)人比較喜歡程序化方式,全部代碼如下:
package top.lrshuai.redisson.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * redisson 配置祝蝠,下面是單節(jié)點(diǎn)配置:
 * 官方wiki地址:https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F
 *
 */
@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;

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        //單節(jié)點(diǎn)
        config.useSingleServer().setAddress("redis://" + host + ":" + port);
        if(StringUtils.isEmpty(password)){
            config.useSingleServer().setPassword(null);
        }else{
            config.useSingleServer().setPassword(password);
        }
        //添加主從配置
//        config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""});

        // 集群模式配置 setScanInterval()掃描間隔時(shí)間绎狭,單位是毫秒,  //可以用"rediss://"來(lái)啟用SSL連接
//        config.useClusterServers().setScanInterval(2000).addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001").addNodeAddress("redis://127.0.0.1:7002");
        return Redisson.create(config);
    }
}

Bean的方式注入坟岔,然后在想用的地方創(chuàng)建一個(gè)變量即可

4社付、代碼使用Redisson


    @Autowired
    private RedissonClient redissonClient;

三、Redisson 分布式鎖的簡(jiǎn)單使用

什么是分布式鎖鸥咖?分布式鎖有什么作用啼辣?分布式鎖怎么用?

個(gè)人見(jiàn)解:學(xué)過(guò)多線程的應(yīng)該知道党远,共享變量沟娱,如果不加鎖的話腕柜,當(dāng)多個(gè)線程去操作的時(shí)候就有可能導(dǎo)致數(shù)據(jù)的不一致性等問(wèn)題盏缤。所以Java 本身給我們提供了Synchronized 關(guān)鍵字或者 Lock 鎖,都可以處理這種問(wèn)題。這種方式只針對(duì)單臺(tái)服務(wù)器而言的台舱,像雙十一柿赊、618 這種大型活動(dòng),肯定不是只有一臺(tái)服務(wù)器就能帶飛的诡蜓,走都不一定能走蔓罚,別說(shuō)飛了。當(dāng)采用分布式系統(tǒng)多臺(tái)服務(wù)器運(yùn)行的時(shí)候郑象,上面的鎖方案就不靠譜了茬末。所以分布式鎖出來(lái)了。

百度百科
分布式鎖是控制分布式系統(tǒng)之間同步訪問(wèn)共享資源的一種方式辈双。在分布式系統(tǒng)中柜砾,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源证芭,那么訪問(wèn)這些資源的時(shí)候担映,往往需要互斥來(lái)防止彼此干擾來(lái)保證一致性另萤,在這種情況下四敞,便需要使用到分布式鎖忿危。

廢話真多铺厨,代碼擼起

 /**
     * 如果只有一個(gè)線程來(lái)訪問(wèn),那么在rLock.tryLock() 這個(gè)方法就會(huì)阻塞赃磨,等鎖釋放然后再繼續(xù)下面的操作邻辉,
     * 如果是多線程訪問(wèn)值骇,那么在rLock.tryLock() 這個(gè)方法會(huì)直接返回false不阻塞了,繼續(xù)往下執(zhí)行
     * 可以配合Jmeter 來(lái)測(cè)試
     * 更多鎖的demo,可以參考wiki: https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8
     * @return
     */
    @GetMapping("/test")
    public Object test(){
        //獲取鎖實(shí)例
        RLock rLock = redissonClient.getLock(lock);
        boolean isLock =false;
        try {
            // 上鎖
            isLock = rLock.tryLock();
            System.out.println(Thread.currentThread().getName()+"isLock="+isLock);
            if (isLock) {
                System.out.println(Thread.currentThread().getName()+"我搶到鎖了吱瘩,開(kāi)心使碾,先休息10秒先");
                Thread.sleep(10 *1000);
                // todo service 業(yè)務(wù)代碼
            }else {
                System.out.println(Thread.currentThread().getName()+"被人鎖了皱卓,郁悶下次再來(lái)");
                return FAILED;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(isLock){
                System.out.println(Thread.currentThread().getName()+"不玩了,開(kāi)鎖了2看D戎!");
                // 解鎖
                rLock.unlock();
            }
        }
        return SUCCESS;
    }
測(cè)試圖片

Redisson 提供的鎖有那么幾個(gè)兄朋,按需使用

  • 可重入鎖
  • 公平鎖
  • 聯(lián)鎖
  • 紅鎖
  • 讀寫(xiě)鎖
  • 閉鎖
    各個(gè)鎖的使用Wiki 都有介紹掐禁,我只是粗略的開(kāi)個(gè)頭。

四颅和、Redisson消息的發(fā)布訂閱

這個(gè)簡(jiǎn)單傅事,一個(gè)發(fā)布,一個(gè)接受峡扩,簡(jiǎn)單代碼如下:

//發(fā)布
public long publish(MyObjectDTO myObjectDTO){
    RTopic rTopic = redissonClient.getTopic(Consts.TopicName);
    return  rTopic.publish(myObjectDTO);
}

// 訂閱
public void subscribe(){
        RTopic rTopic = redissonClient.getTopic(Consts.TopicName);
        rTopic.addListener(MyObjectDTO.class, new MessageListener<MyObjectDTO>() {
            // 接受訂閱的消息
            @Override
            public void onMessage(CharSequence charSequence, MyObjectDTO myObjectDTO) {
                log.info("接受到消息主題={}蹭越,內(nèi)容={}",charSequence,myObjectDTO);
                System.out.println("傳輸?shù)臄?shù)據(jù)為="+myObjectDTO);
            }
        });
    }

MyObjectDTO 就是發(fā)布的消息體,隨意一個(gè)對(duì)象就行,命名有點(diǎn)LOW

示例圖

完整代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末忿项,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脱柱,更是在濱河造成了極大的恐慌掸茅,老刑警劉巖景馁,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件透葛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡靶草,警方通過(guò)查閱死者的電腦和手機(jī)浩蓉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)讯泣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)昨稼,“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了烤芦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)滔韵,這世上最難降的妖魔是什么贱鼻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任肝谭,我火速辦了婚禮镀首,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘觅捆。我一直安慰自己庸论,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布锋边。 她就那樣靜靜地躺著掐场,像睡著了一般萍膛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音借杰,去河邊找鬼洋措。 笑死滓鸠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梁丘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沥邻!你這毒婦竟也來(lái)了埃跷?” 一聲冷哼從身側(cè)響起弥雹,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窗宦,失蹤者是張志新(化名)和其女友劉穎订讼,沒(méi)想到半個(gè)月后寄纵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體亦歉,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞭盟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瑰剃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齿诉。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粤剧,到底是詐尸還是另有隱情歇竟,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布抵恋,位于F島的核電站焕议,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弧关。R本人自食惡果不足惜盅安,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望世囊。 院中可真熱鬧别瞭,春花似錦、人聲如沸株憾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗤瞎。三九已至墙歪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贝奇,已是汗流浹背虹菲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弃秆,地道東北人届惋。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像菠赚,于是被迫代替她去往敵國(guó)和親脑豹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348