01

當應用程式變成「資料處理中心」

從「算得快」到「把資料管好」——先認識五塊積木,再看見貫穿全書的三支柱

過去比「誰算得快」,現在比「誰把資料管得好」

你可能覺得電腦這麼快,還有什麼難得倒它?過去很多程式的瓶頸確實是 運算密集型 ——只要 CPU 夠猛就好。

但網路普及、資料爆炸之後,今天大多數應用更像 資料密集型 ——它不是計算機,而是一座「資料處理中心」。挑戰從「算得快」變成三道難題:

資料量 Volume

要存、要處理的資料「多不多」?從 MB 到 PB,規模前所未有。

資料複雜度 Complexity

資料「長什麼樣」?不只是表格,還有圖片、影片、社交關係,盤根錯節。

變化速度 Speed of change

資料「跑得多快」?產生、更新、讀取飛快,系統得即時回應。

🍱
先給你一個畫面

傳統餐廳拼的是廚師手藝(CPU);現代外送平台拼的是——同時管好幾百萬筆訂單、幾十萬份菜單、幾萬個外送員位置即時更新。後者要的不是「更快的廚師」,而是一整套協調資料的系統。

直接讀原文,旁邊就是白話

這是一本英文書。我們把它最關鍵的開場,左邊放 原文、右邊放白話中文,一句對一句——你既看得懂,也順手練了原文。

原文 · DDIA Ch.1 “The Internet was done so well that most people think of it as a natural resource like the Pacific Ocean, rather than something that was man-made.” — Alan Kay (2012) Many applications today are data-intensive, as opposed to compute-intensive. Raw CPU power is rarely a limiting factor — bigger problems are usually the amount of data, the complexity of data, and the speed at which it is changing. A data-intensive application is typically built from standard building blocks that provide commonly needed functionality.
白話翻譯

「網際網路做得太成功,多數人把它當成像太平洋一樣的自然資源——忘了它其實是人造的。」

弦外之音:好系統「理所當然」的背後,是大量刻意的設計。這正是本書要拆給你看的東西。

今天大多數應用是「資料密集型」,而不是「運算密集型」。

CPU 算力很少是瓶頸——真正的難題是資料的「量」、「複雜度」,還有它「變化的速度」。

而這種應用,通常是用一組標準的「建構塊」組裝出來的。

💡
這就是「融合」的關鍵招

程式碼教學的「程式碼 ↔ 白話」並排,搬到一本雙語書上,剛好變成「英文原文 ↔ 白話中文」——同一個元件,用在書上甚至更貼。

五塊積木:資料系統的標準零件

幾乎每個資料密集型應用,都是把下面這五塊積木挑著組起來的。像玩樂高——每塊各司其職。

🗄️
資料庫 Database

把資料持久存起來,之後(自己或別的程式)還找得回來。系統的「核心資產」。

快取 Cache

把「算過、常用」的結果先存起來,下次直接拿,不必重算或回頭翻資料庫。

🔍
搜尋索引 Search index

像書本目錄——靠關鍵字或條件快速找到資料,不必把整批掃過一遍。

📨
串流/訊息佇列 Stream

把訊息丟進佇列,另一端慢慢非同步處理;發送方不必等,服務彼此解耦。

📊
批次處理 Batch

定期把一大批累積資料一次處理完,例如每天半夜跑報表、做分析。

🧩
界線正在變模糊

Redis 既能當快取也能當訊息佇列;Kafka 既是訊息佇列又有資料庫般的持久性。所以選工具別只看「分類」,要看它實際提供什麼能力——靠的是抽象化,你只管用它的介面。

動手配配看:哪塊積木解哪個問題?

把上面的積木,拖到它最該負責的任務上。配完按「對答案」。

資料庫
快取
搜尋索引
訊息佇列
批次處理
使用者輸入書名,要在數百萬本書中「極速找到」結果
拖到這裡
下單成功後,要通知庫存、寄信、排出貨——但不能卡住結帳頁面
拖到這裡
每月初彙總上月全球銷售,計算量大、但不必即時
拖到這裡
首頁熱門商品每秒被讀爆,想避免每次都打資料庫
拖到這裡
訂單與用戶資料必須長期保存、隨時讀寫
拖到這裡

貫穿全書的「黃金三角」

