轉轉基於MQ的分散式重試框架設計方案
來源:轉轉技術
1 背景
2 方案
3 效果
4 可選項
5 注意事項
6 總結
1 背景
在分散式場景下,為了保障系統的可用性和資料的最終一致性,採用基於訊息佇列(MQ
)的重試機制是一種常見的解決方案。虛擬碼如下:
/**
* 需要保證最終一致性的函式
*/
public void doSomething(Object args) {
try {
// 執行事務的操作
executeTransaction();
// 提交事務
commitTransaction();
} catch (Exception e) {
// 回滾事務
rollbackTransaction();
// 記錄日誌
log.error(e);
// 序列化引數
byte[] body = serialize(args);
// 構建訊息, 指定Topic、Body
Message msg = new Message("doSomethingTopic", body);
// 傳送失敗重試訊息
mq.send(msg);
}
}
/**
* 消費者,用於失敗重試處理
*/
@Consumer(topic = "doSomethingTopic")
public void consume(Message msg) {
// 反序列化
Object args = msg.deserialize();
// 重試
doSomething(args);
}
在上述示例中,我們需要編寫一系列與業務無關的程式碼來實現業務邏輯的重試機制。為了減輕開發人員的負擔並讓其專注於核心業務,我們可以對這些無關程式碼進行抽象和最佳化,以提高開發效率和程式碼質量。
2 方案
透過如下步驟,我們對重試邏輯進行了封裝,開發人員只需要在需要保證最終一致性的函式上標註一個重試註解,便擁有基於MQ的分散式重試能力。
1. 使用註解與AOP:
透過使用註解與面向切面程式設計(AOP
)的技術,將重試邏輯模組與業務程式碼解耦。開發人員可以在需要保證最終一致性的業務方法上新增註解,透過AOP將重試邏輯應用到目標方法中,從而自動觸發重試機制。
2. 提供配置化選項:
為重試邏輯提供可配置化的選項,例如設定最大重試次數、重試間隔時間等。這樣,開發人員可以根據具體業務需求進行調整,而無需修改程式碼。
3. 異常處理和日誌記錄:
在重試邏輯中合理地處理異常,並在必要時記錄相關日誌。這樣可以幫助開發人員及時發現問題並進行排查。
4. 提供視覺化監控工具:
開發一個視覺化的監控工具,用於實時跟蹤重試操作和相關指標。這樣可以幫助開發人員更好地理解重試的執行情況,並進行故障排查和效能最佳化。
3 效果
我們引入了@MQRetry
註解用於標記業務邏輯函式,一旦該函式發生異常,該註解會將服務名、類的完整名稱、方法名稱以及實際引數列表傳送到訊息佇列(MQ)中。同時系統會註冊一個MQ消費者來消費這些訊息,並進行重試處理。
舉個例子,假設我們有一個名為doSomething
的函式,它包含了需要保證最終一致性執行的業務邏輯。僅需在該函式上新增@MQRetry
註解,當函式出現異常時,框架會自動傳送一條MQ重試訊息
。這條訊息可以被當前服務的任意一臺伺服器消費,並重新執行doSomething
函式。
@Service
class Service {
@MQRetry
public void doSomething(String params1, String params2, List<String> params3) {
//throw new RuntimeException(); 拋異常將重試
//RetryContext.markRetryLater(); 標記為需要下次重試
//int retryCount = RetryContext.getRetryCount(); 獲取重試次數
}
}
@Controller
class Controller {
@Autowired
private Service service;
service.doSomething("1", "2", Arrays.asList("3", "4"));
}
4 可選項
除此之外,我們還為開發人員提供了一些可選項,提供一些可配置的能力。
/**
* 基於MQ的分散式重試元件
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MQRetry {
/**
* 最大重試次數,預設與上限為16次
*/
int maxAttempts() default 16;
/**
* 忽略的異常類列表,預設所有異常都重試
*/
Class<? extends Throwable>[] exclude() default {};
/**
* 需要重試的異常類列表,預設所有異常都重試
*/
Class<? extends Throwable>[] include() default {};
/**
* 出現異常時的處理函式, 格式: Bean名.方法名. 如: smsService.onError
* 也可以只設定函式名, 不設定Bean名將執行本類的函式. 如: onError
* 要求函式引數必須與重試函式的引數完全一致
*/
String errorHandler() default "";
/**
* true: 第一次呼叫時, 同步執行@MQRetry函式, 如果失敗再使用MQ
* false: 呼叫@MQRetry函式時, 只會傳送MQ
*/
boolean firstSyncCall() default true;
/**
* 消費執行緒數,預設為20個
*/
int consumeThread() default 20;
}
5 注意事項
適用於非同步場景,重試函式不要設定返回值,函式的返回值將不會有任何的實際意義。
At lease Once
保證,重試函式需要保證冪等。使用了AOP代理實現,因此,
@Transactional
的注意事項同樣適用於@MQRetry
,如this呼叫、private函式、final函式會導致重試失效。如果重試函式需要增加引數,請在函式引數最後位置新增。歷史訊息消費時對應引數將填充為null。
6 總結
在計算機領域中,重試機制的重要性不言而喻。它通常分為兩種模式:客戶端模式
和服務端模式
。客戶端模式簡單易用,但可靠性較低;而服務端模式雖然相對複雜,但能夠提供更高的可靠性。
無論是客戶端模式還是服務端模式,重試機制都是保障系統正常執行的重要一環。選擇適合您業務需求的模式,並透過合理的配置項進行最佳化,將為您的系統帶來更好的表現和使用者體驗。
關於作者
苑衝,轉轉架構部儲存服務負責人,負責MQ、監控系統、KV儲存、時序資料庫、Redis、KMS秘鑰管理等基礎元件。喜歡深入思考問題,對探索新領域和解決問題充滿熱情。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70027824/viewspace-3006006/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [轉載]基於Redis的分散式鎖到底安全嗎?Redis分散式
- 分散式ID設計方案分散式
- 一種基於柔性事務的分散式事務解決方案設計探究分散式
- 基於SPI的增強式外掛框架設計框架
- 基於Scrapy分散式爬蟲的開發與設計分散式爬蟲
- 基於RocketMq的分散式事務解決方案MQ分散式
- 設計一個分散式RPC框架分散式RPC框架
- iOS基於中間層的路由跳轉方案iOS路由
- 分散式服務(RPC)+分散式訊息佇列(MQ)面試題精選分散式RPC佇列MQ面試題
- 基於Seata探尋分散式事務的實現方案分散式
- 基於redis的分散式鎖Redis分散式
- 基於 Redis 的分散式鎖Redis分散式
- 基於kubernetes的分散式限流分散式
- 基於可靠訊息方案的分散式事務:Lottor介紹分散式
- 打造基於 PostgreSQL/openGauss 的分散式資料庫解決方案SQL分散式資料庫
- 關於MQ的幾件小事(七)如果讓你設計一個MQ,你怎麼設計MQ
- 分散式儲存轉崗記分散式
- 基於 BDD 理論的 Nebula 整合測試框架重構(上篇)框架
- 基於 BDD 理論的 Nebula 整合測試框架重構(下篇)框架
- 阿里巴巴開源分散式事務解決方案 FESCAR【轉】阿里分散式
- 基於SpringBoot AOP面向切面程式設計實現Redis分散式鎖Spring Boot程式設計Redis分散式
- (轉載 --- 上篇) 分散式系統測試那些事兒 - 理念分散式
- 技術分享| 基於 Etcd 的分散式鎖實現原理及方案分散式
- 基於java的分散式爬蟲Java分散式爬蟲
- 基於 dubbo 的分散式架構分散式架構
- 基於 Redis 分散式鎖Redis分散式
- 部署基於pythonwsgiweb框架的工程到函式計算PythonWeb框架函式
- 分散式重複提交問題架構設計思路分散式架構
- TiDB 分散式資料庫在轉轉公司的應用實踐TiDB分散式資料庫
- 從零到一帶你手寫基於Redis的分散式鎖框架Redis分散式框架
- 分散式儲存glusterfs詳解【轉】分散式
- GlusterFS企業分散式儲存【轉】分散式
- 玩轉用例設計:XMind2TestCase一個高效的測試用例設計解決方案
- 1. 揭秘Spring型別轉換 - 框架設計的基石Spring型別框架
- 面試必備的分散式事務方案面試分散式
- 基於Redis的任務排程設計方案Redis
- 基於promise的阻塞式佇列設計Promise佇列
- 基於可靠訊息方案的分散式事務(四):接入Lottor服務分散式