面試遇到的問題2

Redisson的看門狗相關問題

首先要明確一點,看門狗機制的使用方式是:在加鎖的時候不加任何參數,也就是:

RLock lock = redisson.getLock("myLock");
try {lock.lock();  // 阻塞式加鎖// 業務邏輯...
} finally {lock.unlock(); // 確保在finally中釋放鎖
}  //這樣子加鎖會使用看門狗,也就是說這個鎖會一直的續命下去,只要代碼沒有執行到 lock.unlock() 這一行

如果加了參數,那么和看門狗這個機制就完全不搭邊,時間到了,強制放鎖
通過 lock.lock(long leaseTime, TimeUnit unit) 指定鎖的最大持有時間,超時后鎖也會強制釋放:

RLock lock = redisson.getLock("myLock");
try {// 設置鎖超時時間為10秒,看門狗不會續期lock.lock(10, TimeUnit.SECONDS); // 業務邏輯...
} finally {if (lock.isLocked() && lock.isHeldByCurrentThread()) {lock.unlock();}
}

那么說到這里就有一個很明顯的問題,不加參數的時候,如果try里面有了死鎖,或者一不小心寫了 Thread.sleep(Integer.Max)這樣的代碼,那么這個鎖就會一直不放,這顯然是不對的,如果加了參數,強制放鎖的時候,邏輯又沒有執行完,就會有數據不一致,或者說并發的問題。怎么辦?

問題核心

  • 不加超時時間(依賴看門狗):業務死鎖時,鎖會無限續期,導致其他線程永遠無法獲取鎖(死鎖風險)。
  • 加超時時間(強制釋放):若業務未執行完但鎖已超時釋放,其他線程可能并發操作(數據不一致風險)。

解決方案

1. 合理設置超時時間(平衡點)
  • 原則

    • 超時時間(leaseTime)應 略大于 業務平均執行時間(如業務通常耗時 5秒,設置 leaseTime=10秒)。
    • 通過壓測或監控統計業務耗時,動態調整超時時間。
  • 示例

    RLock lock = redisson.getLock("orderLock");
    try {// 設置超時時間為平均耗時的2倍lock.lock(10, TimeUnit.SECONDS); // 業務邏輯(假設通常耗時3~5秒)...
    } finally {lock.unlock();
    }
    