把積木組起來,你就從「應用程式開發者」升級成「資料系統設計師」。而衡量一個好系統,整本書反覆回到三個字——點點看每一根支柱:

資料系統的三支柱
🛡️ 可靠性 Reliability
📈 可擴展性 Scalability
🔧 可維護性 Maintainability
可靠性(Reliability):就算硬體壞、程式有 bug、人操作出錯,系統仍能持續正確運作。目標不是「零故障」,而是讓『故障 fault』不要變成『失效 failure』。→ 模組 2 細講。
🔗
三支柱會互相拉扯

它們不是各自獨立的。為了可擴展性硬塞一堆分散式機制,可能讓系統更難懂,反而傷了可維護性——設計永遠在權衡。

小試身手

看懂這一格,你就抓到本章的骨架了。來兩題:

為什麼現代應用常要把多種資料工具「複合」起來,而不是只用一個資料庫?
工程師一開口就問「我們要用 PostgreSQL 還是 MongoDB?」,他最該先做什麼?
🛡️
下一站:可靠性

三支柱第一根。我們先搞懂一個最常被搞混的分別——「故障 fault」到底跟「失效 failure」差在哪?往下捲。

02

可靠性:讓「故障」不等於「失效」

三支柱第一根——零件總會壞,目標不是「永不出錯」,而是壞了一塊也撐得住

先分清楚:故障 ≠ 失效

這是整章最常被搞混、卻最關鍵的一對詞。用「煮飯」想就懂了:電鍋插頭鬆了,是電鍋這個「元件」出的小問題——這叫 故障 Fault; 結果全家沒飯吃,是整套「煮飯系統」對人停止服務——這才叫 失效 Failure

故障 Fault|原因

系統「內部某個元件」偏離規格:硬碟壞、記憶體秀逗、程式有 bug。範疇是局部,工程師才看得到。

失效 Failure|結果

整個「系統對使用者」停止提供服務:網站打不開、訂單送不出。範疇是整體,使用者直接感受到。

容錯 Fault-tolerance|橋樑

預期故障一定會發生,事先準備應對策略,讓「故障」不要演變成「失效」。這就是可靠性的真正目標。

🛡️
一句話記住它

故障是「原因」,失效是「結果」。我們的目標不是「永不故障」——那幾乎不可能——而是設計出 容錯 機制,讓壞掉一塊也不至於整個垮掉。

直接讀原文,旁邊就是白話

這段是書裡對「故障 vs 失效」下定義的原句。左邊 原文、右邊白話中文,一句對一句——讀懂定義,順手練原文。

原文 · DDIA Ch.1 The things that can go wrong are called faults, and systems that anticipate faults and can cope with them are called fault-tolerant or resilient. Note that a fault is not the same as a failure. A fault is usually defined as one component of the system deviating from its spec, whereas a failure is when the system as a whole stops providing the required service to the user. It is impossible to reduce the probability of a fault to zero; therefore it is usually best to design fault-tolerance mechanisms that prevent faults from causing failures. In this book we cover several techniques for building reliable systems from unreliable parts.
白話翻譯

那些「會出錯的事」就叫故障(fault);能預先料到故障、又有辦法應付它的系統,就叫「容錯(fault-tolerant)」或「有彈性(resilient)」。

注意:故障(fault)跟失效(failure)不是同一回事。

故障,通常指系統「某一個元件」偏離了它該有的規格;而失效,是整個系統「對使用者」停止提供該有的服務。

你不可能把故障機率壓到零,所以最好的做法是——設計容錯機制,攔住故障,別讓它一路滾成失效。

而這整本書,就是要教你怎麼用「不可靠的零件」,組出「可靠的系統」。

💡
最後那句是全章的精神

「用不可靠的零件,組出可靠的系統。」——這不是雞湯,而是接下來三節(硬體、軟體、人為)一以貫之的設計哲學。

跑給你看:故障發生,使用者卻完全無感

下面有五位「演員」。按「下一步」,看主硬碟突然壞掉時,容錯機制怎麼悄悄把流量切到備援、讓使用者根本沒發現。

🙂
使用者
⚙️
服務
💽
主硬碟
💽
備援硬碟
📟
監控
按「下一步」開始
🔁
這招叫「冗餘 Redundancy」

準備多份備份,一個壞了立刻替補——資料庫主從複製、雙電源供應器、RAID 磁碟陣列都是它的化身。 冗餘 聽起來像「多餘」,但在關鍵時刻能救命。

故障從哪來?三大來源

要防故障,得先知道它躲在哪。書把故障來源分成三類,性質完全不同,對策也不一樣。

💽
硬體故障 Hardware

硬碟壞、記憶體故障、停電、網路線鬆脫。通常隨機且彼此獨立——但資料中心若有上萬顆硬碟,「平均每天壞一顆」就是日常。

🐛
軟體錯誤 Software

程式 bug、失控程序吃光資源、依賴的服務變慢、連鎖反應。它是「系統性錯誤」——特定條件才觸發,一觸發就同時打趴一大片相同程式碼。

🧑‍💻
人為錯誤 Human

設定檔貼錯、誤刪資料庫、部署出包。研究顯示人為失誤才是大型服務中斷的「頭號元凶」——硬體故障只佔 10–25%。

⚠️
最難纏的是「軟體錯誤」與「人為錯誤」

硬體壞了通常只影響一台;但一個 系統性錯誤 或一次配置失誤,可能瞬間放倒成百上千台。小心 級聯失效——一張骨牌倒,全部跟著倒。

動手配配看:哪種故障,配哪種對策?

三種故障來源各有最對症的防禦。把左邊的故障,拖到右邊它該用的對策上。配完按「對答案」。

硬體故障
軟體錯誤
人為錯誤
硬碟、電源這類實體零件總會壞——多備一份,壞了立刻替補
對策:硬體冗餘(RAID、雙電源、主從複製)
藏在特定條件才爆發的程式邏輯問題,會一次打趴一大片
對策:嚴謹測試 + 監控 + 程序隔離
設定貼錯、誤刪資料——人總會出包,得讓「做錯」變得很難
對策:好用介面 + 沙盒環境 + 快速回溯
🐒
反直覺的一招:混沌工程

Netflix 的「混沌猴子(Chaos Monkey)」會在正式環境隨機關掉伺服器。為什麼?因為很多容錯機制平時在「沉睡」,只有真故障才會被觸發—— 混沌工程 主動製造故障,才能確認它們真的有效。

從「單機備胎」到「整台機器壞了也不怕」

應對硬體故障的思維,正在經歷一場轉變。用披薩店想最直覺:

傳統:硬體冗餘(單店備胎)

同一家店多買幾套設備——兩台烤箱、外送車備胎、兩位師傅。專注「讓單一台機器盡量不中斷」。機器一多,這招就不夠了。

現代:軟體容錯(開分店)

把服務分散到多台機器。一整家分店停電關門,訂單自動轉給其他分店,客戶吃得到熱披薩、完全不知情。重點變成「讓整個系統即使有機器掛掉也能繼續運作」。

🔄
附帶的大禮:滾動升級

有了 軟體容錯,你可以分批更新——一次只重啟一小部分伺服器,其他照常服務。這叫 滾動升級(Rolling Upgrade), 像火車行進中一節節車廂輪流進站維護,整列車從不停下。

小試身手

抓到「故障 ≠ 失效」與「為何要容錯」這兩件事,這一節就通了。來兩題:

某購物網站促銷時後端連線池耗盡,顧客頁面一直轉圈、最後收到「交易失敗」。哪個說法最能區分這裡的「故障」與「失效」?
設計一個「容錯」系統,最核心的理念是什麼?
📈
下一站:可擴展性

系統撐得住、不失效之後,下一個問題是——使用者暴增十倍,它還跑得動嗎?下一站我們談「可擴展性 Scalability」。往下捲。

03

可擴展性:從一個人用到一百萬人

先量出系統的「飯量」,再學會看「最慢的那群人」過得好不好——最後決定:把一台機器養肥,還是多找幾台分工

先別急著喊「可擴展」,先量出你的系統有多忙

很多人喜歡幫系統貼個標籤:「我們很可擴展」。但這句話其實沒什麼意義—— 可擴展性 不是一個是非題,而是一個問句:「如果負載這樣長大,我們有哪些應對的選項?

要回答這個問句,第一步得先把系統現在的 負載 講清楚。就像醫生看病前要先量血壓、測心跳——我們用一組數字來描述系統的壓力,這組數字叫 負載參數

🌐
網站伺服器

每秒處理多少個請求?(requests per second)

