溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringCloud之Config配置中心與Redis分布式鎖介紹

發(fā)布時(shí)間:2023-11-20 14:01:32 來(lái)源:億速云 閱讀:128 作者:栢白 欄目:開(kāi)發(fā)技術(shù)

本篇文章和大家了解一下SpringCloud之Config配置中心與Redis分布式鎖介紹。有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)大家有所幫助。

1.服務(wù)配置中心

1.1 服務(wù)配置中心介紹

首先我們來(lái)看一下,微服務(wù)架構(gòu)下關(guān)于配置文件的一些問(wèn)題:
1.配置文件相對(duì)分散。在一個(gè)微服務(wù)架構(gòu)下,配置文件會(huì)隨著微服務(wù)的增多變的越來(lái)越多,而且分散在各個(gè)微服務(wù)中,不好統(tǒng)─配置和管理。
⒉.配置文件無(wú)法區(qū)分環(huán)境。微服務(wù)項(xiàng)目可能會(huì)有多個(gè)環(huán)境,例如︰測(cè)試環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境。每一個(gè)環(huán)境所使用的配置理論上都是不同的,一旦需要修改,就需要我們?nèi)ジ鱾€(gè)微服務(wù)下手動(dòng)維護(hù),這比較困難。
3.配置文件無(wú)法實(shí)時(shí)更新。我們修改了配置文件之后,必須重新啟動(dòng)微服務(wù)才能使配置生效,這對(duì)一個(gè)正在運(yùn)行的項(xiàng)目來(lái)說(shuō)是非常不友好的。

基于上面這些問(wèn)題,我們就需要配置中心的加入來(lái)解決這些問(wèn)題。
配置中心的思路是:
1.首先把項(xiàng)目中各種配置全部都放到一個(gè)集中的地方進(jìn)行統(tǒng)—管理,并提供—套標(biāo)準(zhǔn)的接口。
2.當(dāng)各個(gè)服務(wù)需要獲取配置的時(shí)候,就來(lái)配置中心的接口拉取自己的配置。
3..當(dāng)配置中心中的各種參數(shù)有更新的時(shí)候,也能通知到各個(gè)服務(wù)實(shí)時(shí)的過(guò)來(lái)同步最新的信息,使之動(dòng)態(tài)更新

當(dāng)加入了服務(wù)配置中心之后,我們的系統(tǒng)架構(gòu)圖會(huì)變成下面這樣:

SpringCloud之Config配置中心與Redis分布式鎖介紹

1.2 Nacos Config 實(shí)踐

使用nacos作為配置中心,其實(shí)就是將nacos當(dāng)做一個(gè)服務(wù)端,將各個(gè)微服務(wù)看成是客戶端,我們將各個(gè)微服務(wù)的配置文件統(tǒng)一存放在nacos上,然后各個(gè)微服務(wù)從nacos上拉取配置即可。

1.2.1 Nacos config入門(mén)案例

導(dǎo)入依賴

       <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

在微服務(wù)中添加nacos config的配置,不能使用原來(lái)的application.yml作為配置文件,而是新建一個(gè)bootstrap.yml作為配置文件。

配置文件優(yōu)先級(jí)從高到低為:

bootstrap.properties>bootstrap.yml>application.properties>application.yml

這里舉例為訂單微服務(wù),首先新建個(gè)bootstrap.yml文件,然后配置如下:

spring:
  application:
    name: provider
  profiles:
    active: dev #環(huán)境標(biāo)識(shí)
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml #配置文件格式
      discovery:
        cluster-name: BJ
    sentinel:
      transport:
        dashboard: localhost:8080

然后在nacos配置文件中配置Data ID為bootstrap中配置訂單微服務(wù)名+環(huán)境標(biāo)識(shí)+配置文件格式。如下圖;

SpringCloud之Config配置中心與Redis分布式鎖介紹

 1.2.2  Nacos 配置動(dòng)態(tài)刷新

實(shí)現(xiàn)在配置中心修改配置文件內(nèi)容后,程序內(nèi)部引用可以自動(dòng)刷新,我們可以在自己創(chuàng)建的DataId配置文件中,更改項(xiàng):

config: 
 
appName: product

硬編碼方式

 @GetMapping("/test")
    public String test(){
        String property = configurableApplicationContext.getEnvironment().getProperty("config.appName");
        return property;
    }

