圖解支付系統訂單號設計與最佳實踐

大家好,我是隱墨星辰,深耕境內 / 跨境支付架構設計十餘年。

本文主要講清楚支付系統訂單號(或業務 ID)各種設計方案對比,各子域的訂單號(或業務 ID)爲什麼要統一規範,以及最佳實踐。最後還會簡單分析微信支付和支付寶的對客訂單號的組成差異。

假如你也好奇爲什麼有了數據庫自增 ID 外還需要業務 ID,或者想了解如何在業務 ID 中編織進業務信息比如業務系統,數據版本,分庫分表位等,值得花幾分鐘瞭解一下。

同時我也不建議在支付系統中使用雪花算法來生成業務 ID。

訂單號和業務 ID 本質都是標識一筆交易,以下統稱爲:業務 ID。

1. 什麼是業務 ID

數據庫一般都會設計一個自增 ID 做爲主鍵,同時還會設計一個能唯一標識一筆業務的 ID,這就是所謂的業務 ID(也稱業務鍵)。比如收單域有收單單號,支付域有支付號,渠道網關域有渠道支付號等,這些都屬於業務 ID。

爲什麼有了自增 ID 後,還需要有業務 ID 呢?一般來說有以下幾個核心原因:

  1. 分庫分表的強訴求。一旦分庫分表,各表之間的自增 ID 就一定會重複。

  2. 全球化部署的強訴求。在跨境支付系統建設時,部分國家地區要求本地化部署,需要通過業務 ID 知道業務運行在哪個機房。

  3. 標識業務語義,在處理故障時能快速定位是哪個域哪個業務。

  4. 方便系統升級。通過業務 ID 的版本所在位判斷業務應該走新系統,還是走老系統。

2. 爲什麼業務 ID 要統一規範

互聯網支付系統基本都是微服務化部署,每個子域都是相對獨立的一些同學在研發,架構實現差異非常大,但是業務 ID 是必須要統一的。主要有以下幾個原因:

  1. 減少維護成本。避免在不同服務中重複發明相似機制,也減少了溝通成本。方便做成統一的組件。

  2. 加速異常處理和診斷。在分佈式環境下發現和解決問題一般都比較複雜,統一的業務 ID 規範可以快速判斷問題所在的域,以及對應的業務。

  3. 避免新同學因經驗不足導致設計缺陷,在後期無法滿足業務訴求。

3. 常見業務 ID 生成規範及應用場景

業務 ID 生成規則有很多種,比如知名的 Snowflake 算法,UUID 算法,時間戳 + 隨機數 / 序列號等。以下是部分規範的簡要介紹。

  1. Snowflake 算法

組成:時間戳 + 數據中心標識 + 機器節點 + 序列號。

適用場景:無中心化的環境中生成大量的唯一 ID,無具體業務語義,且性能要求極高。比如社交媒體的聊天消息記錄。

  1. UUID 算法

高度唯一且隨機。

適用場景:不想讓外界感知內部系統的交易量級。比如調用外部渠道的請求號,如果使用序列號,有可能會讓外部猜測出交易的規模。

  1. 編碼系統

特定組織中心化生成。

適用場景:藥品或供應鏈管理,全球範圍內標識或追蹤商品。

  1. 業務規則編碼

把一些業務語義編碼到 ID 中。

適用場景:金融支付、電商訂單等。

4. 支付系統業務 ID 生成最佳實踐

4.1. 業務 ID 生成規範

下面以 32 位的支付系統業務 ID 生成爲例說明。實際應用時可靈活調整。

第 1-8 位:日期。通過單號一眼能看出是哪天的交易。

第 9 位:數據版本。用於單據號的升級。

第 10 位:系統版本。用於內部系統版本升級,尤其是不兼容升級的時候,老業務使用老的系統處理,新業務使用新系統處理。

第 11-13 位:系統標識碼。支付系統內部每個域分配一段,由各域自行再分配給內部系統。比如 010 是收單核心,012 是結算核心。

第 14-15 位:業務標識位。由各域內部定,比如 00-15 代表支付類業務,01 支付,02 預授權,03 請款等。

第 16-17 位:機房位。用於全球化部署。

第 18-19 位:用戶分庫位。支持百庫。

第 20-21 位:用戶分表位。支持百表。

第 22 位:預發生產標識位。比如 0 代表預發環境,1 代表生產環境。

第 23-24 位:預留。各域根據實際情況擴展使用。

第 24-32 位:序列號空間。一億規模,循環使用。一個機房一天一億筆是很大的規模了。如果不夠用,可以擴展到第 24 位,到十億規模。

4.2. 業務 ID 生成技術實現

序列號通常採用數據庫生成,保證機房內唯一性。

簡要流程如下:

  1. DB 初始化序列號數據。KEY 爲業務類型,VALUE 初始爲 0;

  2. 調用業務 ID 生成組件。核心傳參:數據版本號,系統版本號,系統名,業務類型等。

  3. 業務 ID 生成組件查看對應業務類型是否有緩存數據。如果沒有,就以指定步長(比如 100)去更新數據庫,然後緩存起來。

  4. 在內存中加一,然後根據規則生成業務 ID,返回給調用方。

這裏使用指定步長去更新數據庫,主要是考慮提高性能。但是存在一定的損失,比如發佈重啓,緩存中的序列號就會被浪費掉。但因爲是循環使用,所以基本上對業務沒有影響。

5. 內外區分

    建議把內部訂單號和外部訂單號做個區分。所謂外部訂單號主要指對客(包括個人用戶和商戶)的訂單號,這種場景下,可以考慮把業務類型做爲重點編織進到訂單號裏面。

    具體可以參考下面聊到的微信支付和支付寶對客訂單號。

6. 微信支付和支付寶對客訂單號的異同

    微信支付:

    有興趣的可以翻翻自己微信支付的訂單記錄,42000 開頭的是支付類的訂單,1000050001 開頭是轉賬類訂單,也就是微信支付把交易類型放在訂單的開頭。

    日期則放在交易類型的後面。

支付寶:

    也可以翻翻自己支付寶的訂單記錄,日期放在開頭,緊接着日期的就是交易類型,2000 代表轉賬,比如 202501012000xxxx。而 2300 或 2200 就是買東西的支付訂單。

7. 結束語

本文主要講了業務 ID 是什麼,業界常見生成規則及適用場景,以及支付系統業務 ID 生成的最佳實踐。

內容已收錄到《圖解支付系統設計與實現》。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/JHEcc9javbzvCaAUsme9Zw