🗄️
資料庫

讀取多還是寫入多?這就是讀寫比

💬
聊天室

同時有多少人在線上活躍?(concurrent users)

快取系統

資料命中率有多高?(cache hit rate)

📈
平均值會騙人——盯緊尖峰

一個交通監測系統,只看全天平均車流量會覺得很順暢;可是它在上下班尖峰時刻當機,影響就大了。所以除了平均負載,更要看 尖峰負載(Peak Load)——那才是真正考驗系統極限的時刻。

直接讀原文,旁邊就是白話

這是一本英文書。我們把它談「可擴展性/負載」最關鍵的幾句,左邊放 原文、右邊放白話中文,一句對一句——你既看得懂,也順手練了原文。

原文 · DDIA Ch.1 Scalability is the term we use to describe a system's ability to cope with increased load. It is not a one-dimensional label that we can attach to a system: it is meaningless to say “X is scalable” or “Y doesn't scale.” Rather, discussing scalability means considering questions like “If the system grows in a particular way, what are our options for coping with the growth?” Load can be described with a few numbers which we call load parameters. Perhaps the average case is what matters for you, or perhaps your bottleneck is dominated by a small number of extreme cases.
白話翻譯

可擴展性,是我們用來描述「系統應對負載增加的能力」的詞。

它不是一個能往系統上一貼的單一維度標籤——光說「X 可擴展」或「Y 不可擴展」其實沒有意義。

真正在談可擴展性,是在問這種問題:「如果系統以某種方式長大,我們有哪些應對成長的選項?」

負載,可以用一組數字來描述,我們把這組數字叫做「負載參數」。

也許你在意的是平均情況;也許你的瓶頸,是被一小撮極端案例給主宰的。

💡
記住這句反問

下次有人說「我們要做可擴展的系統」,你可以接一句:「好——如果負載長大十倍,我們具體要怎麼辦?」這一問,才是設計真正開始的地方。

招牌案例:Twitter 的「扇出 Fan-out」

書中用 Twitter(2012 年的數據)當經典範例。它有兩個主要操作:發推文,和看首頁時間軸(你追蹤的人發的推文,依時間排好)。問題來了——這兩件事該怎麼設計?

最初 Twitter 用「讀取時即時聚合」:你一打開首頁,系統才現去查你追蹤的所有人、把他們的推文合併排序。發推文很輕鬆,但看首頁慢到爆——因為讀取量是寫入量的近百倍。於是改成下面這招:發推文時,就先把它「扇出」寫進每個追蹤者的首頁快取。按「下一步」看它怎麼跑。

✍️
發文者(名人)
⚙️
貼文服務
📥
追蹤者快取 A
📥
追蹤者快取 B
📥
追蹤者快取 C
按「下一步」開始這趟扇出之旅
🔁
核心心法:寫入時多做一點,換讀取時超快

把工作從「讀取那一刻」搬到「寫入那一刻」。代價是發推文變貴:平均一則推文要送給約 75 位追蹤者,4.6k 則/秒就變成 345k 次/秒的首頁快取寫入。

🌪️
負載參數登場:追蹤者數量決定「扇出」壓力

追蹤者數量分佈差異極大。有些名人超過 3,000 萬追蹤者——一則推文就可能引發超過 3,000 萬次寫入,而且 Twitter 還想在五秒內送達!所以後來改用「扇出混合策略」:一般人照樣扇出寫快取,名人則例外——他們的推文等你讀首頁時才現抓、現合併(回到方法一)。

「快」怎麼量?別再只看平均值

描述完負載,接著要描述效能。先分清楚兩個詞: 響應時間 是用戶從按下到拿到結果的「總時間」; 延遲 則是請求在系統裡「等待被處理」的那段時間。

那「平均響應時間」呢?它就像「平均身高」——會把極端值平均掉、騙過你。平均 200 毫秒看起來很快,可能藏著一群等 10 秒的倒霉用戶。所以高手改看 百分位數

P50
中位數 Median

一半的請求比它快、一半比它慢。代表「典型用戶」的體驗,比平均值可靠多了。

P95
95% 都比它快

反過來說,有 5% 的請求比這個時間還慢。開始看見那群不開心的人。

P99
最慢的 1%

99% 都比它快,剩下 1% 更慢。這些高百分位數就是 尾部延遲

💰
為什麼要為那 1% 操心?

因為最慢的請求,常常來自帳戶資料最多的用戶——也就是買最多、最有價值的大戶。亞馬遜發現:響應時間慢 100 毫秒,銷售額就少 1%。讓最慢的那群人不開心,就是讓錢包不開心。

更麻煩的是尾部延遲放大(Tail Latency Amplification):當一個頁面要同時呼叫好幾個後端服務來組裝,就算每個服務各自的 p99 都很漂亮,只要其中任何一個落入它那 1% 的慢,整個請求就被拖慢。服務越多,踩到至少一個慢請求的機率就越高。這就像點一份套餐,只要沙拉那攤忙了,你整桌都得等。

應對負載的兩條路:向上 vs 向外

負載長大、瓶頸出現,怎麼辦?書上說這常被講成一個二選一:

🦸
向上擴展 Scaling Up(垂直)

換一台更強的機器。像把一個廚師練成料理鐵人。簡單、改動少、見效快;但有物理上限、高階硬體貴、且是單點故障。

🦸‍♂️
向外擴展 Scaling Out(水平)

把負載分散到多台較小的機器。像開連鎖分店、找店長(負載平衡器)分流客人。彈性近乎無限、硬體便宜、單台壞了不全停;但管理複雜、要處理資料一致性、程式可能得重構。

🧩
把負載分散開,就叫「無共享架構」

向外擴展常採用 無共享架構(Shared-Nothing)——每台機器各管各的,靠網路溝通。但現實裡好的架構通常是務實的混搭:用幾台還算強的機器,往往比一大堆小虛擬機更簡單也更便宜。沒有所謂的「神奇擴展銀彈」(magic scaling sauce)。

動手分分看:下面每個情境,比較適合「向上」還是「向外」?把標籤拖過去,配完按「對答案」。

向上擴展
向外擴展
彈性系統
手動擴展
流量暫時暴衝、預算有限,想最快見效又幾乎不改程式
拖到這裡
業務長期成長、單機已碰天花板,且不能容忍單點故障
拖到這裡
客流量無法預測,希望負載一漲就自動加機器、一降就自動收
拖到這裡
流量變化規律、想避免意外,由人判斷何時加機器
拖到這裡

小試身手

抓到「負載、尾部延遲、擴展策略」這三件事,這一章的骨架就在你手上了。來兩題:

Twitter 改用「推播到快取」後,名人發一則推文要複製數千萬次推播。這個挑戰叫什麼?又壓在哪一端?
某電商平均響應時間 200 毫秒看似很好,用戶卻抱怨高峰卡頓。哪種分析最能揭露真實瓶頸?
🔧
下一站:可維護性

系統可靠又能擴展之後,最後一根支柱是——三年後接手的人,會詛咒你還是感謝你?我們去看軟體成本最大的那一塊:上線之後的維護。往下捲。

04

可維護性:讓程式碼成為團隊的資產

軟體最大的花費不在「寫出來」,而在「養下去」——用三大設計原則,讓系統老得慢一點、優雅一點

寫完不是結束,是帳單的開始

很多人以為程式碼寫完、上線就萬事大吉。本書開宗明義就戳破這個幻覺:絕大部分的軟體成本,不在最初的開發,而在它之後的 持續維護 ——修 bug、保持運作、調查故障、適應新平台、改成新需求、償還技術債、再加新功能。

蓋房子 = 初始開發

選地、翻土、種下第一批種子,興高采烈。這只是最初的一筆投入。

長年修繕 = 持續維護

之後每天澆水、除草、驅蟲、改建——長期、持續、才是真正的大工程。

沒養好 = 遺留菜園

雜草叢生、病蟲害肆虐,最後變成沒人想靠近的一團亂麻。

🏚️
什麼是「遺留系統」?

當一個系統因為缺乏文件、設計不良、技術過時,或歷經太多不同的人之手,變得難以理解、修改與維護,它就成了 遺留系統(Legacy System)。 書上一句經典:「每個遺留系統都以自己獨特的方式令人不快。」我們無法完全避免系統變老,卻能從第一天就用好設計,盡量減少未來的痛苦。

直接讀原文,旁邊就是白話

這一段是本章對「可維護性」最直球的定義。左邊原文、右邊白話,一句對一句——你既看得懂,也順手練了原文。