2. 異步續期 + 主動心跳檢測
  • 適用場景:業務耗時波動大(如依賴外部服務響應)。

  • 實現方式

    1. 仍設置較短的 leaseTime(如 10秒)。
    2. 在業務代碼中定期向 Redis 發送“心跳”(如每 5秒更新一次鎖的時間戳)。
    3. 若業務卡死,心跳停止,鎖超時釋放。
  • 偽代碼

    RLock lock = redisson.getLock("orderLock");
    try {lock.lock(10, TimeUnit.SECONDS);while (業務未完成) {// 業務邏輯...redisson.getBucket("lock:heartbeat:" + lockName).set(System.currentTimeMillis());Thread.sleep(5000); // 每5秒發送心跳}
    } finally {lock.unlock();
    }
    
3. 分段鎖(減小鎖粒度)
  • 原理:將大鎖拆分為多個小鎖,降低單個鎖的持有時間。
  • 示例
    // 對訂單ID分段加鎖(如按訂單ID哈希取模)
    int segment = orderId.hashCode() % 16;
    RLock lock = redisson.getLock("orderLock:" + segment);
    lock.lock(10, TimeUnit.SECONDS);
    
4. 兜底補償機制
  • 場景:鎖超時釋放后,其他線程并發操作導致數據不一致。
  • 方案
    • 記錄操作日志或版本號,通過定時任務檢查并修復不一致數據。
    • 使用數據庫樂觀鎖(如 UPDATE table SET value=newVal WHERE id=xxx AND version=oldVersion)。
5. 結合 tryLock 和熔斷機制
  • 策略

    1. 嘗試獲取鎖(帶短時間等待)。
    2. 若獲取失敗,觸發熔斷(如返回“系統繁忙”)。
    3. 避免線程堆積導致雪崩。
  • 代碼示例

    if (lock.tryLock(1, 10, TimeUnit.SECONDS)) { // 最多等待1秒,鎖超時10秒try {// 業務邏輯...} finally {lock.unlock();}
    } else {throw new BusyException("系統繁忙,請重試");
    }
    

最佳實踐總結

方案適用場景優點缺點
合理設置超時時間業務耗時穩定簡單可靠需準確預估耗時
異步續期 + 心跳業務耗時波動大靈活控制鎖生命周期實現復雜
分段鎖高并發場景減少鎖競爭需設計合理分段規則
兜底補償對一致性要求不苛刻最終一致修復延遲
tryLock + 熔斷高并發且允許短暫失敗避免系統過載用戶體驗可能受影響

終極建議

  1. 優先使用 lock(leaseTime):根據業務 P99 耗時設置超時時間(如 P99=3秒,設 leaseTime=5秒)。
  2. 關鍵業務加監控:對鎖持有時間超過閾值(如 80% leaseTime)觸發告警。
  3. 設計冪等操作:即使鎖超時導致并發,業務邏輯也能安全重試(如唯一鍵防重)。

:沒有完美的方案,需根據業務容忍度權衡 “死鎖風險”“并發風險”

Redisson中的鎖是什么結構,存的是什么?底層實現是 setnx 么?

Redisson 分布式鎖的底層實現

Redisson 的分布式鎖(如 RLock)并非直接使用 Redis 的 SETNX 命令,而是基于 Lua 腳本Hash 結構 實現了一套更復雜的機制,支持可重入、鎖續期(看門狗)、公平鎖等高級特性。


1. 鎖的存儲結構

Redisson 的鎖在 Redis 中存儲為一個 Hash 結構,Key 的名稱即鎖的名稱(如 myLock),Hash 的字段和值如下:

Hash FieldValue說明
UUID:threadId計數器(重入次數)鎖的持有者標識(UUID 為客戶端唯一ID,threadId 為線程ID),計數器表示重入次數。
moderedisson_lock標識這是一個 Redisson 鎖。
leaseTime過期時間(毫秒)鎖的租約時間(看門狗續期時會更新)。

示例 Redis 數據

HGETALL myLock
1) "b983c153-7421-469a-addf-8de0345aaedd:1"  # UUID:線程ID
2) "1"                                       # 重入次數
3) "mode"
4) "redisson_lock"
5) "leaseTime"
6) "30000"                                   # 30秒過期時間

2. 加鎖流程(核心 Lua 腳本)

Redisson 加鎖的核心是通過 Lua 腳本 保證原子性,邏輯如下:

(1) 加鎖腳本(lock.lua

-- 參數:KEYS[1]=鎖名稱, ARGV[1]=鎖過期時間, ARGV[2]=客戶端UUID:線程ID
-- 1. 檢查鎖是否存在
if (redis.call('exists', KEYS[1]) == 0) then-- 鎖不存在,直接加鎖redis.call('hset', KEYS[1], ARGV[2], 1);  -- 設置 Hash 字段(UUID:threadId: 1)redis.call('pexpire', KEYS[1], ARGV[1]);  -- 設置過期時間return nil;                               -- 返回 nil 表示加鎖成功
end;-- 2. 鎖已存在,檢查是否當前線程持有
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then-- 可重入鎖:增加計數器redis.call('hincrby', KEYS[1], ARGV[2], 1);redis.call('pexpire', KEYS[1], ARGV[1]);  -- 續期return nil;
end;-- 3. 鎖被其他線程持有,返回剩余存活時間(TTL)
return redis.call('pttl', KEYS[1]);

關鍵點

  • 原子性:通過 Lua 腳本保證 exists + hset + pexpire 的原子操作。
  • 可重入:同一個線程多次加鎖時,hincrby 增加計數器。
  • 鎖競爭:如果鎖被其他線程持有,返回剩余 TTL,客戶端會循環嘗試。

(2) 看門狗續期機制

如果使用 lock() 不加超時時間,Redisson 會啟動一個 看門狗線程(Watchdog),默認每 10秒 檢查鎖是否仍被當前線程持有,如果是,則續期 30秒

-- 續期腳本
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) thenredis.call('pexpire', KEYS[1], ARGV[1]); -- 重置過期時間return 1;
end;
return 0;