注解方式

@RestController
@RefreshScope  /* 只需要在需要?jiǎng)討B(tài)讀取配置的類(lèi)上添加此注解就可以 */
 
public class UserController {
 
    @Value("${config.appName}")
    private String appName;
 
    @GetMapping("/test")
    public String test(){
        return appName;
    }
 
}
1.2.3 配置共享

當(dāng)配置越來(lái)越多的時(shí)候,我們就發(fā)現(xiàn)有很多配置是重復(fù)的,這時(shí)候就考慮可不可以將公共配置文件提取出來(lái),然后實(shí)現(xiàn)共享。共享存在兩種場(chǎng)景:同一微服務(wù),不同場(chǎng)景(namespace)下共享;不同微服務(wù)之間共享。

 同一微服務(wù),不同場(chǎng)景下共享配置

比如上面的訂單微服務(wù),開(kāi)發(fā)環(huán)境的配置文件為provider-dev.yaml,測(cè)試環(huán)境的配置文件為provider-test.yaml,同一微服務(wù)在不同場(chǎng)景下共享可以配置provider.yaml文件。

 不同微服務(wù)之間共享共享配置

在nacos中新建all-service.yml文件作為共享配置,然后引入配置代碼如下:

spring:
  application:
    name: provider
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
        shared-dataids: allservice.yaml #配置要引入的配置
        refreshable-dataids: allservice.yaml #配置要實(shí)現(xiàn)動(dòng)態(tài)配置刷新的配置
      discovery:
        cluster-name: BJ
    sentinel:
      transport:
        dashboard: localhost:8080
1.2.4 nacos 幾個(gè)概念

命名空間(Namespace)
命名空間可用于進(jìn)行不同環(huán)境的配置隔離。一般一個(gè)環(huán)境劃分到一個(gè)命名空間
配置分組(Group)
配置分組用于將不同的服務(wù)可以歸類(lèi)到同一分組。一般將一個(gè)項(xiàng)目的配置分到一組
配置集(Data ID)
在系統(tǒng)中,一個(gè)配置文件通常就是一個(gè)配置集。一般微服務(wù)的配置就是一個(gè)配置集
 

SpringCloud之Config配置中心與Redis分布式鎖介紹

2.分布式鎖

2.1 分布式鎖介紹

分布式鎖:滿足分布式系統(tǒng)或集群模式下多進(jìn)程可見(jiàn)并且互斥的鎖。

在單體的應(yīng)用開(kāi)發(fā)場(chǎng)景中,在多線程的環(huán)境下,涉及并發(fā)同步的時(shí)候,為了保證一個(gè)代碼塊在同一時(shí)間只能由一個(gè)線程訪問(wèn),我們一般可以使用synchronized語(yǔ)法和ReetrantLock去保證,這實(shí)際上是本地鎖的方式。也就是說(shuō),在同一個(gè)JVM內(nèi)部,大家往往采用synchronized或者Lock的方式來(lái)解決多線程間的安全問(wèn)題。但在分布式集群工作的開(kāi)發(fā)場(chǎng)景中,在JVM之間,那么就需要一種更加高級(jí)的鎖機(jī)制,來(lái)處理種跨JVM進(jìn)程之間的線程安全問(wèn)題.

總之,對(duì)于分布式場(chǎng)景,我們可以使用分布式鎖,它是控制分布式系統(tǒng)之間互斥訪問(wèn)共享資源的一種方式。比如說(shuō)在一個(gè)分布式系統(tǒng)中,多臺(tái)機(jī)器上部署了多個(gè)服務(wù),當(dāng)客戶端一個(gè)用戶發(fā)起一個(gè)數(shù)據(jù)插入請(qǐng)求時(shí),如果沒(méi)有分布式鎖機(jī)制保證,那么那多臺(tái)機(jī)器上的多個(gè)服務(wù)可能進(jìn)行并發(fā)插入操作,導(dǎo)致數(shù)據(jù)重復(fù)插入,對(duì)于某些不允許有多余數(shù)據(jù)的業(yè)務(wù)來(lái)說(shuō),這就會(huì)造成問(wèn)題。而分布式鎖機(jī)制就是為了解決類(lèi)似這類(lèi)問(wèn)題,保證多個(gè)服務(wù)之間互斥的訪問(wèn)共享資源,如果一個(gè)服務(wù)搶占了分布式鎖,其他服務(wù)沒(méi)獲取到鎖,就不進(jìn)行后續(xù)操作。如下圖:

SpringCloud之Config配置中心與Redis分布式鎖介紹

分布式鎖要具有一下特征:

  • 互斥性。在任意時(shí)刻,只有一個(gè)客戶端能持有鎖。

  • 不會(huì)發(fā)生死鎖。即使有一個(gè)客戶端在持有鎖的期間崩潰而沒(méi)有主動(dòng)解鎖,也能保證后續(xù)其他客戶端能加鎖。

  • 具有容錯(cuò)性。只要大部分的 Redis 節(jié)點(diǎn)正常運(yùn)行,客戶端就可以加鎖和解鎖。

  • 解鈴還須系鈴人。加鎖和解鎖必須是同一個(gè)客戶端,客戶端自己不能把別人加的鎖給解了。

SpringCloud之Config配置中心與Redis分布式鎖介紹

分布式鎖的核心是實(shí)現(xiàn)多進(jìn)程之間互斥,而滿足這一點(diǎn)的方式有很多,常見(jiàn)的有三種:

SpringCloud之Config配置中心與Redis分布式鎖介紹

2.2 Redisson 

Redisson是一個(gè)在Redis的基礎(chǔ)上實(shí)現(xiàn)的Java駐內(nèi)存數(shù)據(jù)網(wǎng)格(In-Memory Data Grid)。它不僅提供了一系列的分布式的Java常用對(duì)象,還提供了許多分布式服務(wù),其中就包含了各種分布式鎖的實(shí)現(xiàn)。

假如我們?cè)谖⒎?wù)架構(gòu)中,有個(gè)訂單秒殺服務(wù),要求同一個(gè)優(yōu)惠券,一個(gè)用戶只能下一單。在單機(jī)架構(gòu)中,我們使用synchronized或者Lock的方式就可以解決這個(gè)問(wèn)題,將查詢數(shù)據(jù)庫(kù)是否下過(guò)單和下單扣減庫(kù)存過(guò)程鎖在一塊,只允許獲得鎖的一個(gè)線程進(jìn)行訪問(wèn)。如果不加鎖,假如高并發(fā)場(chǎng)景下,一百個(gè)線程同時(shí)訪問(wèn)并且都是同一個(gè)用戶,然后就會(huì)出現(xiàn)多個(gè)線程先進(jìn)行查詢操作,如果數(shù)據(jù)庫(kù)中沒(méi)有該訂單信息,然后這多個(gè)線程就會(huì)都符合要求進(jìn)行下單扣減庫(kù)存產(chǎn)生多個(gè)訂單,就會(huì)違背一個(gè)用戶只能下一單的情況。而在分布式中,因?yàn)槎鄠€(gè)服務(wù)都是以集群形式的存在存在多個(gè)jvm實(shí)例,synchronized或者Lock的方式只是針對(duì)的同一個(gè)JVM內(nèi)部,這就需要分布式鎖。這里使用Redission進(jìn)行模擬,模擬在微服務(wù)集群高并發(fā)場(chǎng)景下多個(gè)用戶線程下下單同一訂單扣減庫(kù)存情況。

2.2.1 Redisson 實(shí)踐

導(dǎo)入依賴

      <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.19.0</version>
        </dependency>

代碼如下:

本代碼模擬根據(jù)訂單id查詢到訂單信息,然后根據(jù)訂單信息中的goodsId傳遞到商品微服務(wù),進(jìn)行對(duì)應(yīng)商品的庫(kù)存減一,然后返回修改后的商品信息 存儲(chǔ)到訂單信息對(duì)應(yīng)商品Goods屬性上。加分布式鎖是保證在同一集群中不同微服務(wù)進(jìn)程中的這個(gè)方法只能由獲得鎖的線程進(jìn)行處理業(yè)務(wù),由于是代碼模擬,所以在設(shè)計(jì)代碼的時(shí)候相對(duì)隨意。

    @GetMapping("/order/pay/{id}")
    public Orders1 pay(@PathVariable("id") Long id){
        RLock lock = redissonClient.getLock("lockorder" + id);
        boolean b = lock.tryLock();
        if(!b) {
            return null;
        }
        try {
            Orders1 orders1 = orders1Mapper.selectById(id);
            Goods goods = feign.goodsservice(orders1.getGoodsId());
            orders1.setGoods(goods);
            return orders1;
        }finally {
            lock.unlock();
        }
    }