原文 · DDIA Ch.1 It is well known that the majority of the cost of software is not in its initial development, but in its ongoing maintenance. …fixing bugs, keeping its systems operational, investigating failures, adapting it to new platforms, repaying technical debt, and adding new features. Every legacy system is unpleasant in its own way, and so it is difficult to give general recommendations for dealing with them. However, we can and should design software in such a way that it will hopefully minimize pain during maintenance, and thus avoid creating legacy software ourselves. To this end, we will pay particular attention to three design principles: operability, simplicity, and evolvability.
白話翻譯

眾所周知,軟體的絕大部分成本,不在最初的開發,而在它之後的持續維護。

……修 bug、保持系統運作、調查故障、適應新平台、償還技術債,還有新增功能。

每個遺留系統都以自己獨特的方式令人不快,所以很難給出對付它們的通用建議。

但我們可以、也應該這樣設計軟體:讓維護時的痛苦降到最低,從而避免親手製造出遺留系統。

為此,我們會特別關注三個設計原則——可操作性、簡潔性、可演進性。

🧬
把這三點刻進 DNA

軟體想要「活得久、活得好」,就要把這三個原則從設計的第一天起就放進骨子裡:讓系統好顧、好懂、好改。下一格,點點看它們各是什麼。

招牌互動:可維護性的三大設計原則

可維護性不是一句口號,而是落在三根具體的支柱上。點每一根,看它到底在解什麼問題:

可維護性的三大設計原則
🛠️ 可操作性 Operability
簡潔性 Simplicity
🌱 可演進性 Evolvability
可操作性 Operability:讓系統「好顧」。讓維運團隊(負責讓系統跑起來、保持穩定的人)能輕鬆監控、管理、排查問題。書上點出:好的維運常能彌補糟糕的軟體,但好的軟體無法在糟糕的維運下穩定運行。設計重點:高可視性、擁抱自動化、不依賴單一機器(可滾動升級)、良好文件、合理預設又能客製、行為可預測。
🍕
用披薩外送車隊想像「可操作性」

每台機車有 GPS、電量、健康儀表板,中央大螢幕一覽無遺(可視性);備用車充足,一台拋錨立刻補上,技師能一次只保養幾台而不中斷配送(這就是 滾動升級 Rolling Upgrade)。 這就是把系統設計得「好顧」。

複雜度有兩種——一種非有不可,一種純屬自找

三大原則裡,「簡潔性」最容易被誤會。它不是要你砍功能,而是要你分清楚兩種複雜度,然後把那種「自找的」清掉。

🧱
本質複雜度 Inherent

問題本身固有的困難,來自使用者需求。例如多國語言支付系統要處理各種貨幣與稅務規則——無論你怎麼寫都跑不掉。無法完全避免,但可用好設計來管理、簡化。

🌀
偶然複雜度 Accidental

不是問題本身固有的,而是因實作方式不當才額外冒出來的負擔:命名混亂、模組緊密耦合、纏繞的依賴、為效能塞的「偏方」。本來可以避免——這正是我們要努力消除的。

書上把 偶然複雜度(accidental complexity) 定義得很乾脆:如果一個複雜度「不是軟體要解的問題本身固有的(從使用者角度看),而只是從實作冒出來的」,它就是偶然的。那要怎麼清掉它?

🎛️
抽象化:移除偶然複雜度最好的工具

書上原話:「對抗偶然複雜度,我們最好的工具之一就是 抽象化(abstraction)。」 一個好的抽象,能把一大堆實作細節藏在乾淨好懂的介面後面——高階程式語言把機器碼藏起來、SQL 把磁碟上的資料結構藏起來。好抽象還能被重複使用,而且因為被很多地方用,它的品質會被打磨得更高。只是在分散式系統裡,要找到好抽象非常難——這正是全書持續追尋的目標。

動手配配看:哪個做法服務哪根支柱?

把下面這些常見做法,拖到它最主要在強化的那個原則上。配完按「對答案」。

🛠️ 可操作性
✨ 簡潔性
🌱 可演進性
建一套監控儀表板加自動告警,讓維運團隊隨時看清系統健康、出事立刻被通知
拖到這裡
用抽象把實作細節藏在乾淨介面後面、把命名理清楚,移除偶然複雜度,讓新工程師快速看懂
拖到這裡
把系統拆成模組、定義穩定介面,未來需求一變只要換掉相關模組,不必牽一髮動全身
拖到這裡
🔄
演進的決策,要有「依據」

