主頁 > 軟體設計 > Redis分布式鎖的五大演進攻略

Redis分布式鎖的五大演進攻略

2023-01-21 07:35:00 軟體設計

 

本文我們來探討下如何引入分布式鎖解決本地鎖的問題,本篇所有代碼和業務基于我的開源專案 PassJava,

 

本篇主要內容如下:

 

圖片

 

一、本地鎖的問題

 

首先我們來回顧下本地鎖的問題:

 

目前題目微服務被拆分成了四個微服務,前端請求進來時,會被轉發到不同的微服務,假如前端接收了 10 W 個請求,每個微服務接收 2.5 W 個請求,假如快取失效了,每個微服務在訪問資料庫時加鎖,通過鎖(synchronzied 或 lock)來鎖住自己的執行緒資源,從而防止快取擊穿

 

這是一種本地加鎖的方式,在分布式情況下會帶來資料不一致的問題:比如服務 A 獲取資料后,更新快取 key =100,服務 B 不受服務 A 的鎖限制,并發去更新快取 key = 99,最后的結果可能是 99 或 100,但這是一種未知的狀態,與期望結果不一致,流程圖如下所示:

 

圖片

 

二、什么是分布式鎖

 

基于上面本地鎖的問題,我們需要一種支持分布式集群環境下的鎖:查詢 DB 時,只有一個執行緒能訪問,其他執行緒都需要等待第一個執行緒釋放鎖資源后,才能繼續執行,

 

生活中的案例:可以把鎖看成房門外的一把鎖,所有并發執行緒比作人,他們都想進入房間,房間內只能有一個人進入,當有人進入后,將門反鎖,其他人必須等待,直到進去的人出來,

 

圖片

 

我們來看下分布式鎖的基本原理,如下圖所示:

 

圖片

 

我們來分析下上圖的分布式鎖:

 

1)前端將 10W 的高并發請求轉發給四個題目微服務,

 

2)每個微服務處理 2.5 W 個請求,

 

3)每個處理請求的執行緒在執行業務之前,需要先搶占鎖,可以理解為“占坑”,

 

4)獲取到鎖的執行緒在執行完業務后,釋放鎖,可以理解為“釋放坑位”,

 

5)未獲取到的執行緒需要等待鎖釋放,

 

6)釋放鎖后,其他執行緒搶占鎖,

 

7)重復執行步驟 4、5、6,

 

大白話解釋:所有請求的執行緒都去同一個地方“占坑”,如果有坑位,就執行業務邏輯,沒有坑位,就需要其他執行緒釋放“坑位”,這個坑位是所有執行緒可見的,可以把這個坑位放到 Redis 快取或者資料庫,這篇講的就是如何用 Redis 做“分布式坑位”,

 

三、Redis 的 SETNX

 

Redis 作為一個公共可訪問的地方,正好可以作為“占坑”的地方,

 

用 Redis 實作分布式鎖的幾種方案,我們都是用 SETNX 命令(設定 key 等于某 value),只是高階方案傳的引數個數不一樣,以及考慮了例外情況,

 

我們來看下這個命令,SETNXset If not exist的簡寫,意思就是當 key 不存在時,設定 key 的值,存在時,什么都不做,

 

在 Redis 命令列中是這樣執行的:

set <key> <value> NX

 

我們可以進到 redis 容器中來試下 SETNX 命令,

 

先進入容器:

docker exec -it <容器 id> redis-cli

 

然后執行 SETNX 命令:將 wukong 這個 key 對應的 value 設定成 1111

set wukong 1111 NX

 

回傳 OK,表示設定成功,重復執行該命令,回傳 nil表示設定失敗,

 

圖片

 

四、青銅方案

 

我們先用 Redis 的 SETNX 命令來實作最簡單的分布式鎖,

 

1、青銅原理

 

我們來看下流程圖:

 

圖片

 

  • 多個并發執行緒都去 Redis 中申請鎖,也就是執行 setnx 命令,假設執行緒 A 執行成功,說明當前執行緒 A 獲得了,

 

  • 其他執行緒執行 setnx 命令都會是失敗的,所以需要等待執行緒 A 釋放鎖,

 

  • 執行緒 A 執行完自己的業務后,洗掉鎖,

 

  • 其他執行緒繼續搶占鎖,也就是執行 setnx 命令,因為執行緒 A 已經洗掉了鎖,所以又有其他執行緒可以搶占到鎖了,

 

代碼示例如下,Java 中 setnx 命令對應的代碼為 setIfAbsent

 