debug驗(yàn)證結(jié)果如下:

下面訂單微服務(wù)集群為8080端口和9202端口,先訪問(wèn)8080端口,再訪問(wèn)9202端口,在debug環(huán)境下驗(yàn)證了我們的猜想。

SpringCloud之Config配置中心與Redis分布式鎖介紹

SpringCloud之Config配置中心與Redis分布式鎖介紹

 2.2.2 Redisson 原理

此章節(jié)引用網(wǎng)上相關(guān)描述

Redisson 這個(gè)框架對(duì)Redis分布式鎖的實(shí)現(xiàn)原理圖如下:

SpringCloud之Config配置中心與Redis分布式鎖介紹

 1.獲取鎖
一個(gè)Redission客戶端1要加鎖,它首先會(huì)根據(jù)hash節(jié)點(diǎn)選擇一臺(tái)機(jī)器,緊接著就會(huì)發(fā)送一段lua腳本到redis上,比如加鎖的那個(gè)鎖key就是”mylock”,并且設(shè)置的時(shí)間是30秒,30秒后mylock鎖就會(huì)被釋放。
2.鎖互斥機(jī)制
如果這個(gè)時(shí)候Redission客戶端2來(lái)加鎖,它也會(huì)會(huì)根據(jù)hash節(jié)點(diǎn)選擇一臺(tái)機(jī)器,然后執(zhí)行了同樣的一段lua腳本。
它首先回來(lái)判斷《mylock》這個(gè)鎖存在嗎?如果存在則Redission客戶端2會(huì)獲得一個(gè)數(shù)字,這個(gè)數(shù)字就是mylock這個(gè)鎖的剩余生存時(shí)間。
此時(shí)Redission客戶端2就會(huì)進(jìn)入到一個(gè)while循環(huán),就是CAS不停的自旋嘗試加鎖,知道成功為止。
3.看門(mén)狗機(jī)制
如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redisson節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí),這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)。
為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門(mén)狗,它的作用是在Redisson實(shí)例被關(guān)閉前,不斷的延長(zhǎng)鎖的有效期。線程A拿到鎖需要處理2秒,但是鎖的超時(shí)時(shí)間只有1秒,也就是說(shuō)鎖超時(shí)的時(shí)候,業(yè)務(wù)還沒(méi)處理完。這時(shí)候線程B就進(jìn)來(lái)了又拿到鎖,導(dǎo)致加鎖跟解鎖的時(shí)候并不是同一線程??撮T(mén)狗的作用就是當(dāng)遇到這種情況的時(shí)候,看門(mén)狗會(huì)定時(shí)去查看一下這個(gè)線程A是否還在執(zhí)行任務(wù),如果還在執(zhí)行則給他繼續(xù)延長(zhǎng)時(shí)間。

4.可重入加鎖機(jī)制
我們知道ReentrantLock是可重入鎖,它的特點(diǎn)就是:同一個(gè)線程可以重復(fù)拿到同一個(gè)資源的鎖,Redisson也能很好的滿足這點(diǎn)。
Redisson客戶端1獲得mylock鎖時(shí),里面會(huì)有一個(gè)hash結(jié)構(gòu)的數(shù)據(jù),如下圖所示:

SpringCloud之Config配置中心與Redis分布式鎖介紹

SpringCloud之Config配置中心與Redis分布式鎖介紹

上面這圖的意思就是可重入鎖的機(jī)制,它最大的優(yōu)點(diǎn)就是相同線程不需要在等待鎖,而是可以直接進(jìn)行相應(yīng)操作。

5.釋放鎖機(jī)制
如果發(fā)現(xiàn)加鎖次數(shù)變?yōu)?了,那么說(shuō)明這個(gè)Redisson客戶端1不再持有鎖了,Redisson客戶端2就可以加鎖了。

以上就是SpringCloud之Config配置中心與Redis分布式鎖介紹的簡(jiǎn)略介紹,當(dāng)然詳細(xì)使用上面的不同還得要大家自己使用過(guò)才領(lǐng)會(huì)。如果想了解更多,歡迎關(guān)注億速云行業(yè)資訊頻道哦!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI