← 全部概念地圖
標準

概念地圖・交易式 Outbox

分類:系統

這一頁不只是把一個概念解釋一遍——一張自己畫的結構圖,加上拿台灣情境從頭走一次的實例演練、這個框架什麼時候會騙你,以及它接回 P.A.I.N. 之後長什麼樣。一頁必須交付的三層 →

交易式 Outbox:資料與通知一起成立

清運車回場,司機把作業紀錄寫進系統,同一個動作也在待申報清單上留了一行。要等那一行真的送進主管機關的申報系統,這一趟才算結束。麻煩的是,資料庫寫入與訊息送出分屬兩套東西,中間沒有人保證它們同進退——帳上這趟活做完了,該讓別人知道的那一半卻卡在半路。交易式 Outbox 的做法很土:把「要通知誰」也寫成一張表的一行,跟業務資料塞進同一筆交易,再派一支轉送器把那些行讀出來送走。

交易式 Outbox:業務資料與待送事件寫在同一筆交易,再由轉送器送出去 左側金色虛線框是同一筆資料庫交易,框裡並排業務資料表與待送事件表,框下註明這兩張一起成立,或者一起不成立。框右邊的轉送器每 5 秒掃一次,一支朱紅箭頭把待送那一行讀走,一支綠色箭頭回頭把它標成已送,再往右推進申報訊息系統。系統下方註明同一件事可能被送兩次,一支朱紅箭頭往下指到下游,下游用清運聯單編號比對,同一編號只認一次。左下角三行數字對照有無這一層的漏送比例。 業務資料與待送事件,寫在同一筆交易裡 同一筆資料庫交易 業務資料表 清運作業紀錄 車號・噸數 回場時間 待送事件表 申報訊息一行 狀態:待送 送出後改已送 這兩張一起成立,或者一起不成立 讀走待送那一行 回頭標成已送 轉送器 每 5 秒掃一次 待送清單 推出去 申報訊息系統 主管機關那一端 同一件事可能被送兩次 重送在這裡是常態 下游:申報接收端 比對清運聯單編號 同一編號只認一次 一天 42 趟清運回場,一個月 1260 趟 沒有這一層:3 趟寫成功卻沒送出,0.24% 有這一層:9 趟被重送,0.71%,下游擋掉
交易只圈得住框裡那兩張表;出了框,靠的是轉送器一行一行送,以及下游願不願意比對編號。

同一筆交易裡,兩張表各放什麼

這張圖真正的機關,全在左邊那個框裡的分工。兩張表寫進同一筆交易,性質卻完全不同。

問題業務資料表待送事件表
放什麼這趟清運真的發生了什麼該讓誰知道的那一則訊息
誰在讀你自己的系統、報表、對帳只有轉送器,讀完就不再回來
什麼時候寫司機回場按下送出同一筆交易、同一個瞬間
交易失敗了整趟紀錄回滾,等於沒寫一起回滾,通知不會憑空冒出來
事後會變嗎幾乎不再動狀態從待送翻成已送,翻之前重啟就會重送
會長大嗎照業務量長,本來就該長沒有清理機制,它會變成第二張要維護的表

讀完這張表會發現,交易式 Outbox 沒有變出任何新的保證——它只是把「訊息送不送得出去」這個賭注,從網路那一端搬回到資料庫這一端。資料庫本來就會替你守住一筆交易的全有全無,那就把要通知的事,也塞進那個守得住的範圍裡。至於出了框之後的事,圖右半邊那三個箭頭都得靠工程自己扛。

你這條流程需不需要這一層

多養一張表、多顧一支背景程式,值不值得,要看流程長什麼樣。底下四個自問,都是站在截油槽清運那個場景裡問的。

一、回場之後,還有沒有第二個動作。清運車進場、過磅、噸數寫進系統,這趟活在你自己的帳上已經結案。但主管機關那一端還沒收到任何東西——這趟活的「完成」,有一半握在別人手上。自問:這件事做完的定義,會不會有一半在我的資料庫外面?