setIfAbsent 方法的第一個引數代表 key,第二個引數代表值,

// 1.先搶占鎖
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "123");
if(lock) {
  // 2.搶占成功,執行業務
  List<TypeEntity> typeEntityListFromDb = getDataFromDB();
  // 3.解鎖
  redisTemplate.delete("lock");
  return typeEntityListFromDb;
} else {
  // 4.休眠一段時間
  sleep(100);
  // 5.搶占失敗,等待鎖釋放
  return getTypeEntityListByRedisDistributedLock();
}

 

一個小問題:那為什么需要休眠一段時間?

 

因為該程式存在遞回呼叫,可能會導致堆疊空間溢位,

 

2、青銅方案的缺陷

 

青銅之所以叫青銅,是因為它是最初級的,肯定會帶來很多問題,

 

設想一種家庭場景:晚上小空一個人開鎖進入了房間,打開了電燈,然后突然斷電了,小空想開門出去,但是找不到門鎖位置,那小明就進不去了,外面的人也進不來,

 

圖片

 

從技術的角度看:setnx 占鎖成功,業務代碼出現例外或者服務器宕機,沒有執行洗掉鎖的邏輯,就造成了死鎖,

 

那如何規避這個風險呢?

 

設定鎖的自動過期時間,過一段時間后,自動洗掉鎖,這樣其他執行緒就能獲取到鎖了,

 

五、白銀方案

 

1、生活中的例子

 

上面提到的青銅方案會有死鎖問題,那我們就用上面的規避風險的方案來設計下,也就是我們的白銀方案,

 

圖片

 

還是生活中的例子:小空開鎖成功后,給這款智能鎖設定了一個沙漏倒計時,沙漏完后,門鎖自動打開,即使房間突然斷電,過一段時間后,鎖會自動打開,其他人就可以進來了,

 

2、技術原理圖

 

和青銅方案不同的地方在于,在占鎖成功后,設定鎖的過期時間,這兩步是分步執行的,如下圖所示:

 

圖片

 

3、示例代碼

 

清理 redis key 的代碼如下:

// 在 10s 以后,自動清理 lock
redisTemplate.expire("lock", 10, TimeUnit.SECONDS);

完整代碼如下:


// 1.先搶占鎖
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "123");
if(lock) {
    // 2.在 10s 以后,自動清理 lock
    redisTemplate.expire("lock", 10, TimeUnit.SECONDS);
    // 3.搶占成功,執行業務
    List<TypeEntity> typeEntityListFromDb = getDataFromDB();
    // 4.解鎖
    redisTemplate.delete("lock");
    return typeEntityListFromDb;
}

 

4、白銀方案的缺陷

 

白銀方案看似解決了執行緒例外或服務器宕機造成的鎖未釋放的問題,但還是存在其他問題:

 

因為占鎖和設定過期時間是分兩步執行的,所以如果在這兩步之間發生了例外,則鎖的過期時間根本就沒有設定成功,

 

所以和青銅方案有一樣的問題:鎖永遠不能過期,

 

六、黃金方案

 

1、原子指令

 

上面的白銀方案中,占鎖和設定鎖過期時間是分步兩步執行的,這個時候,我們可以聯想到什么:事務的原子性(Atom),

 

原子性:多條命令要么都成功執行,要么都不執行,

 

將兩步放在一步中執行:占鎖+設定鎖過期時間,

 

Redis 正好支持這種操作:


# 設定某個 key 的值并設定多少毫秒或秒 過期,
set <key> <value> PX <多少毫秒> NX
或
set <key> <value> EX <多少秒> NX

 

然后可以通過如下命令查看 key 的變化,

ttl <key>

 

下面演示下如何設定 key 并設定過期時間,注意:執行命令之前需要先洗掉 key,可以通過客戶端或命令洗掉,


# 設定 key=wukong,value=https://www.cnblogs.com/88223100/p/1111,過期時間=5000ms
set wukong 1111 PX 5000 NX
# 查看 key 的狀態
ttl wukong

 

執行結果如下圖所示:每運行一次 ttl 命令,就可以看到 wukong 的過期時間就會減少,最后會變為 -2(已過期),

 

圖片

 

2、技術原理圖

 

黃金方案和白銀方案的不同之處:獲取鎖的時候,也需要設定鎖的過期時間,這是一個原子操作,要么都成功執行,要么都不執行,如下圖所示:

 

圖片

 

3、示例代碼

 

