大廠都是怎麼做Redis重試的?

来源:https://www.cnblogs.com/JavaEdge/archive/2023/11/14/17831145.html
-Advertisement-
Play Games

0 前言 潛心打造國內一流,國際領先的技術乾貨。 文章收錄在我的 GitHub 倉庫,歡迎Star/fork: JavaEdge-Interview 受網路和運行環境影響,應用程式可能遇到暫時性故障,如瞬時網路抖動、服務暫時不可用、服務繁忙導致超時等。 自動重試機制可大幅避免此類故障,保障操作成功執 ...


0 前言

潛心打造國內一流,國際領先的技術乾貨。

文章收錄在我的 GitHub 倉庫,歡迎Star/fork:

JavaEdge-Interview

受網路和運行環境影響,應用程式可能遇到暫時性故障,如瞬時網路抖動、服務暫時不可用、服務繁忙導致超時等。

自動重試機制可大幅避免此類故障,保障操作成功執行。

1 引發暫時性故障的原因

1.1 故障觸發了高可用機制

雲Redis支持節點健康狀態監測,當監測到實例中的主節點不可用時,會自動觸發主備切換,例如將主節點和從節點進行互換,保障實例的高可用性。此時,客戶端可能會遇到下列暫時性故障:秒級的連接閃斷。30秒內的只讀狀態(用於避免主備切換引起潛在的數據丟失風險和雙寫)。

更多參見:主備切換

1.2 慢查詢引起了請求堵塞

執行時間複雜度為O(N)的操作,引發慢查詢和請求的堵塞,此時,客戶端發起的其他請求可能出現暫時性失敗。

1.3 複雜的網路環境

由於客戶端與Redis伺服器之間複雜網路環境引起,可能出現偶發的網路抖動、數據重傳等問題,此時,客戶端發起的請求可能會出現暫時性失敗。

2 推薦的重試準則

2.1 僅重試冪等的操作

由於超時可能發生在下述任一階段:該命令由客戶端發送成功,但尚未到達Redis。命令到達Redis,但執行超時。命令在Redis中執行結束,但結果返回給客戶端時發生超時。如果執行重試可能導致某個操作在Redis中被重覆執行,因此不是所有操作均適合設計重試機制。通常推薦僅重試冪等的操作,例如SET操作,即多次執行SET a b命令,那麼a的值只可能是b或執行失敗;如果執行LPUSH mylist a則不是冪等的,可能導致mylist中包含多個a元素。

2.2 適當的重試次數與間隔

根據業務需求和實際場景調整適當的重試次數與間隔,否則可能引發下述問題:如果重試次數不足或間隔太長,應用程式可能無法完成操作而導致失敗。如果重試次數過大或間隔過短,應用程式可能會占用過多的系統資源,且可能因請求過多而堵塞在伺服器上無法恢復。常見的重試間隔方式包括立即重試、固定時間重試、指數增加時間重試、隨機時間重試等。

2.3 避免重試嵌套

避免重試嵌套,否則可能會導致重覆的重試且無法停止。

2.4 記錄重試異常並列印失敗報告

在重試過程中,建議在WARN級別上列印重試錯誤日誌,同時,僅在重試失敗時列印異常信息。

3 Jedis

建議使用Jedis 4.0.0及以上版本,推薦使用最新的Jedis版本,以下代碼為Jedis 5.0.0的重試示例。

3.1 添加Jedis的Pom依賴

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.0.0</version>
</dependency>

3.2 重試實戰

① 標準架構實例或集群架構代理(Proxy)模式

使用JedisPool模式。

該示例會將SET命令自動重試5次,且總重試時間不超過10s,每次重試之間等待類指數間隔的時間,如果最終不成功,則拋出異常。

PooledConnectionProvider provider = new PooledConnectionProvider(HostAndPort.from("127.0.0.1:6379"));
int maxAttempts = 5; // 最大重試次數
Duration maxTotalRetriesDuration = Duration.ofSeconds(10); // 最大的重試時間
UnifiedJedis jedis = new UnifiedJedis(provider, maxAttempts, maxTotalRetriesDuration);
try {
    System.out.println("set key: " + jedis.set("key", "value"));
} catch (Exception e) {
    // 表示嘗試maxAttempts次或到達了最大查詢時間maxTotalRetriesDuration仍舊沒有訪問成功。
    e.printStackTrace();
}

② 集群架構直連模式

使用JedisCluster模式。

可以通過配置maxAttempts參數來定義失敗情況下的重試次數,預設值為5,如果最終不成功,則拋出異常。

HostAndPort hostAndPort = HostAndPort.from("127.0.0.1:30001");
int connectionTimeout = 5000;
int soTimeout = 2000;
int maxAttempts = 5;
ConnectionPoolConfig config = new ConnectionPoolConfig();
JedisCluster jedisCluster = new JedisCluster(hostAndPort, connectionTimeout, soTimeout, maxAttempts, config);
try {
    System.out.println("set key: " + jedisCluster.set("key", "value"));
} catch (Exception e) {
    // 表示嘗試maxAttempts之後仍舊沒有訪問成功。
    e.printStackTrace();
}

4 Redisson

Redisson客戶端提供了兩個參數來控制重試邏輯:

  • retryAttempts:重試次數,預設為3。
  • retryInterval:重試間隔,預設為1,500毫秒。

重試示例如下:

Config config = new Config();
config.useSingleServer()
    .setTimeout(1000)
    .setRetryAttempts(3)
    .setRetryInterval(1500) //ms
    .setAddress("redis://127.0.0.1:6379");
RedissonClient connect = Redisson.create(config);

5 StackExchange.Redis

StackExchang.Redis客戶端目前僅支持重試時連接,重試示例如下:

var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");

說明

如需實現API級別的重試策略,請參見Polly

6 Lettuce

Lettuce客戶端未提供在命令超時後重試的參數,但是您可以通過下述參數來實現命令重試策略:

  • at-most-once execution:命令最多執行1次,即0次或1次,如果連接斷開並重新連接,命令可能會丟失。
  • at-least-once execution(預設):最少成功執行1次,即可能會在執行時進行多次嘗試,保障最少成功執行1次。使用此策略時,如果Tair實例發生了主備切換,此時客戶端可能累積了較多的重試命令,主備切換完成後可能會引發Tair實例的CPU使用率激增。

說明

更多信息,請參見Client-OptionsCommand execution reliability

重試示例:

clientOptions.isAutoReconnect() ? Reliability.AT_LEAST_ONCE : Reliability.AT_MOST_ONCE;

參考:

本文由博客一文多發平臺 OpenWrite 發佈!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原子引用 帶版本號的原子操作! 解決ABA問題,引入原子引用(樂觀鎖思想) AtomicStampedReference類解決ABA問題 package org.example.cas; import java.util.concurrent.TimeUnit; import java.util.c ...
  • C++ 中 <iterator> <functional> <numeric> 庫好用的函數 泰褲辣! <iterator> 簡述:迭代器省代碼用的。 std::advance 記憶方法:advance-前進。 形如:advance(it, step),表示 it 迭代器自增 step 步。 實現類 ...
  • 寫在前面 接上文《Python學習 —— 初步認知》,有需要請自取:Python學習 —— 初步認知 在這篇文章中,我們一起深入瞭解Python中常用的內置數據類型。Python是一種功能強大的編程語言,它提供了多種內置數據類型,用於存儲和操作數據。這些數據類型包括數字、字元串、序列和映射等。熟練掌 ...
  • 賦值表達式(assignment expression)是Python 3.8新引入的語法,它會用到海象操作符(walrus operator)。 這種寫法可以解決某些持續已久的代碼重覆問題。a = b是一條普通的賦值語句,讀作a equals b,而a := b則是賦值表達式,讀作a walrus ...
  • 1.首先是準備施法材料 JDK的下載地址:https://www.oracle.com/java/technologies/downloads/ 然後選擇自己的想要的版本和英雄(系統) 選擇x64 Compressed Archive免安裝版本進行下載(解壓就用,免除瘋狂確認的煩惱) 解壓到某個位置 ...
  • 來源:blog.csdn.net/qq_44384533/article/details/112324224 之前紅包權益領取查詢的介面超時了,因為有用戶訂購的權益有點多 解決方案 用線程池+ FutureTask將1個查詢拆分成多個小查詢 選擇FutureTask是因為它具有僅執行1次run()方 ...
  • NullPointerException(空指針異常):當試圖調用實例方法或訪問實例變數時,對象引用為 null 時拋出。ArithmeticException(算術異常):當試圖做出違反算術規則的操作時拋出,比如除以零。ClassCastException(類轉換異常):當試圖將對象強制轉換為不是... ...
  • 從JDK11到JDK17,到底帶來了哪些特性呢?亞毫秒級的ZGC效果到底怎麼樣呢?值得我們升級嗎?而且升級過程會遇到哪些問題呢?帶著這些問題,本篇文章將帶來完整的JDK11升級JDK17最全實踐。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...