圖解支付系統(tǒng)訂單號設計與最佳實踐

0 評論 1016 瀏覽 0 收藏 9 分鐘

本文主要講清楚支付系統(tǒng)訂單號(或業(yè)務ID)各種設計方案對比,各子域的訂單號(或業(yè)務ID)為什么要統(tǒng)一規(guī)范,以及最佳實踐。最后還會簡單分析微信支付和支付寶的對客訂單號的組成差異。

本文主要講清楚支付系統(tǒng)訂單號(或業(yè)務ID)各種設計方案對比,各子域的訂單號(或業(yè)務ID)為什么要統(tǒng)一規(guī)范,以及最佳實踐。最后還會簡單分析微信支付和支付寶的對客訂單號的組成差異。

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

同時我也不建議在支付系統(tǒng)中使用雪花算法來生成業(yè)務ID。

訂單號和業(yè)務ID本質都是標識一筆交易,以下統(tǒng)稱為:業(yè)務ID。

一、什么是業(yè)務ID

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

為什么有了自增ID后,還需要有業(yè)務ID呢?一般來說有以下幾個核心原因:

  • 分庫分表的強訴求。一旦分庫分表,各表之間的自增ID就一定會重復。
  • 全球化部署的強訴求。在跨境支付系統(tǒng)建設時,部分國家地區(qū)要求本地化部署,需要通過業(yè)務ID知道業(yè)務運行在哪個機房。
  • 標識業(yè)務語義,在處理故障時能快速定位是哪個域哪個業(yè)務。
  • 方便系統(tǒng)升級。通過業(yè)務ID的版本所在位判斷業(yè)務應該走新系統(tǒng),還是走老系統(tǒng)。

二、為什么業(yè)務ID要統(tǒng)一規(guī)范

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

減少維護成本。避免在不同服務中重復發(fā)明相似機制,也減少了溝通成本。方便做成統(tǒng)一的組件。

加速異常處理和診斷。在分布式環(huán)境下發(fā)現(xiàn)和解決問題一般都比較復雜,統(tǒng)一的業(yè)務ID規(guī)范可以快速判斷問題所在的域,以及對應的業(yè)務。

避免新同學因經驗不足導致設計缺陷,在后期無法滿足業(yè)務訴求。

三、常見業(yè)務ID生成規(guī)范及應用場景

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

Snowflake算法

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

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

UUID算法

高度唯一且隨機。

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

編碼系統(tǒng)

特定組織中心化生成。

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

業(yè)務規(guī)則編碼

把一些業(yè)務語義編碼到ID中。

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

四、支付系統(tǒng)業(yè)務ID生成最佳實踐

4.1. 業(yè)務ID生成規(guī)范

下面以32位的支付系統(tǒng)業(yè)務ID生成為例說明。實際應用時可靈活調整。

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

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

第10位:系統(tǒng)版本。用于內部系統(tǒng)版本升級,尤其是不兼容升級的時候,老業(yè)務使用老的系統(tǒng)處理,新業(yè)務使用新系統(tǒng)處理。

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

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

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

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

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

第22位:預發(fā)生產標識位。比如0代表預發(fā)環(huán)境,1代表生產環(huán)境。

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

第24-32位:序列號空間。一億規(guī)模,循環(huán)使用。一個機房一天一億筆是很大的規(guī)模了。如果不夠用,可以擴展到第24位,到十億規(guī)模。4.2. 業(yè)務ID生成技術實現(xiàn)

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

簡要流程如下:

  1. DB初始化序列號數據。KEY為業(yè)務類型,VALUE初始為0;
  2. 調用業(yè)務ID生成組件。核心傳參:數據版本號,系統(tǒng)版本號,系統(tǒng)名,業(yè)務類型等。
  3. 業(yè)務ID生成組件查看對應業(yè)務類型是否有緩存數據。如果沒有,就以指定步長(比如100)去更新數據庫,然后緩存起來。
  4. 在內存中加一,然后根據規(guī)則生成業(yè)務ID,返回給調用方。

這里使用指定步長去更新數據庫,主要是考慮提高性能。但是存在一定的損失,比如發(fā)布重啟,緩存中的序列號就會被浪費掉。但因為是循環(huán)使用,所以基本上對業(yè)務沒有影響。

五、內外區(qū)分

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

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

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

微信支付:

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

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

支付寶:

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

七、結束語

本文主要講了業(yè)務ID是什么,業(yè)界常見生成規(guī)則及適用場景,以及支付系統(tǒng)業(yè)務ID生成的最佳實踐。

本文由人人都是產品經理作者【隱墨星辰】,微信公眾號:【隱墨星辰】,原創(chuàng)/授權 發(fā)布于人人都是產品經理,未經許可,禁止轉載。

題圖來自Unsplash,基于 CC0 協(xié)議。

更多精彩內容,請關注人人都是產品經理微信公眾號或下載App
評論
評論請登錄
  1. 目前還沒評論,等你發(fā)揮!