這章在規劃裡叫「三本帳:庫存帳、訂單帳、金流帳」,本來要寫我們怎麼對帳。動筆前照慣例回去查證當年的實際做法,結果是:我們沒有做對帳。 系統裡沒有對帳排程、結束檔期不核帳、上線後也幾乎沒處理過錯帳。
一個處理真金白銀的系統,沒有對帳機制,帳卻幾乎沒錯過——這句話比任何對帳架構都值得解釋。答案分散在前面二十三天裡,這章把它們收束起來。
昨天給了第一層答案:冗餘壓到只剩一個,對帳就縮成一支重算排程。第二層答案:對帳這件事存在,只是不在系統裡——它在會計部門。

系統的責任止於匯出:把訂單按會計部門的要求整理出去。這其實是一個翻譯層——把工程師的事實表,翻譯成會計的語言。對帳的執行、判斷、修正,全部在人的世界裡進行:會計對出不一致,請 CTO 派工程師查原因;查完之後,修法看方向——少收,工程師調 DB 讓金額對上,公司內部吸收;多收,客服聯絡客人,退紅利點數或現金,對外補償。
這個不對稱很值得看一眼。少收是公司的損失,對客人沒有影響,所以安靜地在內部處理;多收動了客人的錢,所以走最貴的渠道(客服電話)、給最有誠意的補償。修帳的方向決定誰買單、用什麼貨幣付——這又是一次機制歸系統、政策歸人:系統提供事實,人決定正義。
而這一整套的實際戰績是:**上線後,幾乎沒印象處理過錯帳。**連結束檔期那個一次動幾千筆資料的大結算,都只做黑名單、清購物車、清未付款訂單——不核帳,照樣跑得意外地順。當年我們把這歸功於乖乖遵守 3NF;現在我可以講得更準:3NF 就是「同一個事實只存一份」的紀律,它在源頭掐死了漂移。
那重來一次,對帳還是什麼都不做嗎?不。「幾乎沒錯過帳」和「可以證明帳是對的」之間,有一條 Day 22 講過的縫:我們的安心是「習慣了沒出事」,不是「數字說沒事」。重來會補三件小事,全部順著現有結構長:
就這三件。沒有對帳中台、沒有每日全量核對——在一個冗餘只有一個的系統裡,蓋更大的對帳系統是在對抗不存在的敵人。
**最好的對帳,是讓帳沒有機會錯。**對帳需求與物化冗餘成正比——每多存一份派生數字,就多一本會漂的帳、多一支要寫的核對排程。把派生資料留在讀取端,是最便宜的一致性:它讓「對帳」這個詞從系統詞彙裡幾乎消失。我們當年不是對帳做得好,是把需要對帳的理由一個個設計掉了。
**「沒出事」不等於「證明沒事」。**這是 Day 22 的賒帳論在資料上的重演:我們的帳是乾淨的,但沒有任何量測能證明它乾淨——和風控那章「沒收到抱怨」是同一種沉默。設計紅利是真的,但紅利要配一張成績單;三條 invariant query 的成本,買的就是那張成績單。
這個系統教我最深的一課,是這章的標題反過來讀。「我們沒有做 X,為什麼沒出事」——把 X 換成對帳、換成狀態機、換成通知抽象層,前面二十三天反覆出現同一個結構:不做,是因為結構讓它不必做。工程的成熟不是把清單上的東西都蓋齊,是知道哪些東西你的結構已經免費送了、哪些必須親手補。拆開的資料庫攤在桌上,補得最成功的那一塊,恰恰是看起來什麼都沒做的地方。
明天換個小而美的題目:圖片。上傳只要一個下午,刪除是一輩子的事。
本文改寫自我的部落格系列《Re:從零開始做直播代購電商平台》,本篇完整版:https://blog.aidan.tw/blog/rezero-reconciliation/