3. 解鎖流程

解鎖時,Redisson 會先檢查鎖是否仍被當前線程持有,然后減少重入計數或直接刪除鎖:

-- 參數:KEYS[1]=鎖名稱, ARGV[1]=過期時間, ARGV[2]=客戶端UUID:線程ID
-- 1. 檢查鎖是否屬于當前線程
if (redis.call('hexists', KEYS[1], ARGV[2]) == 0) thenreturn nil;
end;-- 2. 減少重入計數
local counter = redis.call('hincrby', KEYS[1], ARGV[2], -1);
if (counter > 0) then-- 仍持有鎖(重入情況),續期redis.call('pexpire', KEYS[1], ARGV[1]);return 0;
else-- 完全釋放鎖,刪除 Keyredis.call('del', KEYS[1]);-- 發布解鎖消息(通知其他等待線程)redis.call('publish', KEYS[2], ARGV[3]);return 1;
end;

4. 與 SETNX 的區別

對比項Redisson 鎖SETNX 鎖
數據結構Hash(存儲客戶端ID、重入次數)String(簡單 Key-Value)
可重入? 支持(通過計數器)? 不支持
自動續期? 看門狗機制? 需手動實現
公平鎖? 支持(通過 Redis 隊列)? 不支持
原子性? Lua 腳本保證?? 需配合 EXPIRE(非原子)

5. 總結

  1. Redisson 鎖的底層是 Hash 結構,存儲 客戶端ID:線程ID重入次數
  2. 加鎖/解鎖通過 Lua 腳本保證原子性,而非簡單的 SETNX
  3. 看門狗機制 自動續期,避免鎖過期。
  4. 支持可重入、公平鎖等高級特性,比 SETNX 更強大。

適用場景

  • 需要可重入鎖 → Redisson
  • 簡單互斥鎖 → SETNX + EXPIRE(但需自行處理原子性問題)

看門狗是如何知道某個線程是否存活,或者說某個線程是否還在執行?

Redisson 看門狗(Watchdog)如何檢測線程存活?

Redisson 的看門狗機制并不直接監控 JVM 線程是否存活,而是通過以下方式間接判斷業務是否仍在執行,從而決定是否續期鎖:


1. 看門狗的核心邏輯

(1) 鎖續期的觸發條件

  • 當使用 lock() 不加超時時間時,Redisson 會啟動一個后臺線程(看門狗),默認每隔 10秒 執行一次續期檢查。
  • 續期條件
    1. 鎖仍存在于 Redis 中(未被手動釋放或過期)。
    2. 鎖的持有者仍是當前客戶端和線程(通過 Redis Hash 中的 UUID:threadId 字段驗證)。

(2) 續期流程

  1. 檢查鎖歸屬
    看門狗通過 Lua 腳本檢查 Redis 中的鎖是否仍由當前客戶端(UUID)和線程(threadId)持有:
    if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then  -- 檢查UUID:threadId是否存在redis.call('pexpire', KEYS[1], ARGV[1]);          -- 續期鎖return 1;
    end;
    return 0;
    
  2. 續期或終止
    • 如果鎖仍屬于當前線程,則重置過期時間為 30秒(默認)。
    • 如果鎖已被釋放或歸屬變更,看門狗停止續期。

2. 如何判斷業務線程是否仍在執行?

看門狗不直接監控業務線程狀態,而是通過以下間接機制推斷:

(1) JVM 線程存活間接關聯

  • 鎖釋放的觸發條件

    • 業務線程正常執行完成后,調用 lock.unlock(),刪除 Redis 中的鎖。
    • 如果業務線程崩潰或阻塞,unlock() 不會被調用,鎖會因看門狗續期而長期存在。
  • 看門狗續期的隱含假設

    • 只要 JVM 進程存活,且持有鎖的線程未調用 unlock(),看門狗就會認為業務仍在執行(即使線程實際已阻塞或死鎖)。

(2) 異常情況處理

  • 線程崩潰或 JVM 退出

    • 看門狗線程是后臺守護線程(Daemon Thread),如果 JVM 進程退出,看門狗會停止運行,鎖最終會在 Redis 中自然過期(默認 30秒后釋放)。
    • 無需依賴線程存活檢測,依賴 Redis 的過期機制兜底。
  • 網絡分區或 Redis 不可用

    • 看門狗無法連接 Redis 時,續期失敗,鎖會在過期后自動釋放。

3. 為什么不用 Java 線程監控?

  1. 分布式環境限制
    • Redisson 是分布式鎖,可能跨多個 JVM 或機器,無法直接監控其他 JVM 的線程狀態。
  2. 復雜度與可靠性
    • 線程監控需依賴 JVM 的 Thread.isAlive(),但分布式場景下不可靠(如網絡分區時誤判)。
  3. Redis 是唯一信源
    • 所有鎖狀態由 Redis 存儲,看門狗只需關心 Redis 中的數據,無需跨進程協調。

4. 關鍵結論

問題Redisson 的解決方案
如何知道線程是否存活?不直接檢測,而是通過鎖是否被主動釋放(unlock())判斷。未釋放則續期。
線程崩潰后鎖何時釋放?依賴 Redis 的 Key 過期機制(默認 30秒),看門狗停止續期后鎖自動釋放。
看門狗如何保證不續死鎖?業務必須顯式調用 unlock(),否則需設置超時時間(lock(10, TimeUnit.SECONDS))避免無限續期。

5. 最佳實踐

  1. 避免依賴看門狗無限續期
    • 優先使用 lock(leaseTime, unit) 設置合理的超時時間,即使業務卡死,鎖也會自動釋放。
    lock.lock(10, TimeUnit.SECONDS); // 明確指定超時時間
    
  2. 確保鎖被釋放
    • unlock() 放在 finally 塊中,防止異常導致鎖泄漏。
    try {lock.lock();// 業務邏輯...
    } finally {lock.unlock();
    }
    
  3. 監控長耗時鎖
    • 對持有時間超過閾值的鎖觸發告警(如通過 Redisson 的 RLock.getRemainingLeaseTime())。

總結

Redisson 的看門狗通過 定期續期 Redis 鎖檢查鎖歸屬 間接判斷業務是否執行中,而非直接監控線程狀態。
設計核心思想分布式鎖的安全性應完全由 Redis 保證,避免依賴 JVM 層面的不可靠檢測。

也就是說看門狗其實和 jvm中線程完全沒關系,只不過是運行借助jvm運行的一個守護線程,這個守護線程只和redis通信,不和jvm中其他線程做任何的數據交互

核心總結

  1. 看門狗的本質

    • 看門狗線程的啟動時機,全局看門狗線程池:Redisson 在客戶端初始化時(即 RedissonClient 創建時)會啟動一個名為redisson-timeout 的守護線程池。這個線程池并非專為看門狗設計,而是用于處理所有需要超時控制的異步任務(包括但不限于鎖的續期)。

    • 看門狗線程的懶加載:只有在首次使用無超時鎖(lock())時,才會從該線程池中分配一個線程作為專屬看門狗,用于定期續期該鎖。如果只用帶超時的鎖(lock(leaseTime, unit)),則不會分配看門狗線程。

    • 僅與 Redis 交互,通過定期執行 Lua 腳本檢查/續期鎖,完全不感知 JVM 內其他線程的狀態(如是否阻塞、崩潰)。

  2. 與 JVM 線程的關系

    • 不依賴線程監控:看門狗不會檢查業務線程(如 Thread.isAlive()),也不與業務線程直接通信。
    • 僅依賴 Redis 數據:通過 Redis 中鎖的 UUID:threadId 字段是否存在,間接判斷是否續期。
  3. 設計優勢

    • 解耦:分布式鎖的安全性完全由 Redis 保證,與 JVM 線程生命周期無關。
    • 輕量:避免復雜的線程監控,僅通過 Redis 的鍵存在性檢查實現高效續期。
    • 可靠:即使業務線程死鎖,鎖最終會因看門狗停止(JVM 退出)或 Redis 過期而釋放。