設定 lock 的值等于 123,過期時間為 10 秒,如果 10 秒 以后,lock 還存在,則清理 lock,

setIfAbsent("lock", "123", 10, TimeUnit.SECONDS);

 

4、黃金方案的缺陷

 

我們還是舉生活中的例子來看下黃金方案的缺陷,

 

1)用戶 A 搶占鎖

 

圖片

 

  • 用戶 A 先搶占到了鎖,并設定了這個鎖 10 秒以后自動開鎖,鎖的編號為 123,

 

  • 10 秒以后,A 還在執行任務,此時鎖被自動打開了,

 

2)用戶 B 搶占鎖

 

圖片

 

  • 用戶 B 看到房間的鎖打開了,于是搶占到了鎖,設定鎖的編號為 123,并設定了過期時間 10 秒,

 

  • 因房間內只允許一個用戶執行任務,所以用戶 A 和 用戶 B 執行任務產生了沖突,

 

  • 用戶 A 在 15 s 后,完成了任務,此時 用戶 B 還在執行任務,

 

  • 用戶 A 主動打開了編號為 123的鎖,

 

  • 用戶 B 還在執行任務,發現鎖已經被打開了,

 

  • 用戶 B 非常生氣:我還沒執行完任務呢,鎖怎么開了?

 

3)用戶 C 搶占鎖

 

圖片

 

  • 用戶 B 的鎖被 A 主動打開后,A 離開房間,B 還在執行任務,

 

  • 用戶 C 搶占到鎖,C 開始執行任務,

 

  • 因房間內只允許一個用戶執行任務,所以用戶 B 和 用戶 C 執行任務產生了沖突,

 

從上面的案例中我們可以知道,因為用戶 A 處理任務所需要的時間大于鎖自動清理(開鎖)的時間,所以在自動開鎖后,又有其他用戶搶占到了鎖,當用戶 A 完成任務后,會把其他用戶搶占到的鎖給主動打開,

 

這里為什么會打開別人的鎖?因為鎖的編號都叫做 “123”,用戶 A 只認鎖編號,看見編號為 “123”的鎖就開,結果把用戶 B 的鎖打開了,此時用戶 B 還未執行完任務,當然生氣了,

 

七、鉑金方案

 

1、生活中的例子

 

上面的黃金方案的缺陷也很好解決,給每個鎖設定不同的編號不就好了~

 

如下圖所示,B 搶占的鎖是藍色的,和 A 搶占到綠色鎖不一樣,這樣就不會被 A 打開了,

 

做了個動圖,方便理解:

 

圖片

動圖演示

 

靜態圖更高清,可以看看:

 

圖片

 

2、技術原理圖

 

與黃金方案的不同之處:

 

  • 設定鎖的過期時間時,還需要設定唯一編號,

 

  • 主動洗掉鎖的時候,需要判斷鎖的編號是否和設定的一致,如果一致,則認為是自己設定的鎖,可以進行主動洗掉,

 

圖片

 

3、代碼示例

 

// 1.生成唯一 id
String uuid = UUID.randomUUID().toString();
// 2. 搶占鎖
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);
if(lock) {
    System.out.println("搶占成功:" + uuid);
    // 3.搶占成功,執行業務
    List<TypeEntity> typeEntityListFromDb = getDataFromDB();
    // 4.獲取當前鎖的值
    String lockValue = https://www.cnblogs.com/88223100/p/redisTemplate.opsForValue().get("lock");
    // 5.如果鎖的值和設定的值相等,則清理自己的鎖
    if(uuid.equals(lockValue)) {
        System.out.println("清理鎖:" + lockValue);
        redisTemplate.delete("lock");
    }
    return typeEntityListFromDb;
} else {
    System.out.println("搶占失敗,等待鎖釋放");
    // 4.休眠一段時間
    sleep(100);
    // 5.搶占失敗,等待鎖釋放
    return getTypeEntityListByRedisDistributedLock();
}

 

  • 生成隨機唯一 id,給鎖加上唯一值,

 

  • 搶占鎖,并設定過期時間為 10 s,且鎖具有隨機唯一 id,

 

  • 搶占成功,執行業務,

 

  • 執行完業務后,獲取當前鎖的值,

 

  • 如果鎖的值和設定的值相等,則清理自己的鎖,

 

4、鉑金方案的缺陷

 

上面的方案看似很完美,但還是存在問題:第 4 步和第 5 步并不是原子性的,

 