二、那個收件人,進不進得了同一筆交易。申報系統是別人的機器,你沒辦法把它拉進你的交易裡。但你可以把「要對它說的話」寫成自己資料庫的一行——這一步,就是整個做法的全部發明。自問:我能不能把要通知的內容,先變成一筆自己寫得起的資料?

三、漏掉那一趟,你多久會發現。一天 42 趟回場、一個月 1260 趟,其中 3 趟寫成功卻沒送出,比例只有 0.24%。看起來像雜訊,但那 3 趟很少在當天現形——多半要等稽查通知寄到,中間隔了幾個月。自問:今天有一趟沒申報成功,我是幾分鐘後知道,還是等別人來告訴我?

四、下游認不認得同一張聯單。轉送器保證的是「至少送到一次」,順帶保證了「有時候會送兩次」。如果申報端把同一個聯單編號收兩遍就長出兩筆紀錄,你等於用一種錯換掉另一種錯。自問:同一個編號連送三次進去,對方會產生三筆,還是一筆?

一趟清運的回場流程,兩張表各填一次

底下這家台灣中部的截油槽清運業者,是為了把這個結構講清楚而編出來的示意情境,沒有指涉任何真實公司。

實例演練
  • 下午四點十分,回場過磅:司機在車機上按送出,車號、清運起訖時間、噸數寫進業務資料表。這一步從來沒出過問題,它就在自己的資料庫裡
  • 同一筆交易,多寫一行:待送事件表多出一行,帶著清運聯單編號、廢棄物代碼與這一車的噸數,狀態欄寫「待送」。兩張表要嘛一起進去,要嘛一起不進去
  • 轉送器每 5 秒撈一次:背景程式把狀態是待送的那些行讀出來,一行一行推進申報系統。車機當機、司機關掉 App,都影響不到這一步
  • 送出去之後,回頭改狀態:申報系統回應成功,轉送器把那一行標成已送。標記之前服務被重啟,這一行下一輪還會再送一次
  • 下游用聯單編號比對:申報端收到同一個編號的第二次,直接丟掉。重送從災難降級成噪音,就是靠這一步
  • 三十天後清掉已送的行:排一支例行工作,把標成已送滿三十天的行搬去封存。沒人排這件事,半年後它會比業務資料表還大

整條流程真正值得記住的接縫,在第二步跟第四步中間那段空白。第二步結束的那一瞬間,這趟清運已經「一定會被申報」——因為那一行躺在自己的資料庫裡,重啟、斷網、機房跳電都拿它沒辦法。但第四步之前,它同時也「一定可能被申報兩次」。這家業者上線後量了一個月:漏送從 3 趟變成 0,重送則出現 9 趟,1260 趟裡佔 0.71%。九趟重複的申報,靠下游比對聯單編號全數擋下,沒有一筆變成重複申報紀錄。他們換掉的東西很明確——把「有幾趟永遠不會被發現」的風險,換成「有幾趟會吵一下、但看得見」的風險。以上為說明結構用的示意情境,僅供理解框架之用。

這一層裝上去之後,還有三種漏法

  1. 同一件事會被送兩次,這是設計上的正常結果。轉送器推完訊息、還沒把那一行標成已送就重啟,下一輪自然會再撈到它。實測一個月約 9 趟被重送,1260 趟裡的 0.71%——比原本 0.24% 的漏送還高。差別在於重送吵得出聲音、漏送安安靜靜。所以下游一定要能用清運聯單編號認出重複;下游做不到,這一層就只是把問題換了個地方擺。
  2. 送出去這件事,永遠慢一拍。最壞情況是掃描間隔的 5 秒,加上申報系統自己的回應時間。平常沒差,但只要有人在畫面上按了送出、然後盯著看「對方收到了沒」,這幾秒就會變成客訴。把掃描調到 1 秒也治不好——那只是把等待從 5 秒縮到 1 秒,卻讓資料庫多吃五倍的查詢。真正該做的是把介面上那句話改成「已排入申報」。
  3. 待送清單自己會長大。沒有清理機制的話,它會變成第二個要維護的資料表:索引要顧、備份要算它的體積、狀態欄查詢會越來越慢。一天 42 行看不出來,一年一萬五千行也還好,三年之後那張表比業務資料表更常出現在慢查詢清單上。上線那天就要一併排好封存的例行工作,別等它先痛一次。

