#distributed-systems

手機 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

傳統:一個盒子,全部捆在一起 儲存引擎 索引 快取 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

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

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

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

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

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

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

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

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

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

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

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

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

#redis#distributed-systems

取得鎖:一行原子命令 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

資料模型:一棵像檔案系統的樹(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

土砲選 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

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

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

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

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

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

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