圖片

 

  • 時刻:0s,執行緒 A 搶占到了鎖,

 

  • 時刻:9.5s,執行緒 A 向 Redis 查詢當前 key 的值,

 

  • 時刻:10s,鎖自動過期,

 

  • 時刻:11s,執行緒 B 搶占到鎖,

 

  • 時刻:12s,執行緒 A 在查詢途中耗時長,終于拿多鎖的值,

 

  • 時刻:13s,執行緒 A 還是拿自己設定的鎖的值和回傳的值進行比較,值是相等的,清理鎖,但是這個鎖其實是執行緒 B 搶占的鎖,

 

那如何規避這個風險呢?鉆石方案登場,

 

八、鉆石方案

 

上面的執行緒 A 查詢鎖和洗掉鎖的邏輯不是原子性的,所以將查詢鎖和洗掉鎖這兩步作為原子指令操作就可以了,

 

1、技術原理圖

 

如下圖所示,紅色圈出來的部分是鉆石方案的不同之處,用腳本進行洗掉,達到原子操作,

 

圖片

 

2、代碼示例

 

那如何用腳本進行洗掉呢?

 

我們先來看一下這段 Redis 專屬腳本:


if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end

 

這段腳本和鉑金方案的獲取key,洗掉key的方式很像,先獲取 KEYS[1] 的 value,判斷 KEYS[1] 的 value 是否和 ARGV[1] 的值相等,如果相等,則洗掉 KEYS[1],

 

那么這段腳本怎么在 Java 專案中執行呢?

 

分兩步:先定義腳本;用 redisTemplate.execute 方法執行腳本,

// 腳本解鎖
String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);

 

上面的代碼中,KEYS[1] 對應“lock”,ARGV[1] 對應 “uuid”,含義就是如果 lock 的 value 等于 uuid 則洗掉 lock,

 

而這段 Redis 腳本是由 Redis 內嵌的 Lua 環境執行的,所以又稱作 Lua 腳本,

 

九、總結

 

本篇通過本地鎖的問題引申出分布式鎖的問題,然后介紹了五種分布式鎖的方案,由淺入深講解了不同方案的改進之處,

 

從上面幾種方案的不斷演進的程序中,知道了系統中哪些地方可能存在例外情況,以及該如何更好地進行處理,

 

舉一反三,這種不斷演進的思維模式也可以運用到其他技術中,

 

下面總結下上面五種方案的缺陷和改進之處,

 

1)青銅方案

 

  • 缺陷:業務代碼出現例外或者服務器宕機,沒有執行主動洗掉鎖的邏輯,就造成了死鎖,

 

  • 改進:設定鎖的自動過期時間,過一段時間后,自動洗掉鎖,這樣其他執行緒就能獲取到鎖了,

 

2)白銀方案

 

  • 缺陷:占鎖和設定鎖過期時間是分步兩步執行的,不是原子操作,

 

  • 改進:占鎖和設定鎖過期時間保證原子操作,

 

3)黃金方案

 

  • 缺陷:主動洗掉鎖時,因鎖的值都是相同的,將其他客戶端占用的鎖洗掉了,

 

  • 改進:每次占用的鎖,隨機設為較大的值,主動洗掉鎖時,比較鎖的值和自己設定的值是否相等,

 

4)鉑金方案

 

  • 缺陷:獲取鎖、比較鎖的值、洗掉鎖,這三步是非原子性的,中途又可能鎖自動過期了,又被其他客戶端搶占了鎖,導致刪鎖時把其他客戶端占用的鎖刪了,

 

  • 改進:使用 Lua 腳本進行獲取鎖、比較鎖、洗掉鎖的原子操作,

 

5)鉆石方案

 

  • 缺陷:非專業的分布式鎖方案,

 

  • 改進:Redission 分布式鎖,

 

上述所有代碼都基于 PassJava 開源專案,后端、前端、小程式都上傳到同一個倉庫里面了,大家可以通過 github 或 碼云訪問,地址如下:

 

Github:https://github.com/Jackson0714/PassJava-Platform

 

碼云:https://gitee.com/jayh2018/PassJava-Platform

 

配套教程:www.passjava.cn

 

>>>>

參考資料

 

  • http://redis.cn/commands/set.html

  • https://www.bilibili.com/video/BV1np4y1C7Yf

 

作者丨悟空聊架構

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/Five-evolution-strategies-of-Redis-distributed-lock.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/542340.html

標籤:架構設計

上一篇:讀編程與型別系統筆記11_高級型別及其他

下一篇:如何理解這6種常見設計模式?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more