可演進性不是靠拍腦袋。Twitter 之所以能從「讀時才組裝時間線」演進到「寫時預先算好時間線」,正是因為他們監控到了巨大的讀取負載壓力——數據反饋,才是改變方向的底氣。可操作性的「可視性」,反過來餵養了可演進性。

小試身手

把三根支柱串起來,你就抓到「可維護性」的精神了。來兩題:

關於軟體生命週期的「成本」,本書開宗明義點出的核心見解是什麼?
一個多國語言支付系統必須處理各種貨幣與稅務規則。這屬於哪一類複雜度?我們最該採取的態度為何?
🗺️
下一站:大局

可靠性、可擴展性、可維護性——三根支柱都立起來了。最後我們把它們接成一張圖,看它們如何互相拉扯、又如何彼此成全。往下捲。

05

大局:把三支柱接起來

它們從來不是各自獨立——而是一邊互相拉扯,一邊互相成全

三句話,收齊整章

你已經走過三根支柱。如果只能帶走三句話,就是這三句:

🛡️
可靠性 = 出錯也能正確運作

硬體會壞、軟體有 bug、人會犯錯。目標不是零故障,而是讓故障不要變成失效

📈
可擴展性 = 負載長大仍維持好效能

先學會用負載參數描述壓力,用百分位數衡量效能,再決定向上還是向外擴展。

🔧
可維護性 = 讓後來的人活得下去

軟體大部分成本在上線之後。靠可操作性簡潔性演進性三招,降低長期維護成本。

它們會互相拉扯

最容易被忽略的一點:三支柱不是獨立的清單,而是會彼此影響的力。改善一個,常常牽動另一個——有時相助,有時相剋。

🤝
相助

想做到高可靠,往往需要更好的監控——而監控正是「可操作性(可維護性)」的一部分。把可維護性做好,可靠性也跟著受益。

⚔️
相剋

為了追求可擴展性,硬塞一堆分散式機制,系統會變得更難理解,反而傷害可維護性。所以設計永遠是權衡,不是把每項都調到最大。

這也是為什麼,當有人問「你的系統可擴展嗎?」最好的回答不是「可以」,而是反問一句:「如果負載以某種方式成長,我們打算怎麼辦?」

用作者自己的結語收尾

這是第 1 章 Summary 的原文,左原文、右白話——剛好替整章畫上句點。

原文 · Summary In this chapter, we have explored some fundamental ways of thinking about data-intensive applications. These principles will guide us through the rest of the book. Reliability means making systems work correctly, even when faults occur. Scalability means having strategies for keeping performance good, even when load increases. Maintainability has many facets, but in essence it’s about making life better for the engineering and operations teams who need to work with the system.
白話翻譯

這一章,我們探索了思考資料密集型應用的一些根本方式。這些原則會帶著我們走完整本書。

可靠性,是指就算發生故障,系統仍能正確運作。

可擴展性,是指就算負載增加,也有辦法維持好效能。

可維護性有很多面向,但本質上,就是讓「之後要跟這套系統打交道的工程與營運團隊」日子好過一點。

看懂三支柱,你多了一項超能力

下次系統出狀況,你能更快定位:是「故障沒被容錯接住」(可靠性)、是「負載長大撐不住」(可擴展性),還是「沒人敢動這段程式碼」(可維護性)?分得清楚,就問得出精準的問題。最後兩題,驗收一下:

關於三支柱「互相關聯」的精神,下列哪個敘述最貼切?
有人問「你的系統可擴展嗎?」,比較恰當的回應思路是?

第 1 章,完。

你剛剛用「程式碼導讀課」的形式,讀完了一本書的第一章——同一套捲軸敘事、雙語並排、互動測驗,搬到書本上毫無違和。這就是「融合」想證明的事。

🎬
接下來

後面每一章,DDIA 都會一層一層往下挖:資料模型、儲存引擎、編碼與演化……都能用這同一套導讀形式攤開來。第 1 章只是把「地基」鋪好。

💡
這是一份 pilot

整頁沿用既有的 styles.cssmain.js 設計系統,只把內容換成 DDIA 第 1 章。若你喜歡,這套作法可以接回主 app、套用到其他章節。