關鍵流程驗證

場景看門狗行為鎖的最終狀態
業務線程正常執行并解鎖看門狗檢測到 unlock() 刪除 Redis 中的 UUID:threadId,停止續期。立即釋放
業務線程死鎖/阻塞看門狗持續續期(因 UUID:threadId 仍在 Redis 中),直到 JVM 退出或手動干預。可能長期占用(需設置超時時間避免)
JVM 崩潰看門狗線程終止,無人續期,Redis 中的鎖自然過期(默認30秒)。自動釋放

代碼層面驗證

1. 看門狗線程的啟動

Redisson 客戶端初始化時,會創建一個全局的 Watchdog 守護線程(單例):

public class RedissonClient {private final Watchdog watchdog = new Watchdog(); // 守護線程
}
2. 續期任務提交

業務線程加鎖時,向看門狗注冊續期任務(僅記錄鎖名稱和 UUID:threadId):

lock.lock(); // 無參加鎖
// 內部邏輯:
watchdog.scheduleRenewal("myLock", "uuid:threadId");
3. 看門狗的工作內容

看門狗線程循環檢查任務隊列,通過 Redis 的 hexists 命令驗證鎖歸屬:

// 偽代碼
while (!Thread.interrupted()) {for (LockTask task : tasks) {String result = redis.eval("if (redis.call('hexists', KEYS[1], ARGV[1]) == 1) then " +"   redis.call('pexpire', KEYS[1], ARGV[2]); " +"   return 1; " +"end; " +"return 0;",Collections.singletonList(task.getLockName()),task.getUUIDThreadId(), "30000" // 續期30秒);if (result.equals("0")) {removeTask(task); // 鎖已失效,移出任務隊列}}Thread.sleep(10000); // 默認10秒檢查一次
}

常見問題解答

Q1: 如果業務線程卡死,看門狗會一直續期嗎?

? 是的,因為看門狗只檢查 Redis 中的 UUID:threadId 是否存在,不感知線程狀態。需通過 lock(leaseTime, unit) 設置超時時間避免無限續期。

Q2: 為什么看門狗不直接監控業務線程?
  • 分布式限制:無法跨 JVM 監控線程(如微服務場景)。
  • 復雜度:線程監控需處理 JVM 崩潰、網絡分區等邊界條件,不可靠。
Q3: 看門狗會拖累 Redis 性能嗎?
  • 低開銷:續期是低頻操作(默認10秒一次),且 Lua 腳本輕量。
  • 單線程優化:所有鎖的續期由同一個看門狗線程批量處理。

最佳實踐建議

  1. 永遠設置超時時間
    lock.lock(10, TimeUnit.SECONDS); // 避免死鎖導致無限續期
    
  2. 確保解鎖
    try {lock.lock();// 業務邏輯...
    } finally {lock.unlock(); // 必須釋放!
    }
    
  3. 監控長耗時鎖
    long remainTime = lock.remainTimeToLive();
    if (remainTime > THRESHOLD) {log.warn("鎖持有時間過長:{}", lock.getName());
    }
    

總結

? 看門狗是一個純粹的 Redis 通信守護線程,通過定期檢查 Redis 中的鎖歸屬決定是否續期,與 JVM 線程完全解耦。
這種設計實現了分布式鎖的高可靠性低侵入性,但需開發者合理設置超時時間避免死鎖。

看門狗是多久檢查一次上鎖的hash?續命多久?

在 Redisson 中,看門狗(Watchdog) 的檢查與續期機制是鎖續期的核心邏輯,具體行為如下:


1. 看門狗的檢查與續期頻率

  • 默認檢查間隔每 10 秒lockWatchdogTimeout / 3)檢查一次鎖狀態。
    • lockWatchdogTimeout 默認值為 30 秒(可通過 Config.lockWatchdogTimeout 調整)。
    • 計算公式:續期間隔 = lockWatchdogTimeout / 330s / 3 = 10s
  • 續期邏輯:每次檢查時,如果鎖仍被當前線程持有,則將鎖的過期時間重置為 lockWatchdogTimeout(默認 30 秒)

2. 關鍵源碼解析

(1)續期任務調度(scheduleExpirationRenewal
// RedissonLock.java
protected void scheduleExpirationRenewal(long threadId) {// 每 (lockWatchdogTimeout / 3) 秒執行一次續期Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) {// 執行續期邏輯renewExpiration();}}, lockWatchdogTimeout / 3, TimeUnit.MILLISECONDS); // 默認 10 秒
}
(2)續期操作(renewExpiration
// RedissonLock.java
void renewExpiration() {// 通過 Lua 腳本重置鎖的 TTLRFuture<Boolean> future = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +  // 重置 TTL 為 lockWatchdogTimeout"return 1; " +"end; " +"return 0;",Collections.singletonList(getName()),internalLockLeaseTime,  // ARGV[1]: lockWatchdogTimeout(默認 30000 毫秒)getLockName(threadId)   // ARGV[2]: 客戶端標識);// 遞歸調用,實現周期性續期future.onComplete((res, e) -> {if (e != null) {return;}if (res) {scheduleExpirationRenewal(threadId); // 繼續下一次續期}});
}

3. 續期流程總結

  1. 首次加鎖(無超時)
    • 鎖在 Redis 中的 TTL 默認設為 lockWatchdogTimeout(30 秒)。
    • 看門狗在 10 秒 后首次檢查,若鎖仍存在,則重置 TTL 為 30 秒
  2. 周期性續期
    • 10 秒 檢查一次,若鎖未被釋放,則再次續期 30 秒
    • 直到顯式調用 unlock() 或客戶端崩潰(此時續期任務停止,Redis 自動過期)。

4. 關鍵配置參數

參數默認值說明
lockWatchdogTimeout30000 ms鎖的默認存活時間(無超時鎖的初始 TTL 和續期時長)。可通過 Config 自定義。
實際續期間隔10000 mslockWatchdogTimeout / 3,即默認 10 秒。

5. 注意事項

  1. 僅對無超時鎖生效
    顯式指定 leaseTime 的鎖(如 lock(10, SECONDS))不會觸發看門狗續期。
  2. 避免長時間阻塞
    如果業務邏輯執行時間超過 lockWatchdogTimeout,且未及時續期,鎖可能因 Redis TTL 到期而失效。
  3. 調整參數需謹慎
    • 增大 lockWatchdogTimeout:降低續期頻率,但鎖釋放延遲可能增加。
    • 減小 lockWatchdogTimeout:提高續期頻率,但增加 Redis 和網絡負載。

6. 示例場景

// 無超時鎖(啟用看門狗)
RLock lock = redisson.getLock("myLock");
lock.lock(); // 看門狗每 10 秒續期一次,每次續 30 秒
try {// 執行業務邏輯(可能耗時較長)
} finally {lock.unlock(); // 主動釋放,停止續期
}

通過這種機制,Redisson 確保了無超時鎖的長期持有安全性,同時避免了因客戶端崩潰導致的死鎖問題

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91340.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91340.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91340.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux—進程概念與理解

目錄 1.馮諾依曼體系結構 小結&#xff1a; 2.操作系統 概念&#xff1a; 結構示意圖&#xff1a; 理解操作系統&#xff1a; 用戶使用底層硬件層次圖&#xff1a;?編輯 3.進程 概念 結構示意圖 task_ struct內容分類 典型用法示例 觀察進程: 了解 PID PPID 查…

LeetCode 面試經典 150_數組/字符串_買賣股票的最佳時機(7_121_C++_簡單)(貪心)

LeetCode 面試經典 150_數組/字符串_買賣股票的最佳時機&#xff08;7_121_C_簡單&#xff09;題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;貪心算法&#xff09;&#xff1a;代碼實現代碼實現&#xff08;思路一&…

Ubuntu 18.04 repo sync報錯:line 0: Bad configuration option: setenv

repo sync時報 line 0: Bad configuration option: setenv因為 Ubuntu 18.04 默認的 openssh-client 是 7.6p1&#xff0c;還不支持 setenv&#xff0c;但是.repo/repo/ssh.py 腳本中明確地傳入了 SetEnv 參數給 ssh&#xff0c;而你的 OpenSSH 7.6 不支持這個參數。需要按如下…

bug記錄-stylelint

BUG1不支持Vue文件內聯style樣式解決&#xff1a; "no-invalid-position-declaration": null

前端開發(HTML,CSS,VUE,JS)從入門到精通!第一天(HTML5)

一、HTML5 簡介1&#xff0e;HTML全稱是 Hyber Text Markup Language&#xff0c;超文本標記語言&#xff0c;它是互聯網上應用最廣泛的標記語言&#xff0c;簡單說&#xff0c;HTML 頁面就等于“普通文本HTML標記&#xff08;HTML標簽&#xff09;“。2&#xff0e;HTML 總共經…

智慧收銀系統開發進銷存:便利店、水果店、建材與家居行業的—仙盟創夢IDE

在數字化轉型的浪潮中&#xff0c;收銀系統已不再局限于簡單的收款功能&#xff0c;而是成為企業進銷存管理的核心樞紐。從便利店的快消品管理到建材家居行業的大宗商品調度&#xff0c;現代收銀系統通過智能化技術重塑了傳統商業模式。本文將深入探討收銀系統在不同行業進銷存…

三維掃描相機:工業自動化的智慧之眼——遷移科技賦能智能制造新紀元

在當今工業4.0時代&#xff0c;自動化技術正重塑生產流程&#xff0c;而核心工具如三維掃描相機已成為關鍵驅動力。作為工業自動化領域的“智慧之眼”&#xff0c;三維掃描相機通過高精度三維重建能力&#xff0c;解決了傳統制造中的效率瓶頸和精度痛點。遷移科技&#xff0c;自…

Jmeter的元件使用介紹:(九)監聽器詳解

監聽器主要是用來監聽腳本執行的取樣器結果。Jmeter的默認監聽器有&#xff1a;查看結果樹、聚合報告、匯總報告、用表格查看結果&#xff0c;斷言結果、圖形結果、Beanshell監聽器、JSR223監聽器、比較斷言可視化器、后端監聽器、郵件觀察器&#xff0c;本文介紹最常用的監聽器…

聯通元景萬悟 開源,搶先體驗!!!

簡介&#xff1a; 元景萬悟智能體平臺是一款面向企業級場景的一站式、商用license友好的智能體開發平臺&#xff0c;是業界第一款go語言&#xff08;后端&#xff09;開發的智能體開發平臺&#xff08;7月19日&#xff09;&#xff0c;coze studio開源是7月26日&#xff0c;同時…

Git之本地倉庫管理

一.什么是Git在學習工作中&#xff0c;我們經常會遇到改文檔的場景。一個文檔可能會被我們修改多次&#xff0c;而最終真正使用的可能是最先的幾版。而如果我們直接在原文檔上修改&#xff0c;就會導致無法找到最先的幾次。這也就導致我們要對我們所有的版本進行維護&#xff0…

Go再進階:結構體、接口與面向對象編程

&#x1f680; Go再進階&#xff1a;結構體、接口與面向對象編程 大家好&#xff01;在前兩篇文章中&#xff0c;我們深入學習了Go語言的流程控制語句以及數組和切片的使用并且還對Go 語言的核心知識點進行了補充講解&#xff0c;這些知識讓我們能夠編寫出更為復雜和靈活的程序…

Python入門第六課:現代開發與前沿技術

異步編程(asyncio) 1. 協程基礎 import asyncio import time# 定義協程函數 async def say_after(delay, message):await asyncio.sleep(delay)print(message)# 主協程 async def main():print(f"開始時間: {time.strftime(%X)}")# 順序執行await say_after(2, 你…

STM32移植LVGL9.2.1教程

一、環境說明 &#xff08;1&#xff09;開發板&#xff1a;STM32F401RCT6核心板&#xff08;網上很多&#xff0c;價格只有幾塊錢&#xff09; &#xff08;2&#xff09;屏幕&#xff1a;2.8寸spi屏gt911觸摸 轉接板&#xff08;某寶有賣&#xff0c;沒有推廣自行搜索&…

python學智能算法(二十九)|SVM-拉格朗日函數求解中-KKT條件理解

【1】引言 前序學習階段中&#xff0c;我們掌握了最佳分割超平面對應的構造拉格朗日函數極值為&#xff1a; L(w,b,α)∑i1mαi?12∑i,j1mαiαjyiyjxiTxjL(w,b,\alpha)\sum_{i1}^{m}\alpha_{i}-\frac{1}{2}\sum_{i,j1}^{m}\alpha_{i}\alpha_{j}y_{i}y_{j}x_{i}^{T}x_{j}L(w,…

大模型應用開發1-認識大模型

1.基礎概念 1.1 AI的概念&#xff1a; AI&#xff0c;??智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;使機器能夠像?類?樣思考、學習和解決問題的技術。AI發展?今?概可以分為三個階段&#xff1a;其中&#xff0c;深度學習領域的自然語言處理&#…

Linux 遠程連接解析:SSH 協議理論與應用

Linux 遠程連接解析&#xff1a;SSH 協議理論與應用在網絡互聯的時代&#xff0c;遠程管理服務器已成為常態。SSH&#xff08;Secure Shell&#xff09;作為一種安全的網絡協議&#xff0c;憑借其加密機制和靈活的功能&#xff0c;成為 Linux 系統遠程操作的事實標準。本文將從…

ubuntu22.04系統入門 linux入門 簡單命令基礎復習 實現以及實踐

以下有免費的4090云主機提供ubuntu22.04系統的其他入門實踐操作 地址&#xff1a;星宇科技 | GPU服務器 高性能云主機 云服務器-登錄 相關兌換碼星宇社區---4090算力卡免費體驗、共享開發社區-CSDN博客 兌換碼要是過期了&#xff0c;可以私信我獲取最新兌換碼&#xff01;&a…

軟考中級-信息安全工程師-每日一學(1)

前提概要本文章主要用于分享軟考中級-信息安全工程師-學習&#xff0c;以下是一些個人理解&#xff0c;請大家結合參考其他文章中的相關信息及個人經驗進行歸納和補充&#xff0c;內容會存在一定錯誤&#xff0c;希望讀者多多評論批評&#xff0c;本人在此先說感謝啦。1.密碼學…

EEG手工特征提取總結

目錄一、引言EEG信號簡介EEG特征提取的重要性本次匯報目的與內容概述二、EEG信號核心特征時域特征 (Time-Domain Features)頻域特征 (Frequency-Domain Features)三、EEG信號高級特征時頻域特征 (Time-Frequency Domain Features)空間域特征 (Spatial-Domain Features)復雜動力…

React 路由守衛

下面&#xff0c;我們來系統的梳理關于 React Router 路由守衛 的基本知識點&#xff1a;一、路由守衛概述 1.1 什么是路由守衛 路由守衛是一種在用戶導航到特定路由之前或離開特定路由時執行邏輯的機制。它允許開發者控制用戶訪問權限、驗證條件或執行數據預加載等操作。 1.2 …