那份沒送出去的申報,最後誰在賠

痛點視角

這張圖上最貴的一格,其實在畫布外面。

技術上的損失小得可憐——1260 趟裡漏 3 趟,任何工程師都能說服自己那是可接受的誤差。但把那 3 趟攤在客戶面前,長相完全不同:稽查通知寄到某家餐廳,餐廳翻出清運單據,發現清運公司三個月前那一車沒有對應的申報紀錄。餐廳老闆不會去理解什麼叫交易邊界,他理解的是「我付了錢,你沒做完」。這張圖畫得出訊息有沒有離開你的機房,畫不出那位老闆掛掉電話之後,把你歸到哪一類的清運廠商。P.A.I.N. 的第一個字是「誰在痛」——這條流程裡痛的人從來不是你的資料庫,是那個要拿紀錄去應付稽查的人。今晚花十分鐘,翻出上個月被退件或補件的每一件,逐件標一個原因代號:是資料填錯,還是根本沒送到。這兩堆的比例,會直接告訴你該不該多養一張表。

關於交易式 Outbox,常見問題

跟直接在程式裡先寫資料庫、再呼叫申報 API,差在哪裡?

差在中間那個縫。先寫資料庫、再呼叫 API,兩個動作之間有一段沒有人守著的空檔——服務在這裡重啟,或網路在這裡斷掉,資料就進去了、訊息卻永遠不會送。交易式 Outbox 把訊息也變成一次資料庫寫入,塞進同一筆交易,於是那段空檔被搬到「已經確定要送」之後。轉送器就算掛掉,那一行仍然躺在待送清單裡等著;它復活之後接著撈就好。

一定要另外開一張表嗎?直接讀資料庫的變更紀錄不行嗎?

讀變更紀錄(CDC)當然可行,而且省掉一張表。代價是你送出去的訊息長得跟資料表的欄位一模一樣——欄位改名、加一欄、拆一張表,下游全部要跟著改。另外開一張待送事件表,等於自己決定「要對外說什麼」,內部結構怎麼翻都不會波及外面。小系統用變更紀錄比較快;跨部門、跨公司要對接的訊息,多養那張表通常換得回來。

轉送器多久掃一次比較合理?

先問「晚幾秒會有人抱怨嗎」。像清運回場申報這種當天結算的事,5 秒綽綽有餘,甚至 30 秒都沒人察覺。掃描間隔縮短一半,資料庫的查詢量就翻倍,而換來的只是使用者感覺不到的幾秒。比較划算的做法是保留固定間隔當保險,再讓寫入端在交易提交後順手戳轉送器一下——平常靠戳的走得快,戳失敗了還有定時掃描兜底。

下游沒辦法去重,怎麼辦?

那就把去重搬到自己這一側,效果打折但堪用:在轉送器與下游之間放一張已送編號表,送出前先查一次。這只能擋掉大部分,因為「查完到寫入」之間仍然有縫。真正乾淨的解法還是請下游把聯單編號當成唯一鍵。談不動的時候,退一步的做法是每天跑一次對帳,把自己送出的編號跟對方回傳的清單比一遍,重複的手動註銷——麻煩,但至少看得見。

圈出你那條流程裡「先做完、再通知」的地方,就知道哪幾個縫需要這張待送清單。往下走還有兩條相關的路:下游來不及消化時要怎麼往上游喊停,可以看背壓與流量控制;一份單據沿著一站一站被押著走、每站都要留下憑證的結構,則在信用狀流程那張圖上畫得更完整。

發現引用或事實有誤?請寫信回報,我會依更正政策修正。