Tech

checkout sh 'build' sh 'test' deploy 每個步驟之間,把「執行到哪 + 變數裡有什麼」整包寫到磁碟 ⚡ controller 在這裡重啟 重啟後:從最後一次存檔的狀態接著跑,不用從頭來過 為了能隨時存檔,Jenkins 把你的 Groovy 轉成「可以一步步暫停」的形式(CPS) 而能存檔的前提是:所有還活著的變數,都必須可以序列化 NotSerializableException、@NonCPS、某些寫法行為詭異——全部源自這一句話

Jenkinsfile 不是 Groovy:CPS、序列化與沙箱

· tech · 約 6 分鐘 · 📚 Jenkins 學習筆記 #9

這個系列到目前為止給過三次同一個建議:Jenkinsfile 只做編排,邏輯放到 shell 腳本或 src/ 的 class 裡。 但我給的理由一直都很軟——好讀(半夜看它的人不一定會 Groovy…

#jenkins#ci-cd#groovy

payment-api(repo) main feature/refund feature/webhook PR #12 PR #15 webhook掃描 Multibranch有 Jenkinsfile 的就自動長一個 job job: main跑 main 的 Jenkinsfile job: feature/refund跑「它自己那版」 job: feature/webhook跑「它自己那版」 job: PR-12合併前先驗 job: PR-15合併前先驗 每個分支跑「它自己那一版」Jenkinsfile,不是共用一份 所以改 pipeline 的 PR,是用改過之後的版本跑的——建置流程的變更,合併前就被驗過了 分支刪掉,對應的 job 也要跟著消失(孤兒 job 清理策略)——否則就是下一批要清的堆積

Multibranch 與 PR 觸發:讓每個分支都有自己的 pipeline

· tech · 約 11 分鐘 · 📚 Jenkins 學習筆記 #8

前面七篇談的都是「一條 pipeline」。但真實的 repo 從來不只有一條路:main 上有人在合、三個 feature branch 在跑、還有兩個 PR 等著 review。 這篇處理的就是這…

#jenkins#ci-cd#branching

✗ 十份複製貼上的 Jenkinsfile 專案 A · 200 行修過安全性設定 專案 B · 205 行沒跟上那個修補 專案 C · 180 行兩年前複製的版本 專案 D · 240 行有人改過,原因失傳 專案 E · 200 行複製自 C(所以也舊) 沒有人知道哪一份才是對的 一個修補要改十次,而且一定會漏掉兩個 「最佳實務」只存在於最早那份,之後只有漂移 ✓ 收斂成一份,各自釘版本 A · 15 行@1.4.0 B · 15 行@1.4.0 C · 18 行@1.5.0 D · 22 行@1.4.0 E · 15 行@1.5.0 pipeline-lib一份 · 有版本 一次修補,全體受惠 但同一件事的反面是:一改,可能全炸 所以要釘版本——升不升、什麼時候升,由專案自己決定 收斂解決的是「漂移」,版本解決的是「連坐」 只做前者不做後者,你會把十個獨立的小問題,換成一個全公司同時發作的大問題

Shared Library:把十份幾乎一樣的 Jenkinsfile,變成公司資產

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #7

第 2 篇的結論是:把 pipeline 寫成程式碼、放進 repo。這件事在一個專案上是純粹的勝利,但當公司有十個、三十個專案之後,會長出一個新問題——十份幾乎一樣、但又不完全一樣的 Jenkins…

#jenkins#ci-cd#pipeline

✗ 一把萬能鑰匙,放 Global prod-deploy-keyGlobal · 永久有效 · 全權限 前端 build 後端 build 工具 job 外部 PR build 能讓任何一個 build 跑起來的人 = 拿到了 Production 的鑰匙 ✓ 按 folder 切 + 短期票 folder: web只有 npm registry token folder: api只有內部 maven 憑證 folder: deployprod 憑證只在這裡 · 只能部署,不能刪叢集每次 build 現發,build 結束就失效 PR build 在 web / api folder 底下 它根本看不到 deploy folder 的憑證 看憑證只問三題:能做什麼 · 活多久 · 誰拿得到 三題都答得出來,才輪得到討論「有沒有加密」——那從來不是重點

憑證管理:機密怎麼進 pipeline,又不會漏出去

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #6

第 2 篇的結論是:pipeline 要寫成程式碼、進 git、讓每個人都能 review。這是整個系列的立場,但它有一個必須同時付的代價——這條路上的每一行,所有能讀這個 repo 的人都看得到。 …

#jenkins#ci-cd#security

序列:一個接一個 Unit 4m Integration 6m 1m Image 3m 14m 010 分 平行:同時開跑 Unit 4m Integration 6m ← 最慢的那條 1m Image 3m 6m —— 總時間 = 最慢的那一條 所以再加平行不會更快,要動的是那條 6 分鐘的 平行的代價:每條各佔一個 executor 格子 · 同機互搶 CPU 與硬碟 · 日誌交錯變難讀 格子不夠時,「平行」會退化成「排隊」——只是排在 Jenkins 內部,你在 UI 上看不出來

進階 pipeline:平行、條件、失敗處理與那個很貴的人工關卡

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #5

前面四篇處理的是「在哪跑」與「東西放哪」。這一篇回到 Jenkinsfile 本身:同樣一條會動的 pipeline,怎麼讓它跑得快、失敗得清楚、而且不會在半夜卡住一台機器。 這批東西的共同點是:它們…

#jenkins#ci-cd#pipeline

① build #41 跑完target/ · node_modules/build 時產生的 config.yml.gradle / .m2 快取全部留在 workspace 裡 ② build #42 開始checkout 更新 git 追蹤的檔案沒被追蹤的殘骸 → 原封不動(它不是 clean,只是 update) ③ build #42 綠燈 ✓但測試讀到的是 #41 產生的那份 config.yml換一台乾淨機器 → 爆 同一個 workspace 目錄,被 #41、#42、#43… 重複使用——它是一個沒人在管的共用狀態 檢驗問題:同一個 commit,在一個全新的環境跑,還會過嗎? 答不出來,你的綠燈就是靠殘留撐著——而殘留遲早會被清掉、或換一台 agent 就消失 這也是「在我機器上明明可以」的反面:在 CI 上明明可以

Workspace 與 Artifact:build 出來的東西去哪了

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #4

上一篇解決了「在哪台機器上跑」。這一篇往下挖一層:跑起來之後,檔案到底放在哪、留多久、誰看得到。 這聽起來很枝微末節,但它其實是整個系列主軸裡「可重現」最常破功的地方——而且破得很安靜:你的 CI 一…

#jenkins#ci-cd#build

① 觸發webhook / PR ② 佇列等一個空格子 ③ 依 label 媒合Jenkinsfile 說:linux && docker agent-alabel: linux docker3 個 executor,還剩 1 格 → 派這台 agent-blabel: linux全空,但沒有 docker → 輪不到它 agent-maclabel: mac簽 iOS 用的,別的工作不派來 排隊等的是 executor 格子,不是機器 一台 agent 有幾個 executor,就能同時跑幾個 build——格子開太多,大家一起搶 CPU 與硬碟 而 label 不符的 agent,就算整台閒著也不會被派工:你的 build 在等的往往不是「機器」,是「對的機器」

Controller 與 Agent:工作到底在哪台機器上跑

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #3

上一篇那份 Jenkinsfile 裡有一行 sh './scripts/ci-build.sh'。它到底在哪台機器上執行? 這個問題聽起來很基本,但它決定了三件事:你的 build 要等多久、失敗時…

#jenkins#ci-cd#infrastructure

設定住在 Jenkins UI 上 v1 · 1月 v2 · 3月 v3 · 8月 job 設定(config.xml)只有「現在」這一份 checkout v1 想重 build 一次 配到的是 8 月的設定,不是 1 月的 那顆產物,再也組不回來 設定住在 repo 裡 v1 · 1月 v2 · 3月 v3 · 8月 Jenkinsfile Jenkinsfile Jenkinsfile 每個 commit 自己帶著當時的建置方式 checkout v1 想重 build 一次 拿到的就是 1 月那份 Jenkinsfile 程式碼與建置方式永遠同版本 「這版是怎麼 build 出來的?」——只有右邊答得出來 同一個 commit、同一次 review、同一次 revert:可審查買一送二,順便買到可重現與可回滾

第一個 Jenkinsfile:pipeline as code 為什麼贏過 UI 點按鈕

· tech · 約 7 分鐘 · 📚 Jenkins 學習筆記 #2

上一篇最後那份 Jenkinsfile 只有二十行,語法簡單到不需要解釋。但我還是要為它寫一整篇——因為這二十行真正的價值不在語法,而在它躺在哪裡。 同一個 build,你可以在 Jenkins 的 …

#jenkins#ci-cd#pipeline

同一條路,三個名字——差別只在自動化走到哪裡 ① 提交程式碼push / open PR ② 建置 + 測試自動、每次都跑 ③ 打包產物一顆可部署的東西 ④ 測試環境驗收隨時可上線的狀態 ⑤ 上 Production誰按下這一步? CI(持續整合) 合回主幹 + 每次都自動驗證 Continuous Delivery(持續交付) 隨時可上線,但人按 Continuous Deployment(持續部署)——過關就自動上,沒有那顆按鈕 兩個 CD 的差別不是技術,是你敢不敢把那顆按鈕拿掉 敢不敢,取決於前面幾關擋得住多少——這也是為什麼品質關卡與回滾是後面幾篇的重點

Jenkins 是什麼:CI 不是「有跑測試」,是「頻繁合回主幹」

· tech · 約 13 分鐘 · 📚 Jenkins 學習筆記 #1

大部分人第一次碰 Jenkins,情境都差不多:公司有一台跑很久的 Jenkins,你要在上面「加一個 job」。點進去、複製隔壁專案的設定、改幾個欄位、按存檔——會動了,收工。這樣用了兩年,你會很熟…

#jenkins#ci-cd#concept

沒有願景 有願景 每個都是好點子,合力 ≈ 0 那個畫面 不必平行,方向相近就會疊加

領導力 - 願景

· tech · 約 7 分鐘 · 📚 成為 Tech Leader 讀書筆記 #8

創新篇走到這裡:拆了牆、學會看見自己、養起了點子流。但還剩最後一個問題——點子流有了,誰決定它流往哪裡? 一個團隊可以點子很多、討論很熱,但每個點子指向不同方向——這時候點子多反而是內耗。這章的答案是…

#leadership#innovation

① 丟出點子自己想的,只佔一種 ② 偷點子借用改良、站上肩膀 ③ 幫點子加工把半成品補完 ④ 放下自己的給更好的讓路 點子脆弱的半成品 團隊的點子流 創新上線的解法 ⑤ 不讓點子太早被殺 —— Leader 撐的傘 「以前試過了」 「這行不通」 「全專案都這樣做」

領導力 - 發想力

· tech · 約 6 分鐘 · 📚 成為 Tech Leader 讀書筆記 #7

前面談過擋住創新的三道牆,也談過用日記拆掉第一道牆——但牆拆掉之後呢?點子要從哪裡來? 這章給的答案是:發想力(idea power)是一種可以練的技能,不是天分。而且更反直覺的是——Leader 對…

#leadership#innovation

帶人的組織:再保險網 CTO:對外承保 事故的臉、商譽的理賠 PM:需求承保 範圍錯了算他的理賠 同仁:選標 整塊自留 同仁:前端 整塊自留 我:後端 毒藥的 parser 分層自留,超額往上送—— 沒有人獨自面對全部 一人 + agent fleet:垂直瀑布 一個人 全部保單的唯一承保人 agent agent agent agent 責任 100% 全反射,中間無人吸收—— 產出像一隊,承保只有一人

責任的保費:AI 不收,也不賠

· tech · 約 9 分鐘 · 📚 帶 AI 的手藝(2026) #4

這篇的起點是一個樸素到近乎廢話的觀察:僱一個員工,他會負責,所以責任不(全)在你身上;用一個 AI,責任百分之百在你身上。第一篇把它叫做分流與全反射。但往下多想一步,它會裂開成一個更大的問題——雇用,…

#ai#leadership

Multica:頸在下游(虛線) AI agents 產出 認領 issue · 寫 code · 留言回報 in_review:人的驗收 prompt 慣例——伺服器不強制 done agent 可直拉 done (通知也不會響) 同一套認證能分辨人與機器—— 但鎖只裝在計費 API 上 Superpowers:頸在上游(實線) 人:spec 簽核 HARD-GATE:未批准不准實作 AI 實作(TDD · subagents) 計畫寫給「零判斷的執行端」 驗證後交付 無證據不准宣稱完成 簽名寫成 specs/*.md 並 commit—— 責任有物理形式;弱點是簽核疲勞

看板上的頸:工具怎麼設計人的責任——兩個開源專案的對照稽核

· tech · 約 11 分鐘 · 📚 帶 AI 的手藝(2026) #3

第一篇立了模型:AI 吃寬層,人守頸口。第二篇把模型丟進事故現場驗證。這一篇看工具——因為 2026 年的工程師不是在白紙上跟 AI 協作,是在一堆新工具裡:agent 看板、多 agent 編排、s…

#ai#leadership

⏱ 頸上有時鐘:主播在罵,時間在走 症狀 / 新證據 指標 · log · 查證結果 AI:敘事 + 把手 候選假設 · 驗證動作 · 溝通草稿 人:動手驗證 抽樣 · 對時間戳 · 照把手走 人:決定與行動 重啟 · hotfix · 補建 · 對外承諾 結果回灌 敘事收斂後 直接採信敘事 = 權威幻覺的短路

頸上有時鐘:事故中的 AI——重播一場毒藥訊息事故

· tech · 約 12 分鐘 · 📚 帶 AI 的手藝(2026) #2

上一篇講了漏斗:AI 吃掉寬層的量,人守住頸口的責任。這一篇把漏斗搬到它最極端的測試場——事故。事故是頸上有時鐘的場景:主播在罵、營運在催,而你必須在資訊不全的情況下做決定。AI 不能替你決定要不要在…

#ai#incident#sre

授權給人:責任分流 同事 工作 ↓ 部分責任 ↑ 「這部分是他負責的」——成立 授權給 AI:責任全反射 AI 工作 ↓ 責任 100% ↑ 「這是 AI 寫的」——不成立

責任漏斗:AI 能做掉九成的事,為什麼剩下的一成是你

· tech · 約 6 分鐘 · 📚 帶 AI 的手藝(2026) #1

寫完 GitCrisp 和 部落格產線 兩篇之後,讀者最自然的下一個問題是:如果 AI 能做掉這麼多事,那你還剩什麼? 我的答案是一個形狀:漏斗。工作的量,大部分真的可以交給 AI——code、測試、…

#ai#leadership

寫作時只寫一個 [[slug|說法]] remark plugin 在 build 時展開 ① 內文連結 讀者順著文脈跳到對的段落(支援標題錨點) ② 對方文末的「🔗 被引用於」 反向連結自動生成,還依引用所在章節分組 ③ 知識圖譜的一條邊 /graph/ 頁把全站文章畫成一張互動網絡圖 寫一次,長三個地方——文章寫得越多,舊文章越值錢

這個部落格本身,就是一個作品:把寫作做成一條產線

· tech · 約 5 分鐘

寫了 旅遊分帳 和 GitCrisp 的介紹之後,發現漏了一個最常被使用的作品——你現在正在看的這個網站。它不是「架個 blog」:一百六十多篇文章、十幾個系列、一排小工具的背後,是一個 Astro …

#side-project#automation#ai

presentation — PySide6 main window · graph delegate · MD3 theme tokens application commands / queries(薄薄一層 use-case) domain entities(純資料類) ports(Protocol 介面) 零框架依賴 infrastructure pygit2 composite 十個 ops mixin: branch / commit / diff / stage merge-rebase / stash / tag remote / submodule / worktree + subprocess(git apply) 實作 ports 依賴指向內圈:presentation → application → domain ← infrastructure

GitCrisp:我和 AI 一起寫了一個 Git 桌面客戶端

· tech · 約 6 分鐘

GitCrisp 是一個桌面版的 Git 客戶端:視覺化 commit graph、逐 hunk staging、互動式 rebase、衝突解決介面、多倉庫管理,Python + PySide6(Qt…

#side-project#system-design#ai

instance 專屬設定 應用與它的設定 烘烤線 agent・共用設定 套件與 runtime 基底 OS 線以上:開機時才灌(fry) 彈性、改了馬上生效; 但開機慢、開機時可能失敗 線以下:烤進 image(bake) 每台一模一樣、開機即用; 但改一行要重建 image 線可以移:往上移=開機快、變更慢;往下移=變更快、開機慢——沒有免費的方向

Servers as Code:烘烤線畫在哪,決定你開機多快、改動多痛

· tech · 約 5 分鐘 · 📚 Infrastructure as Code 讀書筆記 #8

Stack 那層管的是「有哪些資源」;這篇往下鑽進資源裡最有內容物的那種——伺服器本身。一台 server 從開機到能服務,身上堆了一整疊東西,而 IaC 在這層要回答兩個問題:這疊東西什麼時候放上去…

#iac#devops#book-notes

複製貼上 一包全裝 可重用 stack code A code A' code A'' dev staging prod ✗ 三份 code 各自漂移 改三次,忘一次就失真 一份 code 同一個 stack(同一份 state) dev stg prod ✗ 環境共用爆炸半徑 改 dev 的失誤可能炸到 prod 一份定義 dev staging prod 各自的 state,差異只在參數檔 ✓ 測過的那份定義 就是上線的那份

Stack 與環境:staging 不該是另一份 code,是同一份的另一個 instance

· tech · 約 5 分鐘 · 📚 Infrastructure as Code 讀書筆記 #7

進入書的第二部分:stack。前面講切割時一直在說「一個 stack」怎樣怎樣,這篇先把這個詞站穩,再處理它最日常的應用場景——同一包基礎設施,要生出 dev、staging、prod 好幾份。這件事…

#iac#devops#book-notes

單體:爆炸半徑 = 全部 小元件:爆炸半徑 = 一塊 網路 資料庫 服務 A ← 改這 服務 B 監控 權限 改一行,整包一起 plan、一起冒險 網路 stack 資料 stack 服務 A ← 改這 服務 B 只 plan、只動這一塊;其他透過介面往來

小而簡單的元件:爆炸半徑決定你敢不敢改

· tech · 約 4 分鐘 · 📚 Infrastructure as Code 讀書筆記 #6

三個核心實踐的最後一個。上一篇說變更批次要小,這篇補上它的前提:批次小得起來,元件先要小——如果整個系統是一包巨大的 stack,再小的改動也會被迫帶著整包一起上路。這章講的就是怎麼把基礎設施切成「小…

#iac#devops#book-notes

端到端・整合 起一個真的測試 stack 單元測試・plan 預覽 靜態分析:lint・validate・policy as code 回饋:秒 → 分 → 十分鐘

持續測試與交付:品質來自快回饋,不是守關卡

· tech · 約 4 分鐘 · 📚 Infrastructure as Code 讀書筆記 #5

三個核心實踐的第二個。上一篇把一切變成程式碼之後,下一個問題自然是:程式碼會錯,怎麼知道這次變更是安全的?書的答案跟傳統直覺相反——不是在上線前設一道更嚴的關卡,而是把驗證拆碎、塞進工作的每一步。品質…

#iac#devops#book-notes

定義檔(想要的終點) web 伺服器 × 3 現況 web 伺服器 × 2 比對(plan) 差異:+1 台 執行(apply) 只補差異的部分 把現況推向定義 跑第二次?比對差異 = 0 → 什麼都不做。這就是冪等

一切皆程式碼:宣告式寫終點,程序式寫路徑

· tech · 約 4 分鐘 · 📚 Infrastructure as Code 讀書筆記 #4

前三章鋪完為什麼、原則、平台,從這章開始進入三個核心實踐,第一個就是招牌:把所有東西定義成程式碼——不只伺服器,網路、pipeline、監控、權限,全部。好處書裡列得很整齊(可重用、一致、透明、可測試…

#iac#devops#book-notes

應用層 你的產品與服務 應用執行環境 Kubernetes、PaaS、資料庫叢集 基礎設施平台 運算 VM · 容器 · FaaS 儲存 block · object · DB 網路 VPC · LB · DNS 可程式化(API) 隨需(分鐘級) 自助(不用開票)

基礎設施平台:你家的雲,是真的雲嗎?

· tech · 約 4 分鐘 · 📚 Infrastructure as Code 讀書筆記 #3

前兩章講完 為什麼和原則,第三章回頭補一個地基問題:IaC 要有東西可以 code——你的定義檔寫得再漂亮,也要有一個收到 API 呼叫就能生出資源的平台在下面接著。這章就在講這個「動態基礎設施平台」…

#iac#devops#book-notes

前提:任何元件隨時會壞(便宜的 commodity 硬體) 流程可重複 + 變異最小化 一切可重現 從定義檔重建任何東西 一切可拋棄 牛,不是寵物 故障=例行重建 不再是災難 可靠性從「硬體不會壞」搬到「軟體重建得快」 鏈條由左往右:上游做不到,下游全是空談

雲時代基礎設施的原則:壞了就重建,可靠性來自軟體

· tech · 約 4 分鐘 · 📚 Infrastructure as Code 讀書筆記 #2

第一章說雲時代該擁抱變更,這章回答「憑什麼敢」。前提先翻轉:鐵器時代的可靠性是用錢買硬體——更貴的機器、雙電源、RAID、原廠保固;雲跑在海量便宜的 commodity 硬體上,供應商直白告訴你:任何…

#iac#devops#book-notes

鐵器時代 · Iron Age 雲時代 · Cloud Age 實體硬體:變更以週、月計 最佳化方向:減少變更 重審批、重文件、凍結窗口 軟體定義:變更是 API 呼叫 最佳化方向:擁抱變更 自動化 + 快速回饋顧品質 錯不起 → 少改 改得快又安全 → 常改、用變更學習

Infrastructure as Code 是什麼?從「變更」的成本翻轉講起

· tech · 約 7 分鐘 · 📚 Infrastructure as Code 讀書筆記 #1

開一個新系列:讀 Kief Morris 的 Infrastructure as Code,用的是第三版(2025)——副標從第二版的 Dynamic Systems for the Cloud Ag…

#iac#devops#book-notes

手機 A localStorage 手機 B localStorage 電腦 C localStorage Apps Script /exec doGet / doPost LockService:鎖內合併 Google 試算表 trips 表(JSON) 明細分頁(唯讀鏡像) 同一組行程代碼 同步循環:① GET 拉雲端 → ② 本機合併 → ③ POST 推回 → ④ 伺服器鎖內再合併,回傳權威版本

旅遊分帳:把 Google Sheet 當後端,寫一個不會把帳弄丟的分帳工具

· tech · 約 6 分鐘

每次跟朋友出國,分帳都是同一個劇本:有人先墊機票、有人刷了租車、晚餐又是另一個人付——回國後對著一堆收據算「誰欠誰多少」,算到懷疑人生。市面上的分帳 App 不是要每個人都註冊帳號,就是要大家都裝同一…

#side-project#system-design#distributed-systems

中斷的成本:不是時間,是被切碎 工作 ramp-up 中斷 ① 被切碎的一天 完整深度工作 ≈ 幾乎沒有(全是碎片) ② 把中斷收成一塊 不被打斷的深度工作(一整段) 中斷時段 同樣的中斷總量 → 深度工作 = 一整段 中斷的成本不是它花的時間,是把剩下的時間切碎到做不了深度工作

維運中斷:殺死生產力的不是工作量,是被切碎的時間

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #17

On-call 那篇講「怎麼設計告警、誰值班」,Toil 那篇講「用 50% 護欄別讓維運吃光工程時間」。但這兩條之間,漏了一個每天都在發生、卻很少被當成問題來管的東西:中斷(interrupts)—…

#sre#reliability

PRR:上線前的一道關 開發 把服務做出來 功能 OK ≠ 可上線 PRR 生產就緒審查 ① SLO 定義了嗎 ② 監控 + 告警(黃金訊號) ③ 壓測 / 容量 / load shedding ④ 發布能不能快速 rollback ⑤ 依賴掛了會怎樣(降級) ⑥ runbook:半夜照著能做 過關 沒過 SRE 接手 共同扛 pager 退回補齊 pager 先留在開發手上 SRE 不接「不可運維」的服務——PRR 把可靠度變成上線的硬門檻

生產就緒審查(PRR):SRE 憑什麼接手一個服務

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #16

前面十五篇,講的幾乎都是「服務已經在線上了,怎麼讓它更可靠」——SLO、監控、postmortem、降級。但有一個更前面的問題一直沒問:一個新服務,憑什麼可以上線、憑什麼值得 SRE 接手扛 page…

#sre#reliability

黃金路徑:由粗到細,一路「點」過去 ① Metric:有沒有 ↑ exemplar = trace_id 先看到「痛」 ② Trace:在哪一段 紅色那段 = 慢/error 縮到哪個服務、哪段 ③ Log:是什麼 info handling req error NPE at line 42 info retry ok 都帶同一個 trace_id 看到根因那一行 trace_id trace_id 三步都是「點」,不是「查」:看有沒有 → 看在哪 → 看是什麼

關聯:從一個尖峰,點到那一行 log

· tech · 約 4 分鐘 · 📚 Grafana LGTM 可觀測性 #8

整個系列從第一篇的黃金路徑就一直押著一句:metric 看有沒有、trace 看在哪、log 看是什麼,由粗到細。但我一直跳過最關鍵的一步——這三格之間,到底怎麼「跳」過去?Tempo 那篇說「找 t…

#observability#grafana#correlation

role defaults —— 最通用的預設值 group_vars —— 整個群組共用(如 prod) host_vars —— 單一機器 play vars / vars_files task vars --extra-vars(-e)永遠最大 越具體,優先權越高 群組輸給單機、檔案輸給命令列——通用預設放底層,緊急覆寫走 -e

Playbook 進階:變數、條件,與重新定義成功

· tech · 約 5 分鐘 · 📚 Ansible for DevOps 讀書筆記 #4

上一篇的 playbook 是死的:寫死的套件、寫死的路徑,只能打一種環境。第五章一口氣補上讓它活起來的所有機關——變數、條件、錯誤處理。內容很雜,但整理之後其實就三個主題:資料從哪來(變數、fact…

#ansible#devops#automation

腳本:描述步驟 「依序做這些動作」 apt-get update apt-get install -y apache2 systemctl start apache2 中斷 = 卡在半套狀態 重跑 = 每一步都可能因「做過了」而爆炸 Playbook:描述狀態 「機器最後要長這樣」 apache2 已安裝 服務 started + enabled 設定檔內容 = 模板產出 每個斷言自帶現狀檢查(冪等) 中斷 = 重跑就好;跑幾次,結果都一樣

第一份 Playbook:把 shell 腳本翻譯成宣告式

· tech · 約 4 分鐘 · 📚 Ansible for DevOps 讀書筆記 #3

上一篇說膠帶貼到第二次就該轉正——這篇就是轉正手續。Playbook 說穿了只是「把 ad-hoc 指令寫進 YAML 檔案」,但書的第四章真正想教的,是一個世界觀的切換:腳本描述步驟,playboo…

#ansible#devops#automation

逐台 SSH 登入 → 打指令 → 登出,重複三次 terminal app1 app2 db t1 t2 t3 總時間 = t1 + t2 + t3,而且手會抖 10 台就是 10 次複製貼上 Ansible ad-hoc ansible multi -a "hostname" 一行指令 inventory:[multi] 展開 app1 app2 db t1 t1 t1 平行執行,總時間 ≈ 最慢那台;預設 5 forks,-f 調整

Ansible ad-hoc:一行指令,管一群機器

· tech · 約 4 分鐘 · 📚 Ansible for DevOps 讀書筆記 #2

上一篇說 Ansible 第一天就能用——這篇就是「第一天」的實際內容。書的第二、三章其實在回答兩個很務實的問題:我要在哪裡練習?(答案:一個可以隨時砍掉重練的本機實驗場)以及還沒學 playbook…

#ansible#devops#automation

Agent 模式(Puppet / Chef) 先養 master、每台機器裝 agent Master 伺服器 節點 + agent 節點 + agent 節點 + agent agent 定期輪詢、拉取組態 開始自動化之前,先多一套要維運的系統 Agentless(Ansible) 沒有 master、沒有 agent 你的筆電 節點 節點 節點 SSH 主動推送 節點只需要 SSH + Python——本來就有

Ansible 是什麼?從告別雪花伺服器講起

· tech · 約 5 分鐘 · 📚 Ansible for DevOps 讀書筆記 #1

每個維運過伺服器的人都經歷過這個循環:SSH 登入機器、改幾個設定、裝幾個套件、登出——三個月後沒有人記得那台機器上到底改過什麼。書裡把這種機器叫做 snowflake server(雪花伺服器):每…

#ansible#devops#automation

重來也不換(核心) FSM・查詢即驗證 事實 append+讀時派生 批次淤而不倒 3NF・庫存雙欄位 per-provider 金流事實表 五個 boring 元件・一台 VM 排序不排期・merge 即上線 轉檔即驗證・泛型外鍵 重來要補(保護) 四個黃金訊號+batch lag 量表 事故的語言:severity・runbook 毒藥訊息的 dead-letter 第一天就上 Cloudflare invariant query 排程(自我對帳) deleted_at・sweep 前反查 負載測試・另外半張 checklist ——全是「保護」,沒有一項是「功能」 核心是對的,欠的全是保護 這也解釋了我後來為什麼走向 SRE

Re:如果真的重來

· tech · 約 7 分鐘 · 📚 Re:從零開始做直播代購電商平台 #21

這個系列從一則留言的旅程開始,寫了二十章。終章不新增任何架構,只做四件事:交代結局、講完最後一個月、把三個寫到中段才浮現的體悟收起來,然後回答書名的問題——如果真的重來,我會改什麼。 19 講過那一天…

#war-story#live-commerce#retrospective

站 1:單機 + tenant_id 每張表帶 tenant_id・複合索引打頭 多數 SaaS 的終點站 往下一站的觸發:連線數、資料量、 噪音鄰居——不是「感覺該分散了」 站 2:讀寫分離 replica 吃報表・商城讀流量 寫入仍單點,這站買的是時間 觸發:讀流量壓過寫、報表打擾交易 站 3:Pool + Silo 混合 小商家共居 pool shard・大主播獨立 DB 噪音鄰居的 DB 層解法=企業版分層 per-tenant 備份還原=silo 殺手優點 升艙搬家:單商家停機匯出匯入, 只影響他自己,約在深夜搬 站 4:真分片 Citus 類 shard by tenant_id / NewSQL pool 本身要水平擴的那天才需要 誠實地說: 多數直播代購 SaaS 到不了這站 每一站都有觸發條件——沒被觸發,就留在原站;演進是回應,不是興趣

平行世界:如果變成 SaaS

· tech · 約 11 分鐘 · 📚 Re:從零開始做直播代購電商平台 #20

先交代一件前面十九章都沒說的事:當年我們每一個人,都是降薪進來的。降薪換的是一個承諾——現在做的直播代購平台只是第一站,真正要造的是一艘 SaaS 大船:把整套系統賣給每一個想做直播代購的商家。 船,…

#war-story#live-commerce#system-design

全盛 七人・每天上線 那一天 CTO:暫停開發 合約重談・可能資遣 一個月後 剩三個人 我・一個前端・CTO 新方向 接外部訂單的採購系統 選標搬出・monolith 降格 背景音:商城還開著,但已經沒有客人

三個人的微服務:暫停開發之後

· tech · 約 8 分鐘 · 📚 Re:從零開始做直播代購電商平台 #19

上一章結尾說,這個團隊的終點比所有人想的都近。這章從那一天講起。 某天,CTO 通知全部工程師:暫停開發。與第三方的合約要重新談;可能會走向資遣;他會去幫大家爭取多一點資源。 政治的細節留給終章,這章…

#war-story#live-commerce#microservices

商城線 我(backend lead) 後端 ×1 前端 ×2 CTO:專職做 PM 商城期間不寫程式 工程輸出=4 個工程師 選標線(獨立) 後端 ×1・前端 ×1 專屬 PM ×1 老實說:我不熟這條線 (初期)外包 1–2 人——單人後端時期的止血帶 全遠端・拆分線=組織線(下一章的伏筆)

六個工程師,跑出二十個人的速度

· tech · 約 7 分鐘 · 📚 Re:從零開始做直播代購電商平台 #18

系統的故事,到上一章告一段落;剩下的章節要講的,是做出這個系統的人,和這一切是怎麼結束的。先回答一個最基本的問題:前面十七章的系統——FSM、三層訂單、金流事實表、一台 VM 的帝國——是誰做出來的?…

#war-story#live-commerce#engineering-management

直播現場 助理看直播截圖 貼進 dialog、確認 前端:優化 切正方形・轉 webp 為了體驗與頻寬 後端:保證 一律重編碼+thumbnail 原始 bytes 不落地 GCS 原圖+縮圖 兩檔 轉檔即驗證:解不開的檔,轉檔自己失敗 image_metadata:path・content type・object id DB 存 path(事實);API 回應時解出 URL(派生)——實際供圖走 GCS 掛 CDN 前端的處理是優化,後端的處理是保證

上傳容易,刪除難:圖片與資源的生命週期

· tech · 約 9 分鐘 · 📚 Re:從零開始做直播代購電商平台 #17

這章插一個看起來最不起眼的題目:商品圖。「不就是上傳檔案嗎」——這章會用一半的篇幅講上傳,另一半講一件難得多的事:刪除。上傳只要一個下午就能做完;刪除,是一輩子的事。 先看這條管線的真實使用場景,因為…

#war-story#live-commerce#system-design

一台資料庫的裡面 我們的系統 WAL:先寫日誌,再做別的 留言清洗後先 append 落地 log consumer:消化日誌、建索引 FSM batch 消化留言、建購物車 物化視圖:先算好存起來 賣出數量計數(唯一的物化) view:讀的時候才計算 付款/訂單狀態讀時派生 redo log:可重放的變更史 配貨紀錄:可整段重建 內建排程:vacuum、checkpoint heartbeat 掃表:催付、結算 repair:壞了照事實修回來 每小時重算賣出數量 拆開的代價:資料庫免費送的交易保證,得自己一項項補回來 這章要回答的就是:「一致性」這項,我們是怎麼補的

對帳:我們沒有做,為什麼帳還是對的

· tech · 約 7 分鐘 · 📚 Re:從零開始做直播代購電商平台 #16

這章在規劃裡叫「三本帳:庫存帳、訂單帳、金流帳」,本來要寫我們怎麼對帳。動筆前照慣例回去查證當年的實際做法,結果是:我們沒有做對帳。 系統裡沒有對帳排程、結束檔期不核帳、上線後也幾乎沒處理過錯帳。 一…

#war-story#live-commerce#data-consistency

13,000 人在線 一台 VM traefik API+WS API+WS API+WS API+WS Celery:heartbeat 排程的心臟 Celery:抓留言 只有 1 個 worker Celery:async task 10 workers・acks_late Redis RabbitMQ 刻意用盡量少的資源做——這是哲學,不是預算 Cloud SQL 8 core・不自己養 DB

沒有 SRE 的年代:backend lead 的上線日記

· tech · 約 9 分鐘 · 📚 Re:從零開始做直播代購電商平台 #15

上一章講尖峰怎麼打;這一章講打仗的人。當年團隊沒有 SRE 這個職稱——身為 backend lead,infrastructure 的仗自然全落在我身上。這章是那段提心吊膽日子的日記:全部家當一台 …

#war-story#live-commerce#sre

200/s 10–20/s 介紹商品 起標:一秒內 10–20 倍 結標中不定時放優惠 → 一連串浪 一場結標:短則 10 秒,平均 3 分鐘 13,000 人在線;副台同時起標時,最壞疊加 ~250 則/秒

開賣瞬間:主播喊完 key 的那三秒

· tech · 約 8 分鐘 · 📚 Re:從零開始做直播代購電商平台 #14

交易和營運的故事都寫完了,接下來幾章講的是貫穿全系統的事:尖峰、維運、對帳。先從所有直播電商的原點講起——主播喊完 key 的那三秒。這章有真實的數字、最痛的一次事故,和一條從被打爆一路通往「雲端菩薩…

#war-story#live-commerce#scalability

第一次 開網頁跳警示 dialog 按「確認」即解鎖 簽收警告・誤殺成本≈0 第二次 鎖一個月 時效到自動解 第三次 鎖三個月 時效到自動解 第四次 永 ban 僅客服可解 再犯一次,往上爬一級——分級讓誤殺變便宜,讓慣犯自己爬上重罰

風控與黑名單:不是逐客令,是信用體系

· tech · 約 6 分鐘 · 📚 Re:從零開始做直播代購電商平台 #13

先把攻擊模型講清楚。這個系統裡,留言喊單當場佔庫存、付款卻在檔期尾聲——中間隔著幾天的信任。惡意的玩法於是很簡單:喊單、佔住、不付。庫存被白佔最長一整週(檔期長度),真想買的客人搶不到,主播的貨卡在幽…

#war-story#live-commerce#risk-control

訊息嚴重度 → private reply 自動・免費・量大 得標通知+綁定 token 政策牆:一則留言 只能回一次 email 常規・內部通知 async 完成通知走這裡 Google Workspace 現成 缺點:會沉底 電話(客服) 人工・最貴・必達 最後通牒:錢要被清、 人要進黑名單之前 渠道來源:綁電話送免運 簡訊:OTP+最後催繳(一檔期只發一次) 簡訊沒催動的,才輪到電話 渠道成本與訊息嚴重度對齊;而觸達權不是接 API 就有的——它是產品換來的

通知系統:兩個欄位、一支排程,和一通電話

· tech · 約 7 分鐘 · 📚 Re:從零開始做直播代購電商平台 #12

「通知系統」四個字在教科書裡的長相:一套 notification service、一組 message queue、模板引擎、多渠道 SDK、退避重試框架。這章要講的版本是:兩個欄位、一支排程掃描、…

#war-story#live-commerce#notification

需要券:一張券 = 三個參數的組合 效果 滿額折抵 滿額免運 門檻 滿額多少才生效 + 商品白名單(算進額度的) 範疇 特定檔期/多個檔期 全檔期合算 例:「滿 3000 折 300・限檔期 A・限指定商品」 不需要券:多件優惠 買多少送多少 一個商品可以掛多種 套用順序的故事在下一節 實驗層:Django admin 各種買 A 送 B 的花式組合 實驗性緊急套用 站穩了,才升級成正式規則

優惠與金額:折扣算錯,比超賣還難查

· tech · 約 12 分鐘 · 📚 Re:從零開始做直播代購電商平台 #11

超賣會炸、金流會叫,折扣算錯不會有任何聲音——客人多付了 13 元不會知道,少收了 13 元你也不會知道,直到對帳那天一筆一筆挖。這章講優惠:規則怎麼收納、聰明演算法怎麼輸給主播的一句話、以及讓分攤永…

#war-story#live-commerce#pricing

第一幕 Django group + permission model 級 CRUD 機器的粒度,沒語意 第二幕(+一週) 把 permission 塞進 JWT 錯的粒度被固化 改權限=等重登 第三幕 轉 role-based 語意終於對了 但正交維度一出現 role 數量開始暴增 落點 可疊加的 能力 role cost monitor 乘法變加法 每一步都是局部合理的:用內建的(省時間)→ 塞 JWT(跟無狀態一致)→ 換 role(要語意) 錯不在任何一步,在沒有先問:這個系統的權限,天然的單位是什麼?

權限:誰能按哪顆按鈕——我們改了三次

· tech · 約 11 分鐘 · 📚 Re:從零開始做直播代購電商平台 #10

權限是我自己認證當年沒做好的部分之一:改了三次,每次都花了真實的時間,每次都只對了一半。有趣的是,把三次改版排開來看,它剛好走完了權限系統的經典演化路徑——所以這章與其說是懺悔,不如說是幫後人把路標插…

#war-story#live-commerce#authorization

主播 只看,不操作 留言流 (帶黑名單標籤) 販賣數量 下單的人 觀看人數 (FB API) 用數據抓節奏 直播助理 直播的操作台 商品資訊填入 (事前填/臨時開) 起標・結標 重新起標 追加庫存 替主播動手 營運 另外的獨立頁面 結束檔期 運費設定 入庫單 配貨 管檔期的節奏 客服 處理例外 調整購物車 清除購物車 多重綁定 接住殘量 工程師 Django admin 安全操作台 Celery task 花式需求 (半成品試驗場) 不確定的先住這 底下是同一套事實與 API——同一份資料,五扇不同的窗

主播與營運後台:沒有一個叫「後台」的東西

· tech · 約 5 分鐘 · 📚 Re:從零開始做直播代購電商平台 #9

前八章寫的是交易的骨架:留言進來、庫存卡住、錢收好、貨出門。這章換一個視角——站在直播現場的人,看到的是什麼。講「後台」之前先劇透結論:這個系統裡沒有一個叫「後台」的東西,有的是一組角色介面,每個人打…

#war-story#live-commerce#internal-tools

銷售庫存(承諾) 上限・賣出計數——下單瞬間守超賣 活在毫秒級的交易裡 實體庫存(現實) 入庫單 append——營運登記實際到貨 活在天級的物流節奏裡 兩本帳天生會歪:談好 100 件,到貨 80 件 配貨系統 實際庫存 → 分給訂單;怎麼分,營運決定 配貨紀錄表 append——庫存變動可用全部事件重建 order「全部」配齊 → 產生出貨單(items 一起出,不拆件) 7-11 超商取貨 API 介接・客人網頁選店號 宅配(自配貨運) 人工匯出 CSV 交給貨運

出貨前處理:賣的是承諾,出的是現實

· tech · 約 7 分鐘 · 📚 Re:從零開始做直播代購電商平台 #8

錢收完了,該出貨了。這章是系統與實體世界的交界——留言、庫存、金流都活在資料庫裡,但貨是真的紙箱、真的倉庫、真的宅配司機。也因此,這是全系列「系統邊界」劃得最有意識的一章:哪些歸系統管、哪些交給人,當…

#war-story#live-commerce#fulfillment

告警的狀態機:for 把短暫抖動吸收掉 查詢值 vs 門檻(每個 interval 評估一次) 門檻 短暫尖峰(< for) 持續超標(≥ for) Normal 超門檻 Pending在 for 期間持續觀察 撐過 for Firing 送通知 沒撐過 for → 回 Normal(不 page) for 是抗抖動閥:短暫尖峰在 Pending 就被吸收,只有真正持續的問題才會吵醒你

Grafana 告警:從看見到行動

· tech · 約 5 分鐘 · 📚 Grafana LGTM 可觀測性 #7

這系列從第一篇就一直押著一句話——觀測的終點不是「看到」,是「行動」。前面六篇把「看到」講完了:三支柱怎麼存、怎麼查、怎麼進來。這篇補上最後那一哩、也是整個系列的 payoff——告警(Alertin…

#observability#grafana#alerting

orders payment 狀態不儲存,讀取時聚合:已付 = SUM(入帳事實) ≥ 應付 銀行 A・智慧轉帳 事實表 銀行 A・信用卡 事實表 銀行 B・付款 事實表 現金入帳 營運標記 150,000 單筆上限 3 萬 = 五筆事實 webhook(即時) 銀行主動通知 polling(兜底) 排程主動查單 雙通道寫進同一組事實表——事實冪等,重疊無害,互為備援

第三方金流:教科書的三個坑,與一個沒有坑的地形

· tech · 約 6 分鐘 · 📚 Re:從零開始做直播代購電商平台 #7

上一章把單聚合成了三層,現在要收錢了。金流是這個系統第一次把「正確」交到別人手上——付款發生在銀行那邊,你只能透過不可靠的網路得知結果。教科書會警告你三個坑:通知會重複、會亂序、會根本不來。這章要講的…

#war-story#live-commerce#payment

佔庫存購物車(直播) 可橫跨多個檔期/實況主 不佔庫存購物車(商城) 同一張 cart item 表,來源多型 合併結帳 orders payment —— 付錢的單位 跨檔期一次付清・聚合第三方付款事實(下一章) order(檔期 A) 履約單位・檔期優惠記這層 order(檔期 B) 按檔期切 order(檔期 C) 跟著各自的出貨節奏 order item —— 會計單位:成交時定格金額,發票/退款以它為準

購物車到訂單:被主播拔掉的狀態機

· tech · 約 8 分鐘 · 📚 Re:從零開始做直播代購電商平台 #6

交易主線的最後一站:單怎麼從購物車走到訂單。留言進了購物車、身分掛好了單、庫存卡住了不變量——這章把它們聚合成一筆可以付錢、可以出貨、可以開發票的東西。標題不是比喻:這個系統裡真的有一台狀態機,被主播…

#war-story#live-commerce#system-design

product 價格、商品資訊 直播中會一直變 1:1 庫存表(熱資料,獨立一張) 庫存上限 —— 主播追加貨=只調這裡 購物車數量(預留) 訂單數量(成交) 付款:購物車 → 訂單,同一筆交易內轉移 不變量:購物車 + 訂單 ≤ 上限(可賣=導出值,不存「剩餘」) FSM batch 下單・LWW 改單 客人 自行調整數量 客服 清除・調整購物車 助理/營運 追加貨・結束檔期 寫入者有四方——但每小時會從 cart/order items 全量重算兩個計數(派生值的自我修復)

庫存:不能超賣,是這個系統唯一的鐵律

· tech · 約 8 分鐘 · 📚 Re:從零開始做直播代購電商平台 #5

留言解析完、身分掛好單,主線走到心臟:庫存。這個系統的功能清單可以慢慢長,但只有一條規則從第一天就是鐵律——不能超賣。賣掉不存在的貨,是要一個一個跟客人道歉退款的。這章講當年怎麼守這條不變量、它被什麼…

#war-story#live-commerce#inventory

identity:身分是事實 fb user(PSID) 留言當下就地建立 ig user 自建 user account:帳號是聚合 account 登入後才出現 認領 identity 的單,1:N 綁定(可多重) cart item(佔庫存) 掛在 fb user 上,不是 account 上 fbmsgtocartitem msg id・bidding key id 聚合視圖:認領即收編,訂單不用搬家

身分與帳號:留言的那個人,到底是誰

· tech · 約 9 分鐘 · 📚 Re:從零開始做直播代購電商平台 #4

上一章的 FSM 解出了「誰買了什麼」——但那個「誰」,其實只是 FB 給的一串數字。他可能從來沒註冊過我們的平台,可能明天才會登入,可能永遠不會。而庫存現在就要卡給他。這章講全景裡我說「全系列最容易…

#war-story#live-commerce#identity

✗ 直連:M × N 條耦合 app 1 app 2 app 3 Mimir Loki Tempo 每個 app 都要懂每個後端(位址/格式/重試) 換一個後端 → 改「所有」app ✓ 經過 collector:M + N 條 app 1 app 2 app 3 OTLP 一種協定 Collector(Alloy)批次・重試・脫敏・路由 Mimir Loki Tempo 換後端 → 只改 collector 設定,app 一行不動 M 個 app × N 個後端 → M + N:app 只認一種協定(OTLP),後端只面對 collector

採集層:資料怎麼進來——OpenTelemetry 與 Alloy

· tech · 約 5 分鐘 · 📚 Grafana LGTM 可觀測性 #6

三支柱講完了,但有個前提一直被我跳過:訊號要先「進得來」,才有得看。第一篇資料流圖中間那格「採集層」,這篇把它拆開。兩個主角:OpenTelemetry(統一三種訊號的標準)與 Grafana All…

#observability#opentelemetry

FB(100)・輪詢 IG(10)・webhook 自建(1)・直推 取回:各源各自的接法 FB 輪詢自適應:忙續抓、閒放慢 殊途同歸進同一張表 清洗 → 落地 統一 message 格式 append 去重鍵:source+message id batch 200・FSM 解析 → 查 bidding key 扣賣出數量+建立身分 raw 有落地・FB 可整場重抓——但從沒被動用 處理失敗 → 直接略過,沒有補救路徑 一切為了主播眼中最新鮮的庫存狀態;代價:尖峰 lag 可達幾分鐘、掉單無聲

留言即下單:把聊天室變成下單通道

· tech · 約 13 分鐘 · 📚 Re:從零開始做直播代購電商平台 #3

全景和起手式鋪完,進主線第一戰:一則留言,怎麼變成一筆單。這章講「接進來」和「解析」兩段,佔庫存的攻防留給下一章。主角是把聊天室變成收銀機的那台有限狀態機——我們會直接讀它的程式碼。 留言來自三個源:…

#war-story#live-commerce#fsm

同步・毫秒級 Django API 請求進、回應出 購物車・結帳・會員 即時・推送 WebSocket 客人留言 → 即時推給 主播 dashboard 非同步・秒~分 RabbitMQ(管道) Celery workers 抓留言・FSM 下單・開發票 寄 email・匯出訂單 PostgreSQL 唯一的事實:訂單・庫存・會員 Redis 速度:banned user 快速判斷 三種時間尺度各請一位專家,底下一份事實、一份速度

起手式:五個元件與一條 CI/CD

· tech · 約 6 分鐘 · 📚 Re:從零開始做直播代購電商平台 #2

全景鋪完,講留言、庫存那些戰役之前,先把當年的武器庫攤開——因為後面每一章的取捨,都是在這套技術棧的邊界裡做的。團隊很小:3 個後端、3 個前端,偶爾發包給外包 1–2 位工程師。武器庫也很樸素:Po…

#war-story#system-design#django

留言進來 FB / IG / 自建 統一留言事件 每源一個 adapter 解析 key+n 同人重複取最後一筆 身分 identity 沒帳號也要能掛單 佔庫存購物車 庫存 −n・不能超賣 結帳 兩種購物車合併 第三方金流 webhook・冪等 出貨前處理 合併出貨・交物流 逾期未付 → 釋放庫存 每一站都是系列的一章:留言接入、身分、庫存、購物車、金流、出貨前處理

全景:留言下單的一筆訂單,會經過哪些系統

· tech · 約 6 分鐘 · 📚 Re:從零開始做直播代購電商平台 #1

這是一個新系列,也是這個部落格第一個戰爭故事。我在前公司實際做過一個直播代購電商平台——使用者看直播、在留言區打字下單,後面接著庫存、金流、物流一整條鏈。這系列不是回憶錄:我想帶著現在的功力(DDIA…

#war-story#live-commerce#system-design

傳統:一個盒子,全部捆在一起 儲存引擎 索引 快取 mat. view log ↓ 拆開(unbundle),每個功能交給一個特化系統 ↓ log 當中樞(Kafka)— 定順序的膠水 OLTP DB儲存 + 交易 Elasticsearch= 索引 Redis= 快取 數倉 / Gold 層= materialized view 每個系統都是 log 的 follower,照同一順序消費 → 各自一致 你的資料平台 = 一台「由內翻外」的資料庫;讓它不散架的,是那條 log

資料系統的未來:拆開的資料庫、Kappa,與端到端的正確性(完結)

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #12

終章。前面十一章把儲存、複製、分區、交易、共識、批次、串流一塊塊講完,Kleppmann 在這章把它們收攏成一個大膽的視角:別再把「資料庫」當成一個盒子——把它拆開。 而讀到這裡你會發現,這個「未來」…

#distributed-systems#book-notes#data-engineering

✗ 雙寫:應用自己寫三份 應用程式 DB 快取 搜尋索引 病一:寫到一半當掉 → 有的寫了有的沒寫 沒有交易能跨三個系統回滾 病二:並行寫抵達順序不同 DB 收到先A後B、快取先B後A → 收斂到不同值 → 三個系統永久分歧,無聲無息 ✓ log 先行:只寫一個地方 應用程式 只寫這裡 一條有順序的 log(source of truth) DB 快取 搜尋索引 全部照「同一順序」消費 → 順序一致、掉了可重放 下游全是 follower,最終收斂到同一狀態 一份資料要進 N 個系統?選一個當 source of truth,其他全部當 follower

串流:雙寫的陷阱、CDC,與流表二象性

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #11

批次處理「已經齊了」的資料;串流處理「一直來」的資料。這章很多地基我在別處鋪過了:log 與 offset 在 Kafka 系列、投遞保證在 delivery 那篇、視窗與 event time 在 …

#distributed-systems#book-notes#streaming

輸入(不可變) log 分片 1 log 分片 2 log 分片 3 ① map(就地、平行) (/a,1)(/b,1)… (/a,1)(/c,1)… (/b,1)(/a,1)… 逐筆抽 (key, value),不搬資料 ② shuffle(按 key 重分發) 同 key 跨網路聚到同一台+排序 唯一大搬家的一步=最貴 ③ reduce(整組聚合) /a:(1,1,1)→ /a=3 /b:(1,1)→ /b=2 … 輸出:寫成「新」檔案 map 就地跑(把運算搬到資料旁)· shuffle 是唯一的大搬家,也是一切成本所在 groupBy、join、去重……凡是「同 key 要相聚」的操作,背後都是一次 shuffle

批次處理:MapReduce 的精神、join 的兩條路,與不可變輸入的美德

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #10

Part II 在單一系統內把一致性守住了;Part III 的主題換成資料在系統之間流動——而最古老、也最可靠的流動方式,是批次(batch)。DDIA 講 MapReduce 的切入點很別緻:先講…

#distributed-systems#book-notes#data-engineering

終場哨響:結果寫入,但兩個 replica 進度不同 leader:2 : 1 終場 replica 1(已同步):2:1 終場 replica 2(落後):1:1 進行中 ① Alice 查到「終場 2:1」→ 告訴 Bob ② Bob 重新整理 → 「還在踢」?! 發生在「後」的讀,讀到「更舊」的狀態 → 「單一資料」的幻覺破滅 = 不 linearizable

一致性與共識:linearizability、CAP 的誠實版,與全序廣播

· tech · 約 5 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #9

上一篇的結論是:任何單一節點的判斷都不可信,真相只能由多數決定。這章講的就是「多數怎麼安全地決定」——DDIA 全書的理論高潮。演算法細節(Raft、Paxos、Zab 怎麼投票換屆)我在 SRE 共…

#distributed-systems#book-notes#consistency

你的節點 送出請求,等待… ① 請求在網路上丟了對方根本沒收到 ② 對方當掉了真的死了 ③ 對方只是很慢(過載、GC 暫停中)等一下它會處理——甚至正在處理 ④ 對方做完了,但「回應」在路上丟了動作已經發生,你卻以為沒有 在你這端: 四種一模一樣 = 沒有回應 timeout 到了,只代表「你決定不等了」,不代表「你知道發生了什麼」

分散式系統的麻煩:不可靠的網路、不可信的時鐘,與半死不活的節點

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #8

上一篇結尾埋了個鉤子:當系統跨到多台機器,連「鎖」和「驗證」本身都變得不可靠。這章就是那個「不可靠」的總清算——也是我認為全書最該精讀的一章。核心一句話:單機世界是確定性的,要嘛全好、要嘛全壞;分散式…

#distributed-systems#book-notes#reliability

不變量:值班醫生 ≥ 2(目前:Alice、Bob 都在) Alice 的交易 ① 查值班人數 → 讀到 2 ≥ 2 ✓ ② 把「自己」改成請假 Bob 的交易 ① 查值班人數 → 也讀到 2 ✓ ② 把「自己」改成請假 (快照隔離:兩人看到的都是「舊快照」的 2) (改的是「不同列」→ 沒有寫入衝突,都放行) 結果:值班人數 = 0,不變量被打破 💥 每筆交易「單獨看」都對;錯在:你檢查所依據的條件,被對方的寫入悄悄改掉了 同款劇本:會議室重複預訂、帳號搶同一個 username、餘額分兩筆同時扣

交易:快照隔離擋不住的 write skew,與可串行化的三條路

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #7

交易的地基我在 SQL 系列鋪過了:ACID 的重點是 I、髒讀/不可重複讀/幻讀三種怪事、四個隔離層級的光譜、MVCC 怎麼讀不擋寫——那些這篇不重複。DDIA Ch7 真正的加值在後半:兩個連「快…

#distributed-systems#book-notes#transactions

按 key 範圍切(range) A–F G–R S–Z 像百科全書分冊,key 有序 ✓ 範圍掃描高效(讀連續一段) ✗ key 是時間戳 → 今天的寫入 全砸最後一區(熱點) HBase / 早期 Bigtable 按 key 的 hash 切 分區 0 分區 1 分區 2 hash 把相鄰 key 均勻噴散 ✓ 負載攤平,熱點被打散 ✗ 順序沒了 → 範圍掃描 得問「所有」分區 Cassandra / Redis Cluster(CRC16)/ Kafka 折衷:複合主鍵(第一欄 hash 選分區,其餘欄位在「分區內」照樣排序)—— Cassandra 的招牌 而 hash 救不了「單一超熱 key」(名人問題)—— 那得在應用層加鹽,把一把 key 拆成多把

分區:range 還是 hash、二級索引擺哪、以及怎麼重新平衡

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #6

複製是同一份資料放多台;分區(partitioning,也叫 sharding)是把資料切開,每台只放一部分——當資料量一台裝不下、或寫入 throughput 一台吃不消,這是唯一的出路。兩者幾乎總…

#distributed-systems#book-notes#partitioning

單主 single-leader Leader follower follower 所有寫入 衝突:源頭消滅(單一寫入點) 代價:failover 難(誰接任?) MySQL / Postgres / Redis / Kafka 多主 multi-leader Leader A Leader B 資料中心 1資料中心 2 兩邊同時改同一筆 → 衝突! 得利:各地就近寫、斷網照收 代價:寫入衝突要事後解 跨資料中心 / 離線編輯 / 協作文件 無主 leaderless 副本 副本 副本 client 同時寫 n 份 quorum:w + r > n 得利:沒有 leader,無 failover 代價:讀寫路徑複雜、read repair Dynamo / Cassandra 同一道題的三種答案:寫入衝突,你想在「源頭擋、事後解、還是讀時調和」?

複製:單主、多主、無主,與延遲的三個怪象

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #5

進入 Part II,資料開始跨機器。第一招是複製(replication):同一份資料放多台,為的是三件事——一台掛了還能服務(高可用)、資料放得離使用者近(低延遲)、讀流量攤出去(擴讀)。如果資料…

#distributed-systems#book-notes#replication

一個請求的 trace:spans 排在時間軸上(waterfall) gateway auth checkout payment← 600ms 瓶頸 inventory db write 05001000 ms metric 只說「checkout 慢」;trace 指出是 payment 那 600ms —— 這是 metric/log 給不了的「在哪一段」

追蹤與 Tempo:一個請求走過的路

· tech · 約 4 分鐘 · 📚 Grafana LGTM 可觀測性 #5

三支柱最後一個:traces。它補的是 metric 和 log 之間那個最關鍵的洞——「在哪一段?」 Metric 告訴你「checkout 慢」,但一個請求橫跨了八個服務,到底卡在哪一 hop?L…

#observability#tracing

滾動更新中:新舊版同時在跑,資料雙向流動 新版程式 v2已升級的那幾台 舊版程式 v1還沒輪到的那幾台 同一個資料庫 / topic 兩邊都在寫、也都在讀 向後相容 backward 新程式,讀得懂「舊資料」 大家都記得(migration 思維) 向前相容 forward 舊程式,讀得懂「新資料」 最常被忘,但滾動與回滾窗口天天發生 schema 每一次變更,兩種相容都要顧——少一邊,滾動到一半就開始噴錯

編碼與演化:讓新舊程式碼,讀得懂彼此的資料

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #4

上一篇講資料怎麼放上磁碟,這篇講一個更容易被輕視的問題:資料寫出去時,是用什麼格式編碼的? 你可能覺得「JSON 就好了啊」——直到 schema 要改的那一天。這章的重量,來自兩個躲不掉的事實:資料…

#distributed-systems#book-notes#data-engineering

Loki 的兩步查詢 {service=checkout}|= "timeout" ① label 索引小而快 → 縮到幾個 chunk(只索引這個) ② grep 那小堆原始 chunk存 object storage・不索引全文暴力掃,但範圍已很小 ELK:索引全文每行都建全文索引 → 任意全文秒搜但索引巨大、RAM 貴 Loki:只索引 label先用 label 縮小、再 grep便宜到能存海量 log 賭注:你多半已知道要看哪個 service、哪段時間 → 先縮再 grep,夠用又便宜

日誌與 Loki:只索引 label,不索引全文

· tech · 約 4 分鐘 · 📚 Grafana LGTM 可觀測性 #4

三支柱第二個:logs。而 Loki 最該懂的一件事,是它一個很聰明、很省的設計選擇——它不像傳統 log 系統(ELK)那樣索引全文,而是「像 Prometheus 一樣只索引 label」。這個選…

#observability#logging

LSM-tree:append-only,事後整理 memtable記憶體,先接住寫入 寫滿→整批順序刷盤 SSTable(新,不可變) SSTable(較舊) SSTable(更舊) compaction背景合併去重 寫:永遠順序 append → 快 讀:可能翻好幾層 SSTable(bloom filter 救) B-tree:page 樹,就地更新 root page page page ✎ 就地覆寫 leaf page WAL:改 page 前先順序記一筆(防當機) 讀:沿樹走 3~4 層就到 → 穩 寫:隨機 I/O 就地改 + 先寫 WAL LSM 寫優(RocksDB / Cassandra / HBase)· B-tree 讀穩(幾乎所有關聯式 DB)

儲存引擎:LSM-tree、B-tree,與欄式儲存

· tech · 約 4 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #3

上一篇選好了資料模型,這篇往最底層鑽:資料庫到底怎麼把資料放上磁碟、又怎麼找回來? DDIA 這章從一個兩行 bash 的「全世界最簡單資料庫」開場——dbset 就是往檔案尾巴 append 一行,…

#distributed-systems#book-notes#storage

cardinality:series 數 = 每個 label 基數的乘積 http_requests_total{...} ✓ 低基數 labels service(3) × method(4) × status(5) = 60 條 series Prometheus 輕鬆扛 ✗ 多加一個高基數 label … × user_id(100 萬) = 6000 萬條 series 💥 記憶體被吃光,Prometheus 暴斃 label 只放低基數維度;高基數(user_id / request_id / email / URL)丟去 logs / traces

指標與 Prometheus:時序、pull、PromQL 與 cardinality 的坑

· tech · 約 5 分鐘 · 📚 Grafana LGTM 可觀測性 #3

三大支柱進第一個,也是骨幹:metrics。它是你「有沒有問題」的第一道防線,也是後面告警和 SLO 的底層數字。而 metrics 世界的事實標準,是 Prometheus。這篇講它的資料模型、為什…

#observability#prometheus

Grafana 只查不存:資料在 data source Grafana(一塊玻璃)只存 dashboard / 設定,不存資料 panel:錯誤率 panel:延遲 p99 panel:錯誤 log 資料真正住這裡 ↓ Prometheus / Mimir Tempo Loki PromQL trace query LogQL 關掉 Grafana,資料一點不少(它在 data source);Grafana 只是「問」,不是「存」

Grafana:一塊玻璃,只查不存

· tech · 約 5 分鐘 · 📚 Grafana LGTM 可觀測性 #2

第一篇那張資料流圖,最右邊那格是 Grafana。這篇把它拆開——而理解 Grafana,其實只要抓住一句反直覺的話:它不存任何觀測資料,它只是一塊拿來「問」的玻璃。 想通這句,它的所有特性就都通了。…

#observability#grafana

三大支柱:各答一個問題 Metrics(指標)→ Prometheus / Mimir 有沒有問題?多嚴重? 數字時序・可聚合便宜・可長期存但沒有細節 Traces(追蹤)→ Tempo 在哪個服務?哪一段慢? 一個請求的完整路徑跨服務串起來 Logs(日誌)→ Loki 那裡到底發生什麼? 事件的完整細節量大・貴・難聚合 排障黃金路徑:由粗到細,逐步收斂 metric:有沒有trace:在哪log:是什麼

可觀測性是什麼:三大支柱與 LGTM 全家桶

· tech · 約 5 分鐘 · 📚 Grafana LGTM 可觀測性 #1

一個系統可不可靠,先看你看不看得見它在幹嘛。這系列講 Grafana 的 LGTM 這套可觀測性工具怎麼把「看見」做到位。第一篇立好整個系列的框架:monitoring 和 observability…

#observability#grafana

時間驅動:cron 對時(脆弱) DAG A @ 02:00 賭 A 跑完了 DAG B @ 02:30(猜的) A 遲到 → B 照跑→ 吃到舊 / 空資料 ✗ 資料驅動:Dataset(精準) DAG A → 產出 sales Dataset: sales DAG B schedule=[sales] A 一更新 → B 立刻觸發,不早不晚 ✓

Airflow 進階:Datasets、deferrable operators 與 executor 選型

· tech · 約 5 分鐘 · 📚 Airflow 學習筆記 #9

這篇講三個進階功能。它們看似無關,其實有個共同點:都在解 Airflow 某個「死板」或「浪費」——排程只認時間、sensor 佔著 slot 空等、worker 一刀切。三個都是選配,但每個都能讓你…

#airflow#data-engineering

一個資料平台的分層 監控 LGTM:一塊玻璃看全平台Grafana · Loki(logs)· Tempo(traces)· Prometheus / Mimir(metrics) Stateful 核心 — StatefulSet + PV KafkaRedis RabbitMQMetadata DB 少動・保護狀態・HA 過半・傾向 managed Stateless 運算 — Deployment + autoscale Spark executor Airflow worker Kafka Connect worker 可拋・隨開隨關・借外部狀態・傾向 self-host Kubernetes 底座control plane + etcd —— 所有東西都跑在這上面 一條軸決定分層:有狀態的沉在核心層少動;無狀態的浮在運算層隨開隨關

把它們兜成一個資料平台

· tech · 約 5 分鐘 · 📚 從 Infra 角度看資料工具 #9

前面八篇,一個一個工具看。這篇把它們兜成一個平台。而「兜」的方法,不是把七個工具的細節背起來——是抓住那條從第一篇就在講的軸:stateful ↔ stateless。這條軸一句話決定了每個工具在平台…

#infrastructure#platform

worker 無狀態,狀態全存回 Kafka Connector(一份 config)→ 拆成 N 個 task Worker 1(無狀態・可拋) task-1task-2 Worker 2(無狀態・可拋) task-3task-4 狀態存回 Kafka Kafka 叢集(Connect 的 state store) configsoffsetsstatus worker 掛 → task rebalance 到別台,一則不丟(狀態在 Kafka);命門 = Kafka 本身

Kafka Connect:連接器的執行時

· tech · 約 5 分鐘 · 📚 從 Infra 角度看資料工具 #8

收尾 stateless 這一批的最後一個:Kafka Connect。它是一套專門在 Kafka 與外部系統(資料庫、S3、Elasticsearch)之間搬資料的框架——你不用每次都手寫消費者/生…

#infrastructure#kafka

Pub/Sub:廣播,丟了就丟 PUBLISH news "…" channel: news(不留存) Sub 線上✓ 收到 Sub 線上✓ 收到 Sub 離線✗ 漏掉 沒人在聽 → 沒了・無持久・無重播・無 ack Stream:留著的 log,可重播 XADD stream * …(append) m1m2m3m4m5 舊 consumer另一個從這讀 訊息留著(可設 MAXLEN 上限) 可從任意位置重讀・離線再上線能補・有 group + ack

Pub/Sub vs Stream:Redis 版的訊息系統

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #12

Redis 也能當訊息系統,但它有兩套截然不同的東西,用錯就會莫名其妙掉訊息、或殺雞用牛刀:Pub/Sub(廣播,丟了就丟)和 Stream(留著的 log,像一台縮小版 Kafka)。這是整個 Re…

#redis#distributed-systems

逐條 N × RTT vs pipeline 1 × RTT ① 逐條:每條都等一個來回 clientserver 3 條 = 3 個來回 = 3 × RTT ② pipeline:打包成一個來回 clientserver cmd1 ; cmd2 ; cmd3 一次送 三個回應一起收 3 條 = 1 個來回 = 1 × RTT ✓

管線、交易與 Lua:省 RTT 與原子性

· tech · 約 4 分鐘 · 📚 Redis 學習筆記 #11

有三個東西常被混在一起,其實各解完全不同的問題:pipeline 解「網路來回太多」、MULTI/EXEC(交易)解「一組命令要一起執行不被插隊」、Lua 解「要原子、又要帶邏輯」。搞混它們,你會拿 …

#redis#distributed-systems

Scheduler每隔幾秒 parse 一次所有 DAG 檔 parseparse ✗ top-level 放重活 df = query_db() # 模組層 cfg = requests.get(url) 每次 parse 都跑這些 → scheduler 被反覆拖垮、DAG 變慢 ✓ 檔案輕,重活進 task @task def load(): query_db() top-level 只有 DAG 結構 parse 秒過 重活只在 task 執行時跑一次

Airflow 測試與部署:別讓一個 typo 弄垮整包 DAG

· tech · 約 7 分鐘 · 📚 Airflow 學習筆記 #8

DAG 寫好了、也可靠了,最後一哩是工程紀律:怎麼確定我的改動不會弄壞它,又怎麼把它安全送上 Production。 這篇講測試(把壞 DAG 擋在 merge 前)、部署(DAG 檔怎麼上環境、se…

#airflow#data-engineering#testing

非冪等:INSERT 附加 第 1 次:INSERT 6/18 → 中途失敗 重試:又 INSERT 6/18 一次 6/18 資料重複兩份 ✗重試把一次故障放大成資料污染 冪等:覆寫分區 第 1 次:覆寫 6/18 分區 → 失敗 重試:再覆寫 6/18 分區一次 6/18 分區一致 ✓跑幾次結果都一樣,重試安全

Airflow 可靠性實戰:冪等、重試、SLA 與告警

· tech · 約 5 分鐘 · 📚 Airflow 學習筆記 #7

前面幾篇教你把 DAG 寫出來、排對區間。但 Production 的 DAG 是會在半夜出事的——來源系統延遲、網路抖一下、下游資料庫重啟。這篇講怎麼讓 DAG 扛得住失敗、能自己救、真救不了會大聲…

#airflow#data-engineering#reliability

key 落哪台:CRC16 → 16384 slot → node key:「user:1000」 CRC16(key) % 16384= slot 5798 Node Aslot 0 – 5460(+ 一個 replica) Node B ✓slot 5461 – 109225798 在這 → 由 B 保管 Node Cslot 10923 – 16383(+ 一個 replica) 16384 個固定 slot 是「中間層」,node 只是認領一段 slot 所以搬資料 = 搬 slot;擴縮容乾淨可控,不必重算全部 key 的位置

Redis Cluster:16384 個 slot 怎麼分片與擴縮

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #10

單執行緒那篇說過,一台 Redis 的瓶頸是記憶體與網路。當一台裝不下、或流量頂到單機上限,就要把資料分片(sharding)到多台——這就是 Redis Cluster。但它的分片方式很有個性:不用…

#redis#distributed-systems

Sentinel 自動故障轉移的五步 ① 監控一直 ping master與 replica ② 主觀下線某個 Sentinel覺得沒回應(SDOWN) ③ 客觀下線過半同意「真掛了」(ODOWN) ④ 選出 Sentinel leader → 挑 replica 升主選一個最完整的 replica 升為新 master其餘 replica 改指向新 master ⑤ 通知客戶端新 master 位址 客戶端向Sentinel 問「現在誰是master?」

高可用:Sentinel 怎麼自動故障轉移

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #9

上一篇的主從複製給了你副本,但留了一個大洞:master 掛了,不會自動有人接手。 你得半夜爬起來,手動把某個 replica 升成 master、把其他 replica 改指向它、再叫所有客戶端換位…

#redis#high-availability

一個 master 寫,多個 replica 讀 應用程式寫走 master、讀走 replica Master讀寫・單一寫入點只有一個 Replica 1只讀 Replica 2只讀 非同步複製 讀流量分散到各 replica → 水平擴展讀

主從複製:讀寫分離與複製延遲的怪現象

· tech · 約 4 分鐘 · 📚 Redis 學習筆記 #8

一台 Redis 再快也有記憶體與流量的上限,而且它一掛,資料就懸在半空。走向高可用的第一塊地基,就是主從複製(replication):一個 master 負責寫、若干 replica 各複製一份、…

#redis#distributed-systems

看似無狀態的組件,真狀態藏在一顆 metadata DB Scheduler解析 DAG、排 task無狀態・可重啟 Webserver那個 UI無狀態 Worker × N執行 task可多開・可重啟 Metadata DB(Postgres)真狀態・命門 組件掛了都能換;DB 掉了 = 整個系統的記憶歸零(哪些跑過、誰在跑、誰失敗) 連多個 scheduler 的 HA,都靠對這顆 DB 上鎖(row lock)來協調

Airflow:排程器、worker 與那個藏起來的狀態

· tech · 約 6 分鐘 · 📚 從 Infra 角度看資料工具 #7

上一篇埋了個伏筆:每個系統都有一塊逃不掉的狀態,認出它就掌握了命門。 Airflow 是這句話最好的示範。它表面上全是看似無狀態、可重啟的組件——scheduler、webserver、worker,…

#infrastructure#airflow

取得鎖:一行原子命令 SET lock:res <token> NX PX 30000 NX只有 key 不存在才設→ 互斥 PX 30000自帶 30 秒 TTL→ 持有者掛了也自動釋放,不死鎖 <token>隨機值→ 標記「這把鎖是我的」 釋放鎖:要驗 owner(Lua,原子) if GET(key)==token then DEL(key)GET 與 DEL 必須原子 → 只刪自己的鎖 直接 DEL 不驗 token→ 誤刪別人續租的鎖 ✗

分散式鎖:從 SETNX 到 Redlock,與那場著名的爭議

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #7

多個行程、多台機器要搶同一個資源(同一時間只准一個人扣庫存、跑一個排程),就需要一把分散式鎖。Redis 因為快又原子,常被拿來當這把鎖。但這是個「看起來三行就能寫完、其實坑深到見底」的題目——一路踩…

#redis#distributed-systems

無狀態運算:算在叢集內,狀態在叢集外 資料源S3/DB/Kafka 輸出 sink寫回結果 Spark app(叢集內) Driver 協調 · 單點命門 Executor短命可拋 Executor短命可拋 Executor短命可拋 executor 掛 → 靠 lineage 重算那一塊,不丟資料;真正 durable 的資料全在叢集外 對比前三篇:狀態 = 服務本體;Spark:狀態借外部,自己近乎無狀態

Spark:短命 executor 的彈性運算

· tech · 約 5 分鐘 · 📚 從 Infra 角度看資料工具 #6

前三篇(Kafka、Redis、RabbitMQ)都在光譜的 stateful 那一端——狀態綁在自己的磁碟或記憶體,擴縮要搬資料、故障要救資料。這篇翻到光譜的另一端:Spark,系列第一個 stat…

#infrastructure#spark

同一個 app 一堆 YAML 九成內容共用 Developmentreplicas:1 · image:app:dev · 資源小 · host:dev.local Stagingreplicas:2 · image:app:rc · host:stg.example.com Productionreplicas:10 · image:app:1.4 · 資源大 · host:example.com

打包與部署:Helm 與 Kustomize

· tech · 約 6 分鐘 · 📚 Kubernetes 學習筆記 #14

前面每一篇都在教你寫 YAML,但實務有個逃不掉的痛:同一個 app 要上 Development、Staging、Production,而三個環境九成的 YAML 一模一樣,只有幾個地方不同——副本…

#kubernetes#operations

① 排程到 nodeScheduler 挑一台 ② 拉映像檔kubelet 去 registry 拉 ③ 起容器・活著跑起來且不崩 ④ Ready・進 Endpoints通過 readiness 才收流量 ✓ 正常收流量 Pending資源不足 / taint 沒 toleration / PVC 綁不到 ImagePullBackOff · ErrImagePull映像名打錯 / 私有 registry 少 imagePullSecret CrashLoopBackOff · OOMKilled起來就掛一直重啟 / 超過記憶體 limit 被砍 Running 卻 not Ready · 連不到readiness 失敗 / Endpoints 空(selector 錯)/ DNS 解不到 / NetworkPolicy 擋掉

故障排除:Pod、Node、Control Plane 怎麼查

· tech · 約 7 分鐘 · 📚 Kubernetes 學習筆記 #13

CKA 佔比最高的一塊是故障排除(30%),但它其實不是新知識——它是把前面整個系列串起來的能力。排障最忌諱用猜的、亂試一通。真正的心法只有一句:沿著 Pod 的生命週期,一關一關問「它卡在哪」——因…

#kubernetes#troubleshooting

Control Plane node · kubeadm init api-server scheduler controller-mgr etcd 都是 static pod:kubelet 讀 /etc/kubernetes/manifests 拉起來就自動維持 吐出 join token + 指令 kubeadm join <token> Worker node只跑 kubelet + 你的 Pod Worker node要幾台加幾台 再加 CP node(join)→ HA control plane

叢集管理:kubeadm、etcd 備份、升級

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #12

前面十一篇都站在「用叢集」的位置。這篇換到「建與養叢集」的位置——CKA 佔 25% 的 Cluster Architecture 裡最硬的 ops 活。三件事貫穿一個管理員的一生:怎麼把一堆機器變成…

#kubernetes#operations

kubectl / Pod 發一個請求 ① 認證 authn 你是誰? 憑證 · token · OIDC ② 授權 authz 你能做這動作嗎? ← 這就是 RBAC 執行 API Server 驗不出身分 → 401 沒權限 → 403 兩道門各管一件事:先確認「你是誰」,再判斷「你能不能」

RBAC:誰能對叢集做什麼

· tech · 約 6 分鐘 · 📚 Kubernetes 學習筆記 #11

前面十篇都在讓東西「跑起來、連得到」。這篇換一個維度:誰有權對叢集下命令? 一個 kubectl delete 打進 API Server,它憑什麼知道你是誰、又憑什麼准你刪?這是 RBAC(Role…

#kubernetes#security

預設:任兩顆 Pod 都通 web api db 全通 = 沒有隔離 web 也連得到 db 套一條只保護 db 的 policy web api db預設拒絕 ✗ web 被擋 db 只放行 api;web↔api 沒被選中,照舊全通

NetworkPolicy 與 CNI:Pod 之間的防火牆

· tech · 約 6 分鐘 · 📚 Kubernetes 學習筆記 #10

Service 與 Ingress 講的是「流量怎麼找到服務」,但底下有個更基本、也更容易被忽略的問題:Pod 跟 Pod 之間,預設能不能互通? 答案會嚇到很多人——預設全通,任何一顆 Pod 都連…

#kubernetes#networking

使用者 一個網域 一個對外 IP GET shop.com/api Ingress L7:讀 HTTP 的 Host + path shop.com/ shop.com/api img.shop.com 順便在這裡卸 TLS(https → http) web-svc ClusterIP → web Pod api-svc ClusterIP → api Pod img-svc ClusterIP → img Pod 一個 IP、一個入口,按網址分流到多個內部 Service —— 這是 L4 的 Service 做不到的

Ingress 與叢集 DNS:一個入口進來、一個名字相認

· tech · 約 6 分鐘 · 📚 Kubernetes 學習筆記 #9

第四篇給了短命 Pod 一個固定門牌 Service,但留了兩個尾巴:一是「外面怎麼用一個入口進來、再按網址分流到不同服務?」——那張對外類型圖裡最上面的 Ingress;二是叢集內服務彼此互打時,那…

#kubernetes#networking

Pod nodeSelector / affinity 「我想去 disk=ssd 的 node」 toleration:對 gpu taint 免疫 Node label: disk=ssd taint: gpu=true:NoSchedule 沒免疫的 Pod 一律趕走 拉:Pod 依 label 挑 node 推:node 把沒免疫的 Pod 趕走 toleration 只是免疫,不會把 Pod「吸」過去

進階排程:讓 Pod 去對的 node

· tech · 約 8 分鐘 · 📚 Kubernetes 學習筆記 #7

第二篇講過 Scheduler 幫 Pending 的 Pod 挑 node 分兩步:先過濾(裝得下、規則允許)、再評分(挑最佳)。 那時我說「過濾與評分背後的旋鈕之後專門一篇講」——就是這篇。預設 …

#kubernetes#scheduling

PV / PVC:把「需求」和「供給」分開 StorageClass:動態供應——PVC 一提出就自動生 PV Pod要掛一塊盤 PVC(需求)「我要 10Gi · RWO」app 開發者只喊這個 bound PV(供給)實際那塊 10Gi 儲存底層:EBS / NFS / Ceph… 供需分離:app 只喊「我要多大、什麼存取模式」,不用管底層是什麼硬體 access modes:RWO(單節點)· ROX(多節點唯讀)· RWX(多節點讀寫,需 NFS 之類) reclaim policy:PVC 刪掉後,PV 要 Retain(保留)還是 Delete(連底層一起刪)

K8s 儲存:Volume、PV/PVC 與 StatefulSet

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #6

Pod 是短命、可拋的——自我修復隨時把它換一個。但有些東西死了不能跟著消失:資料。而容器的檔案系統天生是暫時的(ephemeral):pod 一被重排、容器一重啟,寫在裡面的檔案就沒了。所以 K8s…

#kubernetes#storage

三種破口,長得不一樣 穿透 Penetration 查「不存在」的 key cache 沒有、DB 也沒有 → cache 永遠擋不住 每次都直達 DB 擊穿 Breakdown 單一熱 key ⏰ 剛過期 瞬間大量並行同時 miss → 全湧向 DB 重建 集中打一個點 雪崩 Avalanche 大量 key ⏰ 同時過期 (或 Redis 整個掛掉) → 大範圍 miss DB 崩 → 連鎖 共通:請求繞過 cache 打爆 DB;差別在破口—— 不存在的 key(穿透)· 一個熱點(擊穿)· 一大片(雪崩)

快取三大災難:穿透、擊穿、雪崩,與正確解法

· tech · 約 3 分鐘 · 📚 Redis 學習筆記 #6

把 Redis 當快取,最經典的模式是 cache-aside(旁路快取):讀取先查 cache,命中就回傳、沒命中(miss)才查資料庫,再把結果回填進 cache。平常運作得很好——直到某些情況下…

#redis#cache

Kafka:log m1m2m3m4m5 B 讀到 m2 A 讀到 m4 訊息留著 · 各自用 offset 讀 可重播 · 多消費者 fan out RabbitMQ:queue m4m3m2 consumer m1 已被取走 + ack → 消失 消費即移除 · broker 追蹤 ack 複雜路由 · per-message 控制 狀態:Kafka = 一條「消費留痕」的 log(磁碟為王) · RabbitMQ = queue 裡待處理的訊息(消費即減少) 取捨:事件流 / 可重播 / High-throughput → Kafka · 任務佇列 / 複雜路由 / per-message → RabbitMQ

RabbitMQ:訊息 broker 的叢集與流控

· tech · 約 5 分鐘 · 📚 從 Infra 角度看資料工具 #5

收尾「有狀態的重量級」這一批,第三個是 RabbitMQ。它跟 Kafka 都是訊息中介,但 infra 形狀差很多,而差別可以濃縮成一個字:Kafka 是 log,RabbitMQ 是 queue。…

#infrastructure#rabbitmq

同一個映像檔,跑遍所有環境 映像檔my-app:1.0(不可變) DevelopmentConfigMap + Secret StagingConfigMap + Secret ProductionConfigMap + Secret Pod(dev) Pod(staging) Pod(production) 12-factor:設定放環境/外部,不烤進映像檔——同一映像檔才能跨環境重用

ConfigMap 與 Secret:把設定和機密從映像檔裡拆出來

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #5

前面幾篇,你已經能把一個 app 部署、對外服務了。但真實的 app 還缺一塊:設定——資料庫位址、feature flag,還有密碼、API key、憑證。這些東西有一條鐵律:不該寫死在映像檔或程式…

#kubernetes#concept

記憶體為界:硬牆在 RAM(對照 Kafka 磁碟為王) fork headroom(持久化時可能翻倍)實體 RAM 頂 ↑ ← maxmemory 硬牆 可成長空間 已用資料(在記憶體) 資料在記憶體→ 容量硬上限 = RAM 撞牆 → evict或 noeviction 報錯 磁碟 RDB/AOF 重啟回暖 對照:Kafka 瓶頸=磁碟 throughput / 容量 · Redis 瓶頸=記憶體容量

Redis:記憶體為界的有狀態服務

· tech · 約 4 分鐘 · 📚 從 Infra 角度看資料工具 #4

第二個有狀態的重量級是 Redis,而它跟 上一篇的 Kafka 剛好是一組完美對照:Kafka 磁碟為王,Redis 記憶體為界。兩者都有狀態,但體檢表第②題「狀態放哪」的答案不同——一個在磁碟、一…

#infrastructure#redis

磁碟為王:資料就躺在 broker 磁碟上 Producer Broker 1P0 · leaderappend logon disk Broker 2P0 · followerappend logon disk Broker 3P0 · followerappend logon disk replicate → ISR(3 副本) 瓶頸是磁碟(throughput + 容量),不是 CPU / 記憶體 Kafka 靠 sequential 順序寫 + page cache + zero-copy,讓「磁碟」也能跑很快

Kafka:磁碟為王的有狀態叢集

· tech · 約 4 分鐘 · 📚 從 Infra 角度看資料工具 #3

進入有狀態的重量級,第一個是 Kafka。用體檢表看它,一切都從第②題「狀態」展開——Kafka 的資料(那條可重播的 log)不是抽象概念,它實實在在躺在 broker 的磁碟上。這一個事實,決定了…

#infrastructure#kafka

底座解剖:大腦、工人,與命門 etcd Control Plane(大腦) API Server唯一入口 Scheduler排 pod 放哪 Controller Mgrreconcile loop etcd ★命門狀態真相 · Raft唯一 stateful Worker Nodes(工人) kubelet + Pods kubelet + Pods kubelet + Pods etcd 掛了 → 整個叢集「失明」(現有 pod 還跑,但不能排程 / 更新 / 自癒) 所以 etcd 要:奇數台過半、定期備份、低延遲磁碟——它是你最該小心的東西

Kubernetes:所有東西跑的底座,它自己怎麼站穩

· tech · 約 6 分鐘 · 📚 從 Infra 角度看資料工具 #2

這系列第一個要體檢的,是 Kubernetes——但它很特殊:別的工具都跑在它上面。它是底座,所以它自己的可靠度,就是後面 Kafka、Spark、Redis 全部的地基。用上一篇的體檢表看它,會發現…

#infrastructure#kubernetes

Infra 體檢表:看任何工具都問這 8 題 ① 部署拓撲由哪些角色組成?幾台?誰是大腦誰是工人? ② 狀態與儲存 ★樞紐有狀態嗎?資料放哪?掉了能重建嗎? ③ 擴展水平(加機器)還是垂直(加規格)? ④ HA / 故障轉移掛一台誰接手?有沒有單點? ⑤ 容量規劃瓶頸是 CPU / 記憶體 / 磁碟 / 網路? ⑥ 監控該盯哪些指標?怎麼知道它快不行了? ⑦ 調校旋鈕哪些設定會決定生死? ⑧ 故障模式它最常怎麼壞?壞了長什麼樣?

從 Infra 角度看一個工具,要問哪些問題

· tech · 約 3 分鐘 · 📚 從 Infra 角度看資料工具 #1

學一個工具、和把它放進 Production,是兩種完全不同的問題。學的時候你問「這個 API 怎麼用、這個概念是什麼」;上 Production 時你問的是另一組問題——它會怎麼掛?怎麼長大?半夜壞…

#infrastructure#concept

過期 key 怎麼被清:惰性 + 定期,兩管齊下 TTL 到期的 key仍佔著記憶體(還沒被清) ① 惰性刪除(被動)有人來 GET 它 →發現過期 → 當場刪、回 nil ② 定期刪除(主動)背景每秒抽樣 ~10 次 →從有 TTL 的隨機抽一批刪 所以「過期」≠「立刻釋放」——沒人碰、也還沒被抽到,它就先躺著

Redis 的過期與淘汰:TTL、惰性刪除與 maxmemory 政策

· tech · 約 4 分鐘 · 📚 Redis 學習筆記 #5

把 Redis 當快取,遲早會碰到兩個問題:設了 TTL 的 key 到期後怎麼被清掉? 以及 記憶體滿了會怎樣? 這兩件事常被混為一談,其實是兩回事——前者是過期(expiration):「這個 k…

#redis#cache

拍快照(RDB) vs 記流水帳(AOF) RDB 快照定時拍全景 丟失視窗 檔小、載入快、適合備份 ✓ | 兩次快照之間會丟(可能幾分鐘)✗ AOF 日誌每筆寫都記 更安全(最多丟一個 fsync 間隔)✓ | 檔大、載入慢(要重放)✗ 混合模式(Redis 4+):AOF 開頭放一個 RDB 快照 + 後面接增量命令 → 載入快又丟得少(現代推薦)

Redis 持久化:RDB 快照 vs AOF 日誌,資料到底會不會丟

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #4

「Redis 是記憶體資料庫,一斷電資料就全沒了」——這句話半對半錯。對的是它主要活在記憶體;錯的是它其實有持久化,能把資料寫到磁碟、重啟後還原。只是它的持久化語意比傳統資料庫弱,你得懂才用得對。Re…

#redis#persistence

單機 cron 很簡單,「可靠的」cron 很難 cron(單機)時間到就跑,超簡單 ✗ 機器一掛 → 排程全停(SPOF) 要它掛了也能跑 副本(leader) 副本 / 待命 副本 / 待命 共識日誌(Paxos)記錄:哪些任務跑過了 一台掛 → 重選 leader,狀態從共識還原 → 不重跑、不漏跑 把最單純的 cron 變可靠,底層就得用上分散式共識

可靠的 cron:最單純的定時任務,一分散就變難

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #15

cron 大概是最單純的一種基礎設施:時間到,跑一個任務。單機上寫過 crontab 的人都覺得它理所當然。但只要加上兩個字——「可靠」(那台機器掛了,任務還是得照跑),它就從最簡單的東西,一夕變成一…

#sre#reliability

單執行緒 + event loop:一條隊,一個一個處理 client client client client 上萬連線 epollI/O 多工一個執行緒盯全部 命令佇列(一條隊)cmd1cmd2cmd3 單執行緒執行逐一執行、每個原子無鎖、無 race Redis 6 的「多執行緒」只用在讀寫 socket 這些網路雜活—— 命令的「執行」仍是單執行緒,所以原子性、免鎖的好處通通不變

Redis 單執行緒為什麼反而快?——以及 O(N) 命令的地雷

· tech · 約 4 分鐘 · 📚 Redis 學習筆記 #3

第一篇說 Redis 快的原因之一是「單執行緒 + 免鎖」。這聽起來很反直覺——單執行緒不是慢嗎? 這篇就把這件事講透:為什麼單執行緒反而快、它換來什麼,以及它一體兩面的代價——一個慢命令會卡住所有人…

#redis#performance

五大核心結構:選對一個,問題解一半 Stringbytes / 數字 42 快取 · 計數器(INCR)· 分散式鎖(SET NX) List有序,兩端進出 佇列(LPUSH / RPOP)· 最新 N 筆(LPUSH+LTRIM) Hashfield → value name: Aidanage: 30 存物件 · 只改一個欄位,免整包搬進搬出 Set無序、自動去重 去重 · 標籤 · 交集(共同好友 SINTER) Sorted Set成員帶 score、自動排序 a:1b:2c:3 排行榜 · 範圍查詢 · 延遲佇列(score=時間)

Redis 的靈魂:五大資料結構 + 進階武器

· tech · 約 4 分鐘 · 📚 Redis 學習筆記 #2

上一篇說 Redis 的靈魂是「資料結構」——那這篇就把工具箱打開。Redis 用得好不好,九成看你會不會選對結構:選對了,一個排行榜三行命令搞定;選錯了,你會用一堆 GET/SET 在應用端硬幹本來…

#redis#data-structures

傳統 KV 快取(memcached) key → 「一坨字串」(不透明 blob) 改一個欄位 = GET 整包 → 應用端改 → SET 整包 Redis(資料結構伺服器) key → List / Hash / Set / ZSet 伺服器端直接操作(原子)= HSET · LPUSH · ZADD · ZRANGE 例:排行榜 = 一個 Sorted Set,ZADD 記分 + ZRANGE 取前 N 不必把整個榜撈回應用端自己排序——運算搬到資料旁邊做,又快又原子

Redis 是什麼:不只是快取,是記憶體資料結構伺服器

· tech · 約 5 分鐘 · 📚 Redis 學習筆記 #1

大多數人第一次認識 Redis,都是把它當「快取」——把資料庫查詢的結果丟進去、下次直接拿。這沒錯,但也把它看小了。Redis 的本質是一台記憶體資料結構伺服器(in-memory data stru…

#redis#concept

資料模型:一棵像檔案系統的樹(znode) / /config[P]data: db_url=… /services[P] /lock[P] node-1[E] node-2[E] lock-0000000001[E+S] lock-0000000002[E+S] clientwatch client session一斷 → [E] 消失 [P] persistent 永久(除非刪除)  [E] ephemeral 綁 session、斷線即消失 [S] sequential 自動加遞增編號  watch 訂閱變更、一次性通知

Apache ZooKeeper:分散式系統的協調核心

· tech · 約 6 分鐘

上一篇共識帶到 Zab 是 ZooKeeper 的引擎,但 ZooKeeper 本身值得單獨講一篇。它是分散式系統的協調核心(coordination service):你很少直接用它,卻天天間接依賴…

#distributed-systems#zookeeper

抓一個真實請求,跟著它走完全程 使用者一個真實請求 自建入口 LB(自建) API 服務(自建框架) 自建佇列(自建) 資料庫最終落點 每一跳都停下來,問這四題 ① 這是什麼元件?誰維護? ② 怎麼看它健康?監控 / log 在哪? ③ 它壞了,下游會怎樣? ④ 正常時,流量 / 資料長怎樣? 走完一輪,你腦中就有一張「活的」架構圖——比任何 wiki 都準

SRE 空降一間『什麼都自建』的公司,前 90 天怎麼站穩

· tech · 約 7 分鐘 · 📚 Google SRE 讀書筆記 #14.5

換工作最刺激的一種,是加入一間幾乎什麼都自建的公司:沒有現成的雲服務、連 Stack Overflow 都幫不上忙——因為這裡的基礎設施、部署工具,全世界只有這一家在用。你過去累積的「某某工具怎麼設定…

#sre#career

土砲選 leader:網路一斷,兩邊各自為政 網路斷了 ✂ 左半:Node A 「我沒收到 B → 我當 leader」 收到寫入 X = 1 右半:Node B 「我沒收到 A → 我當 leader」 收到寫入 X = 2 網路恢復後:X 到底是 1 還是 2? 兩邊都以為自己對 → 資料分岔,對不回來(split brain)

分散式共識:一群會掛的機器,如何對同一件事達成一致

· tech · 約 7 分鐘 · 📚 Google SRE 讀書筆記 #14

一群機器要對「同一件事」達成一致——誰是 leader?這把鎖在誰手上?最新的值是多少?——聽起來很簡單,卻是分散式系統最難的問題之一。難在哪?因為機器會掛、網路會斷、時鐘不可信,而你要在這些前提下,…

#sre#distributed-systems

一個請求,要通過兩層負載平衡 使用者世界各地 ① 前端 LB選哪個機房?DNS · Anycast · VIP 依 地理 / 健康 / 容量 資料中心(選中的) ② 機房內 LB給哪台機器?依 真實負載 / 健康 task 1 task 2 task 3 顧「跨機房」的事:就近、避開故障機房、分散容量 顧「機房內」的事:別讓某台過載、別送給壞掉的

負載平衡:先選對機房,再選對機器

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #13

一個請求從使用者送出到被處理,其實要通過兩層負載平衡,回答兩個不同層次的問題:去哪個資料中心? 進了之後分給哪台機器? 這兩層顧的事情完全不同,把它們分開看,負載平衡就清楚多了。 前端這層要處理的是「…

#sre#networking

自動化的演進:一路往上,把人從迴圈裡拿掉 自動化↑ · 人越不用碰 ④ 自主 / 自癒系統系統自己管自己 → 人退出迴圈 ③ 通用自動化平台跨系統重用、一致、可擴展 ② 針對任務寫腳本省時,但腳本要人養、換場景就失效 ① 手動操作(toil)慢、易錯、不一致、無法規模化 ⚠ 但自動化會放大 blast radius 能一致地做對,就能一致地闖禍——一鍵下錯,關掉的可能是整個機房

自動化、發布工程與簡單性:讓『改變』又快又安全

· tech · 約 5 分鐘 · 📚 Google SRE 讀書筆記 #12

自動化、發布工程、簡單性,乍看是三個不相干的主題。但把它們擺在一起,會發現它們在回答同一個問題:怎麼讓「變更」既快又不出事?SRE 的三招答案分別是——用機器一致地做、把上線做成可重現的流程、以及讓要…

#sre#automation

你以為的安全 每天都有備份 ✓✓✓ 「帳面上」很安全 真的要還原時… 真出事時翻車 備份檔本身壞了(從沒驗過) 還原程序沒人跑過 → 手忙腳亂 還原太慢 → 超過 SLA、資料回不來 沒演練過還原的備份 = 薛丁格的備份(不打開不知道死活) 重要的不是「備份」,是「恢復」—— 備份只是達到恢復的手段

資料管線與資料完整性:有備份不等於能還原

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #11

一個資料系統的可靠度,除了前面講的「服務不掛」,還有一層更根本的東西——資料本身不能不見、不能錯。這篇講兩件事:資料管線的可靠度,以及一個會顛覆你直覺的觀念:「有備份」不等於「能還原」。 資料管線(p…

#sre#data-engineering

一台倒下 → 流量轉移壓垮下一台 → 骨牌式全滅 Server A先過載 → 倒 ✗ Server B接手 A 流量 → 也倒 ✗ Server C全壓過來 → 倒 ✗ 而 retry storm(重試風暴)火上加油: 請求失敗 / 變慢 客戶端重試 總負載更高 正回饋:越失敗 → 越重試 → 越失敗(自我放大)

連鎖失效與過載:別讓一台倒下拖垮全部

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #10

第一篇說可靠度的目標是「出錯也能運作」。但有一種故障特別難纏,因為它會自我放大:一個小問題引發骨牌,幾分鐘內把整個系統拖垮——這就是連鎖失效(cascading failure)。它最可怕的地方,是系…

#sre#reliability

E2E Integration Unit ↑ 少、慢、脆(像使用者走完整路徑) 元件兜起來(service + DB…) ↓ 多、快、穩(測單一函式) 倒過來(一堆 E2E、少 unit)= 反模式:慢、flaky、出事還難定位到哪層

為可靠度測試:測試不是證明沒 bug,是讓你敢快

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #9

這篇講一個常被當成「開發的事」、其實是可靠度基石的東西:測試。關鍵觀念先講:可靠度不是靠「不改」得來的——你一定得改(修 bug、加功能、換設定),而每次改動都是一場賭。測試的意義,就是把這場賭變成有…

#sre#reliability

沒有指揮:混亂 系統故障中 工程 工程 工程 工程 搶著改、互相踩、資訊亂飛 → 修更慢 有指揮:有序 IC(統籌) Ops 修 Comms 報 Scribe 記 系統故障中 一人一角、資訊集中 → 修更快

事件應變:大事故真正的敵人是混亂

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #8

前面你學會了 on-call 止血、也學會了系統化除錯——但那是「一個人對付一個問題」。當一場大事故爆發(多人捲入、影響大、時間壓力高),你會發現最大的敵人往往不是技術問題本身,而是混亂。 技術問題總…

#sre#incident

interface DevOps ← 哲學/文化:定義「該做什麼」 減少 silo · 接受失敗為常態 · 逐步變更 · 量測一切 · 自動化 implements(給出具體做法) class SRE implements DevOps ← 怎麼做 error budget · blameless postmortem · canary · SLI/SLO · 消除 toil DevOps 是方向與原則,SRE 是一個具體實作——不是二選一,是不同層次

DevOps vs SRE:一個是介面,一個是實作

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #1.5

前一篇講完 SRE 是什麼,順手補一個超常被問、但其實是假問題的比較:「DevOps 和 SRE 有什麼不同?要選哪個?」之所以是假問題,是因為兩者根本不在同一層。Google 用一句很工程師的話破了…

#sre#culture

究責文化 · 惡性循環 出事 「誰的錯?」找戰犯 大家隱藏錯誤、不敢說真話 學不到 → 重蹈覆轍 Blameless · 良性循環 出事 「系統為何允許?」 大家坦白說出全貌 改系統 → 越來越穩 同一場故障,問「誰」還是問「系統」,把團隊帶向相反的兩個循環

Blameless Postmortem:把故障變成組織的學習

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #7

上一篇講怎麼找到 root cause——但找到之後呢?Postmortem(事後檢討) 就是把一次昂貴的故障,轉化成整個組織的學習:記錄發生什麼、影響多大、時間軸、真因、怎麼修的、怎麼防止再發生。而…

#sre#culture

① Triage 止血 先讓系統活著 (別急著找 root cause) ② Examine 觀察 看監控 / log 四個黃金訊號 ③ Diagnose 診斷 假設 → 測試 → 排除 二分逼近 ④ Treat 修復 一次改一個變因 可回復 沒好?回頭再提假設 每一步都在「縮小範圍」;而反模式(亂猜、隨機換零件、一次改一堆)從不縮小,只是碰運氣

有效除錯:除錯是方法,不是天分

· tech · 約 3 分鐘 · 📚 Google SRE 讀書筆記 #6

上一篇說 on-call 被叫到先止血;但止完血,總得找出為什麼。這篇講除錯——而它最重要的一個觀念是:除錯不是靠天分或運氣,是一套可以學的系統化方法。 新手和老手的差別,不在「知道答案」,而在有沒有…

#sre#incident

一個告警進來:需要人嗎?多急? Page 呼叫 需要人「立刻」介入,否則使用者正在受影響 → 把人吵醒 Ticket 工單 需要人處理,但不急 → 上班時間看 Log 記錄 不需要人看,存著備查 / 事後分析 → 不打擾任何人 把不夠急的都塞進 Page → 告警疲勞、狼來了,真的出事反而被忽略

告警與 On-call:什麼時候該把人吵醒

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #5

上一篇結尾留了一句:什麼時候該把人吵醒?這篇回答。它其實是兩件事:告警(什麼該響、響到誰)和 on-call(被叫到的人怎麼健康地扛)。核心觀念只有一句:告警的目的不是「通知」,是「該有人動手了」。 …

#sre#incident

關聯式 Relational users orders FK 表 + 外鍵,SQL 查 多對多、join 強 文件 Document 姓名、email 經歷 [ … ](巢狀) 學歷 [ … ](巢狀) 巢狀 JSON,一對多自然 局部性好(讀一次拿整份) 圖 Graph 節點 + 邊,高度連結 關係本身是主角

資料模型:關聯式、文件、圖,你在選什麼

· tech · 約 3 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #2

第一篇講了資料系統要追求什麼(可靠、可擴展、可維護)。這篇往下一層:你要用什麼「資料模型」來裝資料? 關聯式、文件、還是圖——這個選擇不是小事,它是你把現實映射成資料的底層抽象,決定了你怎麼建模、怎麼…

#distributed-systems#book-notes#data-modeling

Coordinator 收 query、規劃、分派 Segment 1 Segment 2 Segment 3 DISTRIBUTED BY (分佈鍵):用 hash(分佈鍵) 決定每列落哪個 segment,查詢在每台平行跑 ⚠ 分佈鍵不均勻 → 某 segment 資料爆多(skew),平行失效、最慢那台拖垮全部

當 SQL 跑在 MPP 上:Greenplum 與 Cloudberry

· tech · 約 5 分鐘 · 📚 SQL 我以為我懂 #12

整個 SQL 系列的壓軸。前面 11 篇都跑在單機 PostgreSQL,這篇把同一批 SQL 放到 MPP(Massively Parallel Processing,大規模平行處理) 上——Gre…

#sql#data-engineering

① Dirty Read 髒讀 T1 T2 餘額改 200(未提交) 讀到餘額 200 ❌ ROLLBACK ② Non-repeatable Read 不可重複讀 T1 T2 讀餘額 100 餘額改 200 並提交 又讀餘額 200 ❌ ③ Phantom Read 幻讀 T1 T2 查到 3 筆訂單 插入 1 筆符合訂單並提交 又查到 4 筆 ❌ 時間 →

交易與隔離層級:併發不打架的分級

· tech · 約 6 分鐘 · 📚 SQL 我以為我懂 #11

前面講的都是「一個查詢怎麼跑得快」(索引、EXPLAIN),這篇換個維度:很多交易同時跑,怎麼不互相打架? 這就是交易與隔離層級。(這裡講單機 PostgreSQL 的實務;分散式交易與一致性,交給姊…

#sql#concept

Nested Loop 內表(有索引更快) 外表每列 → 查內表一次 適合:小表 / 內表有索引 Hash Join 小表 Hash 表(記憶體) 大表 小表建 hash,大表 probe 適合:大表、等值 join Merge Join 1 3 5 2 4 6 兩側排序後,像拉鍊合併 適合:已排序 / 有索引

讀懂 EXPLAIN:優化器到底怎麼跑你的 query

· tech · 約 3 分鐘 · 📚 SQL 我以為我懂 #10

上一篇留了一個問題:索引到底有沒有被用到?答案就在 EXPLAIN 裡。這篇是我之前寫的 Spark 執行計畫那篇的 SQL 版姊妹作——同一套「讀計畫、找瓶頸」的思維,換一個引擎。學會讀 EXPLA…

#sql#performance

沒索引:Seq Scan(全表掃) 列 1 列 2 列 3 列 4 列 5 ← 目標 列 6 逐列掃過才找到 → O(n),資料越多越慢 有索引:B-tree 節點 節點 目標 沿樹往下幾步就到 → O(log n)

索引為什麼快 —— 也為什麼會失效

· tech · 約 2 分鐘 · 📚 SQL 我以為我懂 #9

接下來換個主題:引擎與效能。第一個要懂的就是索引——為什麼加了它查詢快幾百倍,又為什麼有時加了卻好像沒用。這兩個問題的答案,都藏在它的資料結構裡:B-tree。 沒有索引時,WHERE id = 50…

#sql#performance

Reliability 可靠 出錯也能正常運作 · 容錯,不是無錯 · fault ≠ failure · 主動製造故障來測 硬體 / 軟體 / 人為錯誤 Scalability 可擴展 負載增加也扛得住 · 先描述「負載長相」 · 用 percentile 看效能 · scale up vs scale out 加機器前,先懂負載 Maintainability 可維護 讓人好好在上面工作 · Operability 好維運 · Simplicity 少意外複雜 · Evolvability 易演進 複雜的代價是別人來付 三個「非功能需求」——功能決定能不能用,這三個決定長期活不活得下去

可靠、可擴展、可維護:資料系統的三個目標

· tech · 約 5 分鐘 · 📚 Designing Data-Intensive Applications 讀書筆記 #1

開一個新系列:讀 Martin Kleppmann 的 Designing Data-Intensive Applications(簡稱 DDIA)。它跟 FoDE 互補——FoDE 是資料工程的實務…

#distributed-systems#book-notes

直接 GROUP BY date_trunc 日期筆數 7/013 7/025 7/03 沒這列 ✗ 7/042 補洞 generate_series + COALESCE 0 7/013 7/025 7/030 7/042 GROUP BY 只產出「有資料」的桶 —— 沒訂單的 7/03 整列消失,時間序列就斷了

時間分桶與 SCD:SQL 處理時間的兩個坑

· tech · 約 3 分鐘 · 📚 SQL 我以為我懂 #8

接著上一篇的「區間」,這篇講時間在 SQL 裡的兩個坑——它們都源自同一件事:時間是連續的,但你的資料是離散的事件。 中間必然有「什麼都沒發生」的空隙,以及「值變了但你沒記」的變化。SQL 不會自動幫…

#sql#data-engineering

你的服務 ① Latency 延遲 請求要多久才回? 分開看「成功」與「失敗」的延遲 ② Traffic 流量 系統現在多忙? QPS / 每秒請求數 ③ Errors 錯誤 多少請求失敗了? 失敗率(含「回 200 但內容是錯的」) ④ Saturation 飽和度 離極限還有多近? 資源用了幾成 → 最能預警 前三個 = 使用者體感(可直接當 SLI);第四個「飽和度」= 還能撐多久的預警

監控:四個黃金訊號

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #4

上一篇說 SLI 是量到的可靠度數字——而那些數字,就來自監控。但監控最容易走歪的地方,是把它當成「收集越多數字越好」,結果儀表板上一百個圖,真出事時反而找不到重點。這篇講 Google 給的精煉答案…

#sre#monitoring

是不是 toil?看這六個特徵 手動 —— 要人一步步動手做 重複 —— 做過很多次、之後還會再做 可自動化 —— 機器能做,只是還沒有人去寫 無長期價值 —— 做完,系統並沒有變得更好 隨規模線性成長 —— 服務變大,它就跟著變多 被動反應 —— 被觸發才做,不是主動規劃出來的 符合越多 → 越是 toil。注意:開會、規劃、寫文件是 overhead,不算 toil

消除 Toil:把重複的維運當成待消滅的 bug

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #3

第一篇說 SRE 的內核是「維運可以被工程化」。這篇講的 toil,就是那個要被工程化掉的東西。很多人以為 toil 就是「辛苦的工作」,其實不是——它是一類有明確特徵的工作,而且如果你不主動砍它,它…

#sre#reliability

① 完全相同的列 (1, A, 100) (1, A, 100) (1, A, 100) DISTINCT (1, A, 100) 整列一模一樣 → 去掉多的 DISTINCT / GROUP BY 就能解 ② 同一 key、多筆版本 user1 · 待付 · 2/01 user1 · 已付 · 2/03 user1 · 退款 · 2/05 ROW_NUMBER 留最新 user1 · 退款 · 2/05 列不相同 → DISTINCT 沒用 要挑「代表」那一筆

去重的正確姿勢:DISTINCT 不是唯一解

· tech · 約 4 分鐘 · 📚 SQL 我以為我懂 #6

資料重複幾乎是資料工程的日常:pipeline 重跑重複匯入、CDC 把同一筆的多個版本都撈進來、JOIN 的 fan-out 把列複製。很多人一講到去重就 DISTINCT——但去重根本不只 DIS…

#sql#data-engineering

輸入(orders):4 列 A · 100 A · 250 B · 80 B · 120 GROUP BY(收合) A · SUM 350 B · SUM 200 4 列 → 2 列(每組收成一列) SUM() OVER(不收合) A · 100組計 350 A · 250組計 350 B · 80組計 200 B · 120組計 200 4 列 → 4 列(每列多一欄看整組的值)

Window Function:不收合的聚合

· tech · 約 4 分鐘 · 📚 SQL 我以為我懂 #5

上一篇的 GROUP BY 把每組收合成一列。但你一定遇過這種需求:「我想要整組的計算,又想保留每一列。」 例如——在每一筆訂單旁邊,標上它佔該客戶總額的比例;或在每個月的營收旁,標上跟上個月的差。收…

#sql#concept#window-function

99.0% 100% SLA 99.5% 對外合約·違反賠錢 SLO 99.9% 內部目標(拚這個) 違約區 沒達標(但還沒違約) 健康區 ← SLI 99.95% 實際量到的 安全 buffer:內部先痛,別讓客戶先痛 門檻鬆緊:SLA(鬆) < SLO(嚴) ≤ SLI(健康時的實測)

SLI / SLO / SLA:一個量測、一個目標、一個合約

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #2

上一篇說 error budget = 1 − SLO。但 SLO 是什麼?它跟另外兩個幾乎人人混用的縮寫——SLI、SLA——又差在哪?這三個字分不清,可靠度就無從談起。一句話先記住:SLI 是你「…

#sre#reliability

可靠度目標訂在 99.9%,不是 100% 剩下的 0.1% 不是遺憾,是可以花的「預算」 Error Budget = 1 − SLO 服務成功 ≥ 99.9%(SLO 目標) 失敗 ≤ 0.1% (刻意放大顯示) ≈ 一個月約 43 分鐘可壞 追到 100%:成本爆炸、邊際效益趨近零——使用者還分不出 99.9% 和 100% (他手上的網路、手機、Wi-Fi 本來就沒那麼可靠)

SRE 是什麼?從 Error Budget 講起

· tech · 約 4 分鐘 · 📚 Google SRE 讀書筆記 #1

「SRE」這個詞很紅,但很常被誤解成「高級一點的維運」或「會寫程式的 SysAdmin」。讀完 Google 這本書我的體會是:它的靈魂根本不在職稱,而在一個轉念 + 一個機制——「100% 可靠不是…

#sre#reliability

原始列(orders) A · amount 100 A · amount 250 B · amount 80 B · amount 120 B · amount 50 GROUP BY customer 收合後:每組一列 customer = ACOUNT=2 · SUM=350 customer = BCOUNT=3 · SUM=250 amount 一組有多個值(100/250)→ 不能裸選,要用聚合(SUM/AVG…)壓成一個數

GROUP BY:把多列收合成一列

· tech · 約 5 分鐘 · 📚 SQL 我以為我懂 #4

GROUP BY 每個人都會寫,但幾乎每個人也都被那句 column "..." must appear in the GROUP BY clause 擋過,而且常常搞不懂「我就選個欄位,為什麼不行?…

#sql#concept

SQL 的邏輯有三個值(不是兩個) TRUE 條件成立 FALSE 條件不成立 UNKNOWN 不知道 ↑ 任何跟 NULL 的比較都落這裡 age = NULL、age <> NULL 都是 WHERE / ON / HAVING 只放行 TRUE TRUE → ✓ 保留 FALSE → ✗ 丟 UNKNOWN → ✗ 丟

NULL 不是值,是「不知道」

· tech · 約 6 分鐘 · 📚 SQL 我以為我懂 #3

上一篇的 LEFT JOIN,會幫沒配到的列補上 NULL。那個 NULL 就是這篇的主角——它是無數 SQL bug 的源頭,而根本原因只有一句:NULL 不是一個值,是「不知道」。 一旦你把它讀成…

#sql#concept

右表 R:訂單(user 欄) A A B 左表 L:使用者 使用者 A 使用者 B 使用者 C A 配到 2 筆 → 結果 A 出現兩次 B 配到 1 筆 C 配不到 → INNER 丟掉 LEFT 補 (C, NULL) ON 符合(留下) 不符合(丟棄)

JOIN 的真相:先算笛卡爾積,再過濾

· tech · 約 6 分鐘 · 📚 SQL 我以為我懂 #2

上一篇把「你寫的順序不是它跑的順序」講清楚了。這篇用同一把鑰匙拆穿 JOIN。很多人把 JOIN 想成「把兩張表黏在一起」,然後死背 INNER/LEFT/RIGHT/FULL 各自的行為。但其實它們…

#sql#concept

你的 code DataFrame API 或 Spark SQL —— 兩者等價 Logical Plan ·「要什麼」 解析出你引用的表與欄位,還沒最佳化 Catalyst 最佳化器 filter 下推 · 剪掉沒用的欄位 · 挑 join 策略 Physical Plan ·「怎麼做」 Exchange(= shuffle)、join 策略都定案 執行 切成 stage / task,丟到 executor 上跑

讀懂 Spark 執行計畫:.explain() 到底在說什麼

· tech · 約 5 分鐘 · 📚 Spark 學習筆記 #6

這個系列一路講下來,有兩句話反覆出現:「相信 Catalyst 最佳化器」、「打開 Spark UI 找瓶頸」。但我一直沒回答一個問題:你到底要怎麼看 Spark 做了什麼? 相信最佳化器不該是盲信—…

#spark#data-engineering#performance

呼叫方 只認 web 這名字 Service:web 固定 IP 10.96.0.10 · DNS web.*.svc selector: app=web 自動負載均衡到健康 Pod Pod · 10.1.2.7 ✓ 健康 Pod · IP 會變 掛了換新:.8 → .31 Pod · 10.1.4.2 ✓ 健康

Service:擋在短命 Pod 前面的固定門牌

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #4

第二篇留了一個問題:既然 Pod 是短命的、被換掉就有新的 IP,那別的服務要怎麼穩定找到它?你總不能把某顆 Pod 的 IP 寫死在設定裡——它下一秒可能就不在了。這篇的主角 Service,就是 …

#kubernetes#concept#networking

你這樣寫 DB 這樣跑(邏輯順序) SELECT FROM / JOIN WHERE GROUP BY HAVING ORDER BY LIMIT ① FROM / JOIN ② WHERE ③ GROUP BY ④ HAVING ⑤ SELECT ⑥ ORDER BY ⑦ LIMIT

你寫的 SQL 不是照你寫的順序跑

· tech · 約 4 分鐘 · 📚 SQL 我以為我懂 #1

你寫 SQL,幾乎都是 SELECT 開頭。寫久了很自然會以為:它就是從 SELECT 開始跑的。但不是——SQL 是宣告式的,你寫的是「要什麼」,引擎自己決定「怎麼跑、照什麼順序跑」,而它跑的順序跟…

#sql#concept

會變的工具 —— 一直換、越來越簡單 當紅框架 託管服務 新平台 明年的工具 ↑ 三年後可能沒人用 ↓ 押三十年不太會錯 不變的地基 源頭 擷取 儲存 轉換 服務 暗流 安全 · 資料管理 · 編排 · 軟體工程 · DataOps

資料工程的未來:工具會變、地基不變,讀《Fundamentals of Data Engineering》Ch.11(完結)

· tech · 約 3 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #11

十一章走到這裡,最後一個問題:資料工程的未來會長怎樣? 書的答案既讓人安心、又有點反直覺 —— 工具會一直變、而且越來越簡單;但底下那套生命週期與暗流,不會變。 這一篇,也是這個系列的完結。 這章把整…

#data-engineering#book-notes

Deployment 期望:replicas = 3 · image v1 ReplicaSet 確保永遠有 3 個 Pod Pod ✓ 健康 Pod ✗ 掛了 Pod ✓ 健康 少一個 → ReplicaSet 觀察到落差 → 立刻補一個新的回到 3 個

Deployment 與自我修復:reconcile loop 的實戰

· tech · 約 6 分鐘 · 📚 Kubernetes 學習筆記 #3

第一篇給了靈魂(reconcile loop),第二篇給了原子(Pod)。但實務上你幾乎不會手動去建一個 Pod —— 你宣告的是 Deployment,而它正是 reconcile loop 最實用…

#kubernetes#concept

Pod 最小部署單位・排程與伸縮的單位 容器:app 你的服務 容器:sidecar 選配(log / proxy) 共享:一個 IP(彼此用 localhost 通)· 共享 Volume

Pod、Node、Scheduler:Kubernetes 叢集的三個原子

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #2

上一篇講了 K8s 的靈魂:你宣告期望,reconcile loop 不斷把現實拉過去。但那句「我要 3 個」——3 個什麼?落在哪台機器上?誰決定放哪? 這篇把叢集最基本的三個原子講清楚:Pod、N…

#kubernetes#concept

期望狀態 你宣告:replicas = 3 Controller 控制迴圈 比較 & 修正 實際狀態 現在只有 2 個 ① 讀期望 ② 動作 ③ 觀察 2 → 建 1 個 → 3 ✓ reconcile loop:不斷比較期望與實際,有落差就修正 —— 這就是 K8s 的靈魂

Kubernetes 是什麼:從「跑容器」到「宣告你要的狀態」

· tech · 約 5 分鐘 · 📚 Kubernetes 學習筆記 #1

很多人學 Kubernetes(K8s)覺得難,是因為一上來就被 kubectl、一堆 YAML 欄位、幾十種資源名詞淹沒。但其實 K8s 只有一個核心觀念,抓住它,後面全部都是同一句話的變形。這個系…

#kubernetes#concept

敏感資料 PII・金流… 當資產 · 價值 分析洞察 訓練 ML 模型 支撐決策 當負債 · 風險 外洩 合規罰款 勒索軟體 信任崩壞 每一筆敏感資料都同時是這兩面 —— 所以:只收該收的、該刪就刪

最該重視卻最被忽略的一章:安全與隱私,讀《Fundamentals of Data Engineering》Ch.10

· tech · 約 4 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #10

走完服務,生命週期還有一條貫穿全程的暗流沒單獨講:安全與隱私。書把它排在很後面,卻直說這是最重要、也最常被忽略的一章。而它最反直覺的第一句話是 —— 安全主要是「人」的問題,不是「工具」的問題。 大多…

#data-engineering#book-notes#security

建模好的資料 Warehouse · Lakehouse 商業分析 BI・儀表板 嵌入式分析 產品內給客戶看 機器學習 特徵・訓練資料 Reverse ETL 回灌 CRM・廣告平台

資料的最後一哩:服務給分析與 ML,讀《Fundamentals of Data Engineering》Ch.9

· tech · 約 4 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #9

前面幾章一路走過源頭、儲存、擷取、建模 —— 但這些辛苦,只有在有人真的拿去用的那一刻才變現。這章講生命週期的最後一站:服務(Serving)。而它的第一原則,只有兩個字。 書把話講得很重:沒人會用他…

#data-engineering#book-notes#data-serving

正規化 Normalized orders customers products 少重複・寫入一致 但查詢要多次 join 反正規化 · 寬表 one big table(寬表) 重複多,但查詢少 join 適合欄式倉儲分析 OLTP 交易(寫多) OLAP 分析(讀多)

把資料變好用:查詢、建模與轉換,讀《Fundamentals of Data Engineering》Ch.8

· tech · 約 5 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #8

資料擷取進來、存好了,接下來的問題是:怎麼把它變成真正好用的東西? 這章給了三支柱 —— 查詢(Query)、建模(Modeling)、轉換(Transformation)。它們合起來,把「一堆原始資…

#data-engineering#book-notes#data-modeling

批次 Batch 小時 ~ 天 定時/定量・成熟(預設) 微批次 Micro-batch 秒 ~ 分 每一小批處理一次 串流 Streaming 毫秒 ~ 秒 逐筆事件・即時 高延遲・低複雜・便宜 低延遲・高複雜・貴 每往即時走一步,就多付一分複雜度與成本

把資料搬進來:批次還是串流?讀《Fundamentals of Data Engineering》Ch.7

· tech · 約 5 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #7

源頭生出資料、儲存準備好接,中間那條把資料搬進來的動作,就是這章的主角:Ingestion(擷取)。它是生命週期的第二站,也是最多人一上來就糾結「要不要即時」的地方。這章最該先想清楚的一句話是 —— …

#data-engineering#book-notes#ingestion

↑ 越上面:越快、越貴、容量越小 CPU 快取~1 ns RAM 記憶體~100 ns · 揮發 SSD~0.1 ms HDD 磁碟(轉盤)~10 ms 物件儲存(S3 / GCS)~100 ms · 超便宜 封存 / 冷儲存分鐘~小時 · 最便宜 ↓ 越下面:越慢、越便宜、容量越大

資料要存在哪:儲存的階層與抽象,讀《Fundamentals of Data Engineering》Ch.6

· tech · 約 7 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #6

上一篇講資料從源頭生出來。生出來之後第一件事就是:存去哪? 這章談儲存 —— 而它最反直覺的一點是:儲存不是「一個東西」,而是一整條從奈秒到小時、從天價到白菜價的階層。 看懂這條階層,後面所有「該放哪…

#data-engineering#book-notes

K8s Control Plane · Scheduler 依 resource request / affinity 決定 pod 落哪個 node Node 1 on-demand 池(穩定) Node 2 spot 池 Node 3 spot 池 Airflow Scheduler Airflow Webserver Airflow Triggerer Metadata DBPersistentVolume(有狀態) Spark Driver Spark Executor Spark Executor Spark Executor Spark Executor Driver 申請的 executor 由 Scheduler 散到各 node Executor 讀取來源 / 寫回結果 Business DB叢集外的營運資料源 / 輸出 Airflow pod Spark Driver Spark Executor Metadata DB Business DB

Airflow + Spark 跑在 K8s 上:不同的 node 怎麼跑不同的 pod

· tech · 約 11 分鐘 · 📚 Kubernetes 學習筆記 #8

Airflow 負責「什麼時候、用什麼順序」跑作業,Spark 負責「把大資料算完」。當這兩個東西都搬到 Kubernetes 上,最常見的困惑是:到底有哪些東西在跑、它們各自是不是一個 pod、又被…

#kubernetes#airflow#spark#data-engineering

源頭系統 — 別人擁有、會自己改變 應用資料庫(OLTP) API / SaaS 檔案 / 日誌 IoT / 感測器 訊息佇列 / 串流 你的邊界 Ingestion 擷取 你的生命週期從這開始 下游

資料從哪來:源頭系統與資料生成,讀《Fundamentals of Data Engineering》Ch.5

· tech · 約 6 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #5

前四章在講大方向 —— 生命週期、架構、選技術。從這章開始,書一階一階走進生命週期的每個環節。第一站是最前面、也最容易被工程師輕看的一段:資料到底是怎麼、在哪裡被生出來的? 這章最該記住的一句話是 —…

#data-engineering#book-notes

易變的表層 — 框架・函式庫・當紅工具 當紅框架 新潮工具 函式庫 平台 SDK 會隨潮流來來去去 → 設計成可抽換 不變的地基 物件儲存 · SQL · 網路 · Unix / bash

技術到底該怎麼選:讀《Fundamentals of Data Engineering》Ch.4

· tech · 約 5 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #4

上一篇講架構(why);這一章接著問:在那個架構底下,技術(how)到底該怎麼選? 這章最該先釘進腦袋的一句話是 —— 先有架構,才選技術,不是反過來。 工具是手段,被架構的取捨牽著走;一上來就問「要…

#data-engineering#book-notes

無界輸入表 t1 一批 t2 一批 t3 新到 …持續 append 表一直長高 同一個查詢groupBy/agg… 結果表(持續更新) aggregate result

Structured Streaming 入門:把串流當成一張無界的表

· tech · 約 6 分鐘 · 📚 Spark 學習筆記 #5

前四篇都在講批次的 Spark —— 是什麼、DataFrame 實戰、shuffle 調校、怎麼跑起來。但資料不會等你湊成一批才來:訂單、點擊、日誌是持續流進來的。這篇講 Spark 處理串流的方式…

#spark#data-engineering#stream-processing

雙向門(可逆) 現狀 新方案 回得來 → 決策可以快 單向門(不可逆) 現狀 新方案 ✕ 回不去 → 決策要慎重

好的資料架構怎麼設計:讀《Fundamentals of Data Engineering》Ch.3

· tech · 約 4 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #3

上一篇給了生命週期的全貌(資料在做什麼);這一章問的是 —— 怎麼把承載它的系統設計得「好」? 這章最反直覺、也最該記住的一句話是:好的架構不是一張固定的藍圖,而是一個「用權衡換取彈性與可逆」的決策過…

#data-engineering#book-notes#architecture

branch full_reload ✓ incremental ⊘ skip join none_failed_…

Airflow 複雜流程控制:branching、trigger rules、TaskGroup、動態任務

· tech · 約 5 分鐘 · 📚 Airflow 學習筆記 #6

到目前為止,我們的 DAG 都是「固定的幾個 task、照線跑完」。但真實流程沒這麼乖:有時要依條件走不同分支、某個 task 失敗了清理工作還是得跑、幾十個相似 task 要收整齊、甚至執行期才知道…

#airflow#data-engineering#dag-design

Generation 生成 Ingestion 攝取 Transformation 轉換 Serving 服務 Storage 儲存(橫跨中間三階段) Undercurrents — 撐起整條生命週期的六條暗流 Security 安全 Data Management DataOps Data Architecture Orchestration 編排 Software Engineering

資料工程生命週期:讀《Fundamentals of Data Engineering》Ch.2

· tech · 約 4 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #2

上一篇給了定義,這一章給的是全書的骨架 —— 資料工程生命週期(data engineering lifecycle)。這本書最有價值的貢獻,就是用這個框架把「資料工程在做什麼」講清楚:五個階段 + …

#data-engineering#book-notes#lifecycle

AI / 深度學習 學習・最佳化(A/B、ML) 彙整・標註(分析、指標) 搬運・儲存(pipeline、ETL) 收集(紀錄、感測、外部資料) ML / AI 資料工程

資料工程是什麼:讀《Fundamentals of Data Engineering》Ch.1

· tech · 約 4 分鐘 · 📚 Fundamentals of Data Engineering 讀書筆記 #1

我開一個新系列,讀 Joe Reis 與 Matt Housley 的 Fundamentals of Data Engineering。這本書最大的價值,是把「資料工程」這個常被講得很模糊的職能,收…

#data-engineering#book-notes

痛點還沒到 → 輕量解 本機 PySpark · dbt + 倉儲 直接打 API · 兩層架構 成本低、好維護 痛點到了 → 才上重武器 Spark 叢集 · Kafka Airflow · 多層 Medallion 威力強,但每天要餵養 痛點臨界點 痛點量級(資料量 · 來源數 · 編排複雜度)→

先確認痛點,再上重武器

· tech · 約 2 分鐘

這是一篇概念筆記 —— 一個我反覆在用的判斷,獨立成篇,讓其他文章可以連回來。 一句話:在引入任何重型工具或架構之前,先確認你的痛點真的到了需要它的量級。 沒到,就別上 —— 因為重武器的成本不在「裝…

#concept#data-engineering

壓縮前 k1:a k2:x k1:b k3:p k2:y k1:c cleaner:每個 key 留最後一筆 壓縮後 k3:p k2:y k1:c

Kafka 維運與部署:KRaft、retention/compaction 與監控

· tech · 約 7 分鐘 · 📚 Kafka 學習筆記 #5

前四篇講的是「Kafka 怎麼用」—— 可重播的 log、核心模型、投遞保證、生態系。這篇收尾,換個視角:當 Kafka 真的上線、要長期穩定跑,維運面得懂哪些事?四塊 —— KRaft(叢集怎麼管自…

#kafka#data-engineering#operations

Kafka topics / log MySQL / API 來源系統 DW / ES / S3 下游系統 Connect source Connect sink Schema Registry Kafka Streams 讀 → 運算 → 寫回

Kafka 生態系:Connect、Schema Registry 與 Streams

· tech · 約 8 分鐘 · 📚 Kafka 學習筆記 #4

前三篇都在講 Kafka broker 本身 —— 可重播的 log、核心模型、投遞保證。但真實世界裡你幾乎不會「只用 broker」:資料要從別的系統搬進來、事件的長相要有人管、流上還得做轉換與聚合…

#kafka#data-engineering#stream-processing

DAG task @task Operator 做一件事 Hook 連線 client 外部系統 DB / S3 / API Connection conn_id:帳密 + 端點 提供帳密

Airflow 怎麼連外部系統:Provider、Operator、Hook、Sensor

· tech · 約 6 分鐘 · 📚 Airflow 學習筆記 #5

前面幾篇都在講 Airflow 的內部機制 —— 排程、任務間傳資料。但真正的 pipeline 一定得碰外面的世界:查一個資料庫、丟檔案到 S3、打一支 HTTP API、等一個檔案到齊。這篇講 A…

#airflow#data-engineering#integration

Producer acks? Broker 複本 / ISR Consumer commit 時機 ① 丟失 / 重複 ② 機器掛了會不會丟 ③ 重做 / 跳過

Kafka 的投遞保證:acks、ISR 與 at-least-once / exactly-once

· tech · 約 8 分鐘 · 📚 Kafka 學習筆記 #3

第二篇講完事件「怎麼擺、誰來讀」,留了一個更尖銳的問題:崩潰重啟後,一筆事件到底會被重複處理、還是漏掉?這篇把 Kafka 的可靠性講透 —— acks、複本與 ISR、commit 時機,以及 at…

#kafka#data-engineering#reliability

Driver 排程 task ① 申請資源 Cluster Manager ② 啟動 Executor task + cache Executor task + cache Executor task + cache ③ 派 task

把 Spark 跑起來:從本機到叢集與 managed 平台

· tech · 約 6 分鐘 · 📚 Spark 學習筆記 #4

前三篇都在講 Spark 怎麼寫、怎麼跑得快(是什麼、DataFrame 實戰、shuffle 調校)。但同一段程式碼,在你筆電上跑、跟在一個幾十台機器的叢集上跑,中間到底發生什麼事?這篇講 runt…

#spark#data-engineering#deployment

task A XCom 訊息板 (metadata DB) task B push pull 只放「小東西」:id、筆數、旗標、檔案路徑… 大資料請寫到 S3 / 檔案,XCom 只傳「路徑」

Airflow 任務間怎麼傳資料:XCom、TaskFlow 進階與 params

· tech · 約 4 分鐘 · 📚 Airflow 學習筆記 #4

上一篇講完排程,這篇處理一個很實際的問題:一個 task 算出來的東西,怎麼交給下一個 task? Airflow 的答案是 XCom,而 TaskFlow 把它包得幾乎看不見。順帶也講 params…

#airflow#data-engineering#xcom

narrow filter/select 分區1 分區2 分區3 分區1 分區2 分區3 1對1,不搬 wide groupBy/join 分區1 分區2 分區3 shuffle:跨分區重新分配 輸出1 輸出2 輸出3

Spark DataFrame 實戰:讀取、轉換、寫出與 Spark SQL

· tech · 約 4 分鐘 · 📚 Spark 學習筆記 #2

上一篇把 Spark 的概念講完了:Driver / Executor、分區、惰性求值、shuffle。這篇動手用 DataFrame 實際轉一份資料 —— 讀進來、清洗、彙總、寫出去,並看看 Spa…

#spark#data-engineering#pyspark

6/18 00:00 6/19 00:00 6/20 00:00 資料區間 = 6/18 資料區間 = 6/19 6/18 的 run 在這觸發 6/19 的 run

Airflow 排程的真相:data interval、catchup 與 backfill

· tech · 約 5 分鐘 · 📚 Airflow 學習筆記 #3

上一篇我們把 DAG 跑起來了,還特別把 catchup 設成 False「保平安」。這篇就來拆解 Airflow 最反直覺、也最多人卡住的部分:排程到底怎麼運作。搞懂這一段,你才真的會用 Airfl…

#airflow#data-engineering#scheduling

./dags/*.py 你寫的 DAG Scheduler Web UI :8080 Worker 瀏覽器 掛載/解析 顯示 派送任務

跑起第一個 Airflow:Docker 環境 + 你的第一個 DAG

· tech · 約 4 分鐘 · 📚 Airflow 學習筆記 #2

上一篇把 Airflow 的概念與架構講清楚了;這篇動手把它在本機跑起來,寫出第一個 DAG,並在 Web UI 上看著它跑完。目標很單純:從零到「我親眼看到自己的 DAG 在介面上變綠」。 方式 指…

#airflow#data-engineering#docker

Driver SparkSession · DAG Cluster Manager YARN / K8s Executor tasks + 分區 Executor tasks + 分區 Executor tasks + 分區 申請資源

Apache Spark 是什麼?一篇搞懂分散式資料處理

· tech · 約 5 分鐘 · 📚 Spark 學習筆記 #1

一句話:Apache Spark 是一個把「大到單台機器裝不下、算不完」的資料,切成很多份、分散到一整個叢集上平行運算的引擎。它源自 UC Berkeley(2009),2014 成為 Apache …

#spark#data-engineering#pyspark

事實 感受 教訓

領導力 - 用日記看見自己

· tech · 約 2 分鐘 · 📚 成為 Tech Leader 讀書筆記 #6

上一篇談到,「看不到自己」是創新的第一道障礙——你改不掉一個你沒看見的東西。作者給的解法意外地簡單:每天花五分鐘寫日記。而且最有意思的是,光是「開始寫」這個動作本身,就能同時訓練與觀察好幾件事。 聽到…

#leadership#innovation

想法新觀點 ① 看不到自己 ② 沒問題綜合症 ③ 只有一個正解 創新被擋住

領導力 - 創新的三大障礙

· tech · 約 2 分鐘 · 📚 成為 Tech Leader 讀書筆記 #5

創新不是少數天才的靈光,而是一種「環境允許你提出不同想法」的能力(呼應 MOI 裡的 Innovation)。但有三種心態會在源頭就把創新擋下來——而且它們往往是無意識的。 第一道牆是看不清自己的行為…

#leadership#innovation

領導力 - 成長模型

· tech · 約 3 分鐘 · 📚 成為 Tech Leader 讀書筆記 #3

成長模型描述的是「技能隨時間怎麼變化」。同一條成長曲線,在不同的觀察尺度下,會呈現完全不同的形狀。下面從最遠的宏觀、一路拉近到最貼近真實的微觀。 只要每天持續進步,把時間尺度拉得夠遠來看,技能的成長速…

#leadership

領導者 M · Motivation激勵讓人願意動起來 O · Organization組織讓人有效率有秩序 I · Innovation創新讓人敢提不同想法 三者合起來 = 領導者塑造的團隊環境

領導力 - MOI

· tech · 約 5 分鐘 · 📚 成為 Tech Leader 讀書筆記 #2

領導方式模型就是透過幾項指標來描述一個環境,MOI模型就是其中一種描述方式 MOI 模型包含三個構面:Motivation(激勵)、Organization(組織)、Innovation(創新)。每個…

#leadership

程式抽籤被質疑黑箱該如何處理

· tech · 約 5 分鐘

前陣子幫目前社區實作了一個簡單的車位抽籤頁面,後來其他管理委員們認為可能會被住戶質疑這程式不可信任,可能有黑箱疑慮,藉此研究了一下如何證明這個抽籤流程沒有黑箱。 - 複雜的說是抽籤的過程可受某方控制達…