<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>system design on Bloggings</title>
        <link>https://theoutsidelaine.com/tags/system-design/</link>
        <description>Recent content in system design on Bloggings</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Sat, 18 May 2024 20:00:00 +0000</lastBuildDate><atom:link href="https://theoutsidelaine.com/tags/system-design/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>System Design (IV)</title>
        <link>https://theoutsidelaine.com/p/system-design-4/</link>
        <pubDate>Sat, 18 May 2024 20:00:00 +0000</pubDate>
        
        <guid>https://theoutsidelaine.com/p/system-design-4/</guid>
        <description>&lt;img src="https://theoutsidelaine.com/p/system-design-4/cover.png" alt="Featured image of post System Design (IV)" /&gt;&lt;p&gt;這禮拜繼續讀 &amp;lt;System Design Interview- An insider&amp;rsquo;s guide&amp;gt; 第四章。&lt;/p&gt;
&lt;h1 id=&#34;chapter-4-設計-rate-limiter&#34;&gt;Chapter 4: 設計 Rate Limiter&lt;/h1&gt;
&lt;p&gt;這章開始作者用實戰的方法帶大家了解，每一種不同的系統的特性是什麼、以及要設計這樣的元件可以怎麼去做思考。&lt;/p&gt;
&lt;p&gt;首先第一個設計的元件就是 Rate Limiter (網路限速器、限流器)。如果面試時，被要求設計一個 rate limiter，你可以怎麼做？&lt;/p&gt;
&lt;p&gt;所謂的 rate limiter簡單來說，就是一個可以限制 client 在指定時段內發送 request 數量的元件。比如：user 每秒可以發幾則貼文、user 每天只能領幾次的獎勵。他的優點是可以防止 server overload, 進而優化資源分配、降低server成本、並避免 dos 攻擊。&lt;/p&gt;
&lt;h2 id=&#34;第一步驟瞭解問題並確立設計的範圍&#34;&gt;第一步驟：瞭解問題，並確立設計的範圍&lt;/h2&gt;
&lt;p&gt;可以問的問題有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;哪一種 rate limiter: client side or server side?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;這個問題屬於明知故問型的提問，因為 client side rate limiter 可控性不高、可靠性也不高。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;是否要根據 ip, user_id etc 去追蹤 api request?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系統的規模大小？for 大公司 or 小新創?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系統是否需要運作於分散式環境？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;這個 rate limiter 需要做成一個單獨的服務、或是實作於應用程式中？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;是否需要通知受到限制的 user?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;根據回答，可能可以匯總的系統需求如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;必須要準確限制 request -&amp;gt; (：演算法選擇)&lt;/li&gt;
&lt;li&gt;必須要盡可能使用少一點記憶體 -&amp;gt; (：演算法選擇)&lt;/li&gt;
&lt;li&gt;因為系統運作於分散式環境，所以採用分散式做法：多 server 共用一個 rate limiter -&amp;gt; (：rate limiter 實作位置選擇)&lt;/li&gt;
&lt;li&gt;others: 需要高容錯、異常處理&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;第二步驟提出高階設計並取得認可&#34;&gt;第二步驟：提出高階設計，並取得認可&lt;/h2&gt;
&lt;p&gt;這邊主要要思考兩點：(1) rate limiter 施作位置 (2) rate limiter 演算法選擇&lt;/p&gt;
&lt;h3 id=&#34;1-rate-limiter-施作位置&#34;&gt;1. rate limiter 施作位置&lt;/h3&gt;
&lt;p&gt;這邊主要考量的是：放置於api server, 或是施作於 api gateway（microservice 中的一個中介元件，用途廣泛，功能包含身份驗證、白名單etc）.&lt;/p&gt;
&lt;p&gt;書中列出幾個可以拿出來討論的點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;目前公司是否已經使用微服務架構、並且此架構已用到 api gateway? 有的話，或許可以考慮直接施作於 api gateway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所選用的演算法，是否可以於 api gateway中選用，或是需要自製於 server 端？&lt;/p&gt;
&lt;p&gt;-&amp;gt; 2-1. 目前公司使用的程式語言，是否支援實作 server 端 rate limiter?&lt;/p&gt;
&lt;p&gt;-&amp;gt; 2-2. 目前公司提供的時間、成本，是否支援開發 server 端 rate limiter?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;2-rate-limiter-演算法選擇&#34;&gt;2. rate limiter 演算法選擇&lt;/h3&gt;
&lt;p&gt;有五個比較常見的演算法如下：&lt;/p&gt;
&lt;h4 id=&#34;1-token-bucket&#34;&gt;(1) Token Bucket&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;步驟：有兩個控制變數，分別是 bucket 容量、token 填入速度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每當一個 request 進來，系統檢查 bucket
&lt;ul&gt;
&lt;li&gt;如果 token 數量足夠，則消耗一個 token 給該 request，並使 request 通過。&lt;/li&gt;
&lt;li&gt;如果 token 數量不足夠，則不使 request 通過。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;固定一個時間之內 refill bucket&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一個系統可以設計一或多個 bucket&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多個 bucket 的狀況：要針對每一個 api 做比較嚴格的 rate limit&lt;/li&gt;
&lt;li&gt;一個 bucket 的狀況：系統很鬆，每秒可以接收極大量的 total requests&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;容易實作&lt;/li&gt;
&lt;li&gt;bucket 大小固定、有限，因此有比較好的 memory usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可以允許短時間內的流量爆炸&lt;/strong&gt;：它不限定某個時間只能有幾個request, 只要 bucket 裡面還有refilled tokens, 就可以通過 request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;書中提到說要 tune 這兩個參數不是一件容易的事&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;應用該演算法的公司：Amazon, Stripe&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;2-leaking-bucket&#34;&gt;(2) Leaking Bucket&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;步驟：有兩個控制變數，分別是 queue 容量、request 處理速度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每當一個 request 進來，系統檢查 queue
&lt;ul&gt;
&lt;li&gt;如果 queue not full, 便把 request 加入 queue&lt;/li&gt;
&lt;li&gt;如果 queue full, 便丟棄 request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;固定一個 request process rate&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;queue 大小固定、有限，因此有比較好的 memory usage&lt;/li&gt;
&lt;li&gt;request process rate 是固定速率，所以適合需要穩定 outflow rate 、不會有突然流量爆炸的狀況。&lt;/li&gt;
&lt;li&gt;(somehow 書中沒有提到這個作法是容易實作的)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果流量爆炸，新 request 處理效率會變很差&lt;/li&gt;
&lt;li&gt;書中提到說要 tune 這兩個參數也不是一件容易的事&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;應用該演算法的公司：Shopify&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;3-fixed-window-counter&#34;&gt;(3) Fixed Window Counter&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;步驟：每個固定的 time slot (eg: 1分鐘、5分鐘) 有固定的 request capacity 與一個 counter&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每當一個 request 進來，系統
&lt;ul&gt;
&lt;li&gt;counter ++&lt;/li&gt;
&lt;li&gt;如果 ++ 之後 capacity 超過，則丟棄 request&lt;/li&gt;
&lt;li&gt;如果 ++ 之後 capacity 未超過，則通過 request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;重要特性（問題）：
&lt;ul&gt;
&lt;li&gt;兩個 time slot request 如果恰恰好是 capacity 最大值（意即極高需求狀況），則中間切分點之 time slot(滾動視窗) 會允許了 capacity 兩倍的 request進來，導致超乎 loading 的需求被處理了。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;容易實作&lt;/li&gt;
&lt;li&gt;request capacity 固定、有限，因此有比較好的 memory usage&lt;/li&gt;
&lt;li&gt;可以被 Redis 支援&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：流量激增會有超過 loading 的需求被處理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;4-sliding-window-log&#34;&gt;(4) Sliding Window Log&lt;/h4&gt;
&lt;p&gt;這是一個有趣的演算法。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;步驟：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每當一個 request 進來，系統
&lt;ul&gt;
&lt;li&gt;將這個 request的 time stamp 加入日誌中&lt;/li&gt;
&lt;li&gt;檢查目前日誌中、「新 request 的一個 time slot」以前，是否還存有其他老request的 time stamps
&lt;ul&gt;
&lt;li&gt;有則刪除&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;檢查目前日誌中，time stamp capacity 是否超標
&lt;ul&gt;
&lt;li&gt;無則 approve request&lt;/li&gt;
&lt;li&gt;有則 reject request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;限速效果十分準確：很可以確保滾動的 time slot 也可以穩定的不超標&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;必須要額外花很多的 memory 紀錄每一個 request 的 time stamp，不會因為 request 被丟棄而消失&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;5-sliding-window-counter&#34;&gt;(5) Sliding Window Counter&lt;/h4&gt;
&lt;p&gt;這是一個融合 Fixed Window Counter 和 Sliding Windoe Log 的做法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;它主要的目的是解決 Fixed Window Counter 遇到的問題，透過施作一個「百分比公式」:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;滾動視窗的 total request = 目前視窗 request + 前一視窗 request * 前一視窗佔滾動視窗的百分比。&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不會讓滾動視窗突有超高流量出現&lt;/li&gt;
&lt;li&gt;因此有比較好的 memory usage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：限速效果不會到非常精確（不過也不會到非常不精確，根據 Cloudflare實驗結果錯誤率是 0.003% in 4b requests）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;3-rate-limiter-資料儲存地點&#34;&gt;3. rate limiter 資料儲存地點&lt;/h3&gt;
&lt;p&gt;通常會把資料放在 cache: (1)存取速度快 (2)支援過期策略。&lt;/p&gt;
&lt;p&gt;Redis 是一個常被施用的元件，如果使用 Fixed Window Counter，可以用到他的 INCR(counter ++)指令與 EXPIRE(使 counter 過期)指令。&lt;/p&gt;
&lt;h2 id=&#34;第三步驟深入設計&#34;&gt;第三步驟：深入設計&lt;/h2&gt;
&lt;p&gt;根據所設計的 rate limiter 架構，延伸的問題通常有以下兩者：&lt;/p&gt;
&lt;h3 id=&#34;1-basic-question-如果超出-rate-limit&#34;&gt;1. basic question: 如果超出 rate limit&lt;/h3&gt;
&lt;p&gt;solution: API 回傳&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;429 error response&lt;/li&gt;
&lt;li&gt;X-Ratelimit-After&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;補充: rate limiter 常傳送的 HTTP headers&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;X-Ratelimit-Remaing: window 內剩餘的可用 request數&lt;/li&gt;
&lt;li&gt;X-Ratelimit-Limit: 一個 window 總共可用的 request數&lt;/li&gt;
&lt;li&gt;X-Ratelimit-After: 當獲得 429 error, 多久之後可以再次重新發送 request&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-advanced-questions-1-當分散式系統有並行的-request-如何避免-race-condition&#34;&gt;2. advanced questions 1: 當分散式系統有並行的 request, 如何避免 race condition&lt;/h3&gt;
&lt;p&gt;solution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lock&lt;/li&gt;
&lt;li&gt;Lua script&lt;/li&gt;
&lt;li&gt;Redis ordered data structure&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;3-advanced-questions-2-當分散式系統有多個-rate-limiters-如何同步每個-rate-limiter-讓所有資料都存在於元件中使-rate-limiting可以正常運作&#34;&gt;3. advanced questions 2: 當分散式系統有多個 rate limiters, 如何同步每個 rate limiter, 讓所有資料都存在於元件中，使 rate limiting可以正常運作？&lt;/h3&gt;
&lt;p&gt;solution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Utilize Redis as centralized data storage&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;4-advanced-questions-others-效能最佳化&#34;&gt;4. advanced questions others: 效能最佳化&lt;/h3&gt;
&lt;p&gt;solution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;地理位置上，設置多資料中心&lt;/li&gt;
&lt;li&gt;使用 eventual consistency model 同步資料&lt;/li&gt;
&lt;li&gt;監控 rate limiter表現，隨時思考演算法選擇的恰當性&lt;/li&gt;
&lt;li&gt;rate limiter設置不同策略：硬限制、軟限制&lt;/li&gt;
&lt;li&gt;不僅在 HTTP 第七層實作，也可以往底下去實作 rate limiter. eg: Ip Table rate limiter.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;我覺得這章蠻有趣的，不僅初步認識與理解 rate limiter的實作概念，也知道要怎麼去討論一個 rate limiter 的設計方式。很好奇有哪些公司會選用 Sliding Window Log 這種很精細又高成本的算法的。除了算法的選擇上，如何做好 trade-off 不是一件容易的事情之外，要怎麼針對每個 follow up question 去提出適合的解決方法，比如說如何使用 Redis 解決 race condition 問題又是需要額外 survey的議題。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>System Design (III)</title>
        <link>https://theoutsidelaine.com/p/system-design-3/</link>
        <pubDate>Fri, 10 May 2024 08:00:00 +0000</pubDate>
        
        <guid>https://theoutsidelaine.com/p/system-design-3/</guid>
        <description>&lt;img src="https://theoutsidelaine.com/p/system-design-3/cover.png" alt="Featured image of post System Design (III)" /&gt;&lt;p&gt;這禮拜繼續讀 &amp;lt;System Design Interview- An insider&amp;rsquo;s guide&amp;gt; 第三章。&lt;/p&gt;
&lt;h1 id=&#34;chapter-3-系統設計面試的框架&#34;&gt;Chapter 3: 系統設計面試的框架&lt;/h1&gt;
&lt;p&gt;這章要介紹的是，如何進行一個系統設計面試。這章應該是讀到目前為止讓我最有感的一章了吧。&lt;/p&gt;
&lt;p&gt;首先，他提到了一個重要的問題：&lt;strong&gt;「為什麼公司要考系統設計？」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;考系統設計的原因，不是因為公司想要找到一個可以設計出 Google 搜尋引擎的完美工程師，或是一個十分精通於設計的人才。相反的，一場成功的系統設計面試可以探測到面試者的很多面向：面試者可否有效的與面試官針對某個問題進行合作，提出一個可行的解決方案？在這其中，可以觀察到面試者的協作能力、溝通能力、承受壓力的能力、以建設性方法解決問題的能力。另外，還可以看看面試者是否有透露什麼危險的訊號：是否過度設計、展現固執的個性、或是狹隘的思維？&lt;/p&gt;
&lt;p&gt;因此，這章旨在提供一個簡單有效的框架，讓我們可以訓練自己做一個有效的問題解決者。以下，作者提出了四個步驟，並假設本次我們面對到的題目是「設計一個 news feed system」。&lt;/p&gt;
&lt;h2 id=&#34;第一步驟瞭解問題並確立設計的範圍&#34;&gt;第一步驟：瞭解問題，並確立設計的範圍&lt;/h2&gt;
&lt;p&gt;當拿到一個問題後，切記不要馬上提出自己的答案。必須先在心裡好好思考題目的目的、釐清條件，並彙整資訊。&lt;/p&gt;
&lt;p&gt;主要有兩個問題可以詢問。可以再針對這兩個問題的回覆，做更多細節上的詢問：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;系統的核心功能有什麼？&lt;/li&gt;
&lt;li&gt;系統的規模大小？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果是 news feed system, 可以先詢問產品最主要的功能為何，假設回覆是「發文」，接著便可以接著詢問發文的排列順序、是否僅包含文字或允許多媒體內容、read-write ratio、consistency requirement等等。接著再針對系統規模大小詢問，比如一天流量，然後接著可以詢問使用者最多的朋友數量等等。&lt;/p&gt;
&lt;h2 id=&#34;第二步驟提出高階設計並取得認可&#34;&gt;第二步驟：提出高階設計，並取得認可&lt;/h2&gt;
&lt;p&gt;接著，便是利用以上取得的資訊、做出初步設計的階段了。&lt;/p&gt;
&lt;p&gt;首先可以先用一個 box diagram，畫出主要 entity 以及其關聯。主要 entity 可能有：client side, web server, db, cache, CDN, message queue 等等。也可以註記主要的 api 有哪些。&lt;/p&gt;
&lt;p&gt;關於粗略估算的部分，作者有提到需針對提出的假說做一點估算，但讀書會的當周講者認為不太需要。我認為如果僅僅是要考驗面試者針對系統功能的規劃思路，或許估算的部分相較於決定哪些功能的使用與否確實看起來比較 minor 一點。&lt;/p&gt;
&lt;p&gt;最後，就是使用一個具體的功能/範例，示範一下你的系統會如何運作。&lt;/p&gt;
&lt;p&gt;這期間必須將面試官視為是你的 partner, 與他討論每一個環節，盡量取的他的回饋。&lt;/p&gt;
&lt;p&gt;如果是 news feed system, 可以針對「發布個人動態」去畫一個 diagram, 說明從 client side開始，如何經過 load balancer, 抵達 post service, 然後存取 post cache, post database 等等。&lt;/p&gt;
&lt;h2 id=&#34;第三步驟深入設計&#34;&gt;第三步驟：深入設計&lt;/h2&gt;
&lt;p&gt;第三步驟是一個比較 tricky 的環節。當你已經釐清需求、畫好藍圖之後，面試官可以延伸問你很多問題。諸如以下（內容為讀書會講者所整理）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;high level design: 製作 on demand new feed 的 trade-off 為何&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;技術細節：how to get friend list by graph database？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;潛在效能問題：what if the fan-out service in new feed system cannot process new post fast enough?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;envelop estimation (算數學環節)：how many RAMs are needed for caching all news feed?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;新需求的討論：what will happen if we need to edit page? delete page? how to do fraud detection?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第四步驟彙整總結&#34;&gt;第四步驟：彙整總結&lt;/h2&gt;
&lt;p&gt;這裡要特別注意的是，要留給自己 wrap up 你的方案的時間，不要花太多時間在細節、或是被面試官不小心帶走節奏。如果還有餘裕與時間，可以再額外討論的點有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;系統可能的瓶頸？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可能出錯的狀況？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可以觀察哪些衡量指標？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;系統面試環節既是考驗你對不同技術的理解，也考驗你如何在有限的時間之內，流暢地提出一個問題的解方。最主要的 takeaway 如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;沒有正確的答案、也沒有最好的答案，只有最適合的答案。不要背答案，盡量針對每一個問題去想一個合適的解決方法。&lt;/li&gt;
&lt;li&gt;把面試官當成你的隊友，跟他討論、溝通，切記不要一個人悶頭思考。時常取得面試官的 feedback。&lt;/li&gt;
&lt;li&gt;當卡住的時候，勇於跟面試官要求提示。&lt;/li&gt;
&lt;li&gt;永不放棄。&lt;/li&gt;
&lt;/ol&gt;
</description>
        </item>
        <item>
        <title>System Design (II)</title>
        <link>https://theoutsidelaine.com/p/system-design-2/</link>
        <pubDate>Thu, 02 May 2024 08:00:00 +0000</pubDate>
        
        <guid>https://theoutsidelaine.com/p/system-design-2/</guid>
        <description>&lt;img src="https://theoutsidelaine.com/p/system-design-2/cover.png" alt="Featured image of post System Design (II)" /&gt;&lt;p&gt;這禮拜繼續讀 &amp;lt;System Design Interview- An insider&amp;rsquo;s guide&amp;gt; 第二章。這章很短，不過帶出一個很重要的概念－數字估算。&lt;/p&gt;
&lt;h1 id=&#34;chapter-2-粗略的估算&#34;&gt;Chapter 2: 粗略的估算&lt;/h1&gt;
&lt;p&gt;在了解系統設計的基礎架構思路後，下一步我們便需要了解，依照這個思路所架構的系統，它的&lt;strong&gt;能耐、效能&lt;/strong&gt;表現究竟如何。&lt;/p&gt;
&lt;p&gt;我們必須要先知道有哪些常見的系統效能指標，並且知道該怎麼粗略的去估算它們。在取得這項能力之前，這本書推薦了一些必須熟悉的基礎常識，這有助於我們在估算系統效能指標上可以更駕輕就熟。&lt;/p&gt;
&lt;p&gt;以下我就用 top-down 的方式來 recap 這些概念（會跟原文順序相反），並再補充一點細節。&lt;/p&gt;
&lt;h2 id=&#34;1-常見的系統效能指標&#34;&gt;1. 常見的系統效能指標&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;QPS（Query Per Second）:
&lt;ul&gt;
&lt;li&gt;描述&lt;strong&gt;資料庫&lt;/strong&gt;或是&lt;strong&gt;搜尋引擎&lt;/strong&gt;的每秒鐘查詢數量。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QPS 峰值:
&lt;ul&gt;
&lt;li&gt;一般情況下，QPS peek 會等於 &lt;strong&gt;QPS * 2&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;儲存空間：
&lt;ul&gt;
&lt;li&gt;儲存各種數據，包含document, media, logging等，的空間。會以 bytes 為單位。&lt;/li&gt;
&lt;li&gt;可能指特定檔案儲存空間，也可能指整體儲存空間。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;伺服器數量：
&lt;ul&gt;
&lt;li&gt;用於不同目的的伺服器總數量，包含Web server, DB server, document server, mail server 等。&lt;/li&gt;
&lt;li&gt;可能指特定類型伺服器數量，也可能指總共伺服器數量。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;2-必須熟悉的基礎知識&#34;&gt;2. 必須熟悉的基礎知識&lt;/h2&gt;
&lt;h3 id=&#34;1-table-of-metrics&#34;&gt;(1) Table of metrics&lt;/h3&gt;
&lt;h4 id=&#34;quantity-related-metrics&#34;&gt;Quantity related metrics&lt;/h4&gt;
&lt;p&gt;在軟體領域，通常我們會用 2 的次方來定義這些單位（因為我們使用 byte 為單位存儲）；在電子通訊或是物理學領域，通常則會使用 10 的次方來定義這些單位。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;kilo: =  2&lt;sup&gt;10&lt;/sup&gt; ~= 10&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;mega = 2&lt;sup&gt;20&lt;/sup&gt; ~= 10&lt;sup&gt;6&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;giga = 2&lt;sup&gt;30&lt;/sup&gt; ~= 10&lt;sup&gt;9&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;tera = 2&lt;sup&gt;40&lt;/sup&gt; ~= 10&lt;sup&gt;12&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;peta = 2&lt;sup&gt;50&lt;/sup&gt; ~= 10&lt;sup&gt;15&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;exa = 2&lt;sup&gt;60&lt;/sup&gt; ~= 10&lt;sup&gt;18&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;zetta = 2&lt;sup&gt;70&lt;/sup&gt; ~= 10&lt;sup&gt;21&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;yotta = 2&lt;sup&gt;80&lt;/sup&gt; ~= 10&lt;sup&gt;24&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;speed-related-metrics&#34;&gt;Speed related metrics&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;milli: = 10&lt;sup&gt;-3&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;micro: = 10&lt;sup&gt;-6&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;nano: = 10&lt;sup&gt;-9&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;pico: = 10&lt;sup&gt;-12&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;femto: = 10&lt;sup&gt;-15&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;atto: = 10&lt;sup&gt;-18&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;zepto: = 10&lt;sup&gt;-21&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;yocto: = 10&lt;sup&gt;-24&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在軟體領域中，由於容量通常以 byte 為儲存單位，因此容量單位習慣使用 2 為基底的乘數，方便二進制系統的溝通；而由於速度通常是看每秒多少個bit，因此習慣以 10 為基底的乘數，可以更直接簡單的反應單位時間內的傳輸位元數量。&lt;/p&gt;
&lt;h3 id=&#34;2-幾個延遲相關的數字&#34;&gt;(2) 幾個延遲相關的數字&lt;/h3&gt;
&lt;p&gt;書中介紹了 13 個常用的延遲相關數字，由 Google 的 Jeff Dean 在 2010 年提出：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Time (ns)&lt;/th&gt;
&lt;th&gt;Time (us)&lt;/th&gt;
&lt;th&gt;Time (ms)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;L1 cache reference&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch mispredict&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2 cache reference&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;14x L1 cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutex lock/unlock&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main memory reference&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;20x L2 cache, 200x L1 cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compress 1K bytes with Zippy&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send 1K bytes over 1 Gbps network&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read 4K randomly from SSD&lt;/td&gt;
&lt;td&gt;150,000&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;~1GB/sec SSD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read 1 MB sequentially from memory&lt;/td&gt;
&lt;td&gt;250,000&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Round trip within same datacenter&lt;/td&gt;
&lt;td&gt;500,000&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read 1 MB sequentially from SSD&lt;/td&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk seek&lt;/td&gt;
&lt;td&gt;10,000,000&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;20x datacenter roundtrip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read 1 MB sequentially from disk&lt;/td&gt;
&lt;td&gt;20,000,000&lt;/td&gt;
&lt;td&gt;20,000&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;80x memory, 20X SSD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send packet CA-&amp;gt;Netherlands-&amp;gt;CA&lt;/td&gt;
&lt;td&gt;150,000,000&lt;/td&gt;
&lt;td&gt;150,000&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;主要要記的就是這 13 個指標，另外書中有提到一些需要記得的延伸內容：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;記憶體查詢速度快、disk 慢&lt;/li&gt;
&lt;li&gt;簡單壓縮法（zippy）速度很快&lt;/li&gt;
&lt;li&gt;(其他過於基本暫略)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;3-sla&#34;&gt;(3) SLA&lt;/h3&gt;
&lt;p&gt;SLA (Service Level Agreement, 又稱服務等級協議)，是 service provider（eg: AWS, Google）常使用的術語，定義了 service 提供的服務等級。&lt;/p&gt;
&lt;p&gt;SLA 通常會以 99.9% 為正常基準，小數點後的 9 越多，代表服務等級越好。甚至 9 的數量可以換算成系統停機時間。&lt;/p&gt;
&lt;p&gt;比如書中有提到，正常水準 99.9 %的每天停機時間為 14.4分鐘，99.9999%的每天停機時間為 86.4 毫秒。&lt;/p&gt;
&lt;h2 id=&#34;3-範例估算-twitter-的-qps&#34;&gt;3. 範例：估算 Twitter 的 QPS&lt;/h2&gt;
&lt;p&gt;實際在做系統效能指標估算時，必須謹記三點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把你的假設與思路寫下來：你要用哪些數字計算這些指標？記下他們，方便釐清也方便日後參考。&lt;/li&gt;
&lt;li&gt;標記單位：你使用的這些數字是什麼單位？寫下來，才不會搞混。&lt;/li&gt;
&lt;li&gt;善用近似法、四捨五入：盡量用簡單乾淨的數字做計算比較方便，不求精確程度。比如題目給說每秒 query 數是 197，可以近似為 200。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;假設系統 Twitter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每月有 3 億活躍用戶&lt;/li&gt;
&lt;li&gt;每天有 50% 的用戶使用 Twitter&lt;/li&gt;
&lt;li&gt;用戶平均每天發 2 則推文&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要估算 QPS:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;QPS = 每日推文總數 / 一天的秒數&lt;/li&gt;
&lt;li&gt;每日推文總數 = 3 * 10&lt;sup&gt;8&lt;/sup&gt; * 50% * 2 = 3 * 10&lt;sup&gt;8&lt;/sup&gt; 則&lt;/li&gt;
&lt;li&gt;推文 QPS = 3 * 10&lt;sup&gt;8&lt;/sup&gt; / (24 * 3600 秒) ~= 3500&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這邊要注意的是，每月 3 億用戶是假設每天流量都是 3 億，整個月都是如此。所以不用把 3 億除以30。&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;這章實際帶系統效能估算只有帶了 QPS 跟 儲存空間，感覺 server 數量也是一個很重要的指標，可能需要額外思考如何計算。&lt;/p&gt;
&lt;p&gt;不過透過這章的介紹，我也瞭解了必須熟記很多容量與速度單位的重要性，以及哪些效能指標是重要的，在估算時可以謹記三點讓自己估算時可以更清楚。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>System Design (I)</title>
        <link>https://theoutsidelaine.com/p/system-design-1/</link>
        <pubDate>Mon, 22 Apr 2024 08:00:00 +0000</pubDate>
        
        <guid>https://theoutsidelaine.com/p/system-design-1/</guid>
        <description>&lt;img src="https://theoutsidelaine.com/p/system-design-1/cover.png" alt="Featured image of post System Design (I)" /&gt;&lt;p&gt;從二月準備正職面試以來，遇到了不只一家公司的面試需要考 system design，有鑒於自己在這方面的知識趨近於 0，剛好朋友分享一個開源社群每週三會定期舉辦一本 system design 書籍的讀書會，便想說藉此機會來讀這個領域有關的書，增加自己的知識量。&lt;/p&gt;
&lt;p&gt;這次要讀的書叫做 &lt;strong&gt;&amp;lt;內行人才知道的系統設計面試指南 System Design Interview- An insider&amp;rsquo;s guide&amp;gt;&lt;/strong&gt;，由 Alex Xu 撰寫，總共有 16 個 chapters，從一開始簡要的介紹 system 由小到大的擴展過程，一步步介紹系統內部元件，最後講解大型系統如 Youtube, Google 的設計思路。&lt;/p&gt;
&lt;p&gt;在這一系列文章中，我會逐章整理每一個章節的內容、並分享一點自己的想法。&lt;/p&gt;
&lt;h1 id=&#34;chapter-1-使用者人數----從零到百萬規模&#34;&gt;Chapter 1: 使用者人數 &amp;ndash; 從零到百萬規模&lt;/h1&gt;
&lt;p&gt;這本書的第一章節是 &amp;lt;使用者人數 &amp;ndash; 從零到百萬規模&amp;gt;，使用循序漸進的方法，帶我們了解系統是怎麼一步步擴大的，包含起點是什麼、怎麼疊加元件，進而長成一個可以承載高流量的系統。以下我把系統擴大的過程拆分為七個階段。&lt;/p&gt;
&lt;h2 id=&#34;phase-1-init-a-system-by-web-server--db-server&#34;&gt;Phase 1: Init a system by Web server &amp;amp; DB server&lt;/h2&gt;
&lt;p&gt;想要打造一個系統，要從哪裡開始？最簡單也是最重要的就是先架一個 Web server。這個 Web server 會與 Web browser user 或是 App user進行互動。&lt;/p&gt;
&lt;p&gt;接著，當使用者稍微開始增加後，我們想要將流量做簡單的分流管理，就會把 server 進一步拆成兩個server: (1) Web server, (2) Database server，如下圖。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/1.png&#34;
	width=&#34;914&#34;
	height=&#34;455&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/1_hu29593f92e61ae743c7e9a4e2fae03161_25902_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/1_hu29593f92e61ae743c7e9a4e2fae03161_25902_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;200&#34;
		data-flex-basis=&#34;482px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;從此開始，我們以這兩種 server 為基礎，逐步擴大系統的元件。&lt;/p&gt;
&lt;h2 id=&#34;phase-2-horizontal-scaling&#34;&gt;Phase 2: Horizontal scaling&lt;/h2&gt;
&lt;p&gt;接著，當使用者再逐漸開始增加，我們想要擴展系統，該怎麼做？首先，我們要選擇一種高彈性、低局限性的擴展策略：水平擴展（Horizontal Scaling）。垂直擴展的意思是升級 server內元件規格，這種方法有硬體設計上的限制；水平擴展的則是指使用多台 server來平均分擔流量的方法。&lt;/p&gt;
&lt;p&gt;在 Web server方面的水平擴展，我們可以使用增加多台server搭配負載平衡器（Load Balancer）的方法來達成目標，Load Balancer 會計算出最優的系統流量分配方法。而在 Database server上，我們可以透過使用資料庫複寫機制，意即使用一台 write-only master DB 搭配多台 read-only slave DB來達成目標。如果 master DB 掛了，會有其中一台 slave DB取代他。由於多數系統的 read 永遠大於 write，這麼做可以讓系統以平行的方式處理更多 query。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/2.png&#34;
	width=&#34;899&#34;
	height=&#34;890&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/2_huf6d604aaf6bad90c246b3a9be9e5b8fc_51031_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/2_huf6d604aaf6bad90c246b3a9be9e5b8fc_51031_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;101&#34;
		data-flex-basis=&#34;242px&#34;
	
&gt;&lt;/p&gt;
&lt;h3 id=&#34;horizontal-scaling-known-as-sharding&#34;&gt;Horizontal scaling known as &amp;ldquo;Sharding&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;書中有提到，水平擴展其實有個更廣為人知的名稱：Sharding（分片）。所謂的 Sharding, 意即做出許多個相同 schema 的資料庫，然後平均的把 data 透過 hashing 等方式分配給不同的 sharding DB。在 sharding DB 的使用架構中，最重要的是 hashing 方法中的 &lt;strong&gt;sharding key&lt;/strong&gt; 是如何被選擇的？如果制定的不好，容易讓 data 通通集中於同一個 sharding DB，那就不好了。&lt;/p&gt;
&lt;p&gt;書中提到了幾個有意思的 sharding 要考量到的議題：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如何制定具有一致性的 hashing method:
&lt;ul&gt;
&lt;li&gt;目的是讓 data 不會過度集中於一個 shard，或是解決當某個 shard 容量滿了之後如何重新搬動 data的問題。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;celebrity / hotspot problem:
&lt;ul&gt;
&lt;li&gt;某個 shard 因為太熱門，被過度的 read action 所淹沒。&lt;/li&gt;
&lt;li&gt;可能的解決方法有：(1) 為每個 celebrity 制定一個 shard, (2) 每個 shard 可能要進一步 partition。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;難以取得所有資料：
&lt;ul&gt;
&lt;li&gt;因為資料都放在不同的 sharding DB，難以做 json join。&lt;/li&gt;
&lt;li&gt;可能的解決方法是將 schema 做 de-normalization。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;sharding-vs-partition&#34;&gt;Sharding vs Partition&lt;/h3&gt;
&lt;p&gt;這邊額外整理一個書中沒提到、但是常常看到的比較：sharding 跟 partition 的差異是什麼？簡而言之:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sharding 是將 data 依據 hashing method 等方式分配儲存於不同的 databases, 分隔成實體的單位（實際意義上，這些資料位於不同地方）。&lt;/li&gt;
&lt;li&gt;partition 是將同一個 database 中的 data, 依據比如 country, department等單位再次做分割，分隔成虛擬的單位（實際意義上，這些資料位於同個地方，只是以邏輯意義分成不同組別）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;phase-3-cache--cdn&#34;&gt;Phase 3: Cache &amp;amp; CDN&lt;/h2&gt;
&lt;p&gt;接著，當使用者再逐漸開始增加，service response time 開始變低，我們想要改善系統效能，該怎麼做？這時候我們以資料性質分成兩種處理方式：使用 cache 改善多數資料的存取速度、使用 CDN 改善靜態資料的存取速度。&lt;/p&gt;
&lt;p&gt;Cache 是一個存取速度很快的臨時資料儲存層，介於 Web server 與 client 之間，根據不同的資料類型、存取模式等等，有許多種 request-cache-server 的互動方式（eg: read-through&amp;hellip;）。要讓 Cache 既可以提升速度、又要維持正確性的方法，是仔細的思考 Cache system 的建構策略：什麼時候該使用 cache 而非query db、多久讓 cache中的資料過期、如何讓 cache 與 db資料保持同步、如果 cache 壞掉怎辦、cache 如果滿了怎辦&amp;hellip;&lt;/p&gt;
&lt;p&gt;CDN 是一個第三方供應商提供、為靜態內容提供快取的server，通常分散於地理位置各處。良好的、可以提升靜態內容存取速度的 CDN 很大關鍵取決於 user 與 CDN 之間的地理距離。如同 cache，要讓 CDN 可以良好正確的提升系統效能的方法是思考 CDN 的使用策略，包含過期時間設定、CDN壞掉時的備案措施。另外，CDN 使用成本也是建構系統需要考慮的一點，因此存放於 CDN 的資料必須是高使用率的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/3.png&#34;
	width=&#34;924&#34;
	height=&#34;913&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/3_hu48c34fa339754230f5dbd39bc65d1e12_44583_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/3_hu48c34fa339754230f5dbd39bc65d1e12_44583_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;101&#34;
		data-flex-basis=&#34;242px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;phase-4-stateless-web-server--auto-scaling&#34;&gt;Phase 4: Stateless web server &amp;amp; Auto scaling&lt;/h2&gt;
&lt;p&gt;接著，當使用者再逐漸開始增加，我們想要進一步優化 service response time，該怎麼做？這時候我們針對 Web 層做進一步的優化，方法就是讓所有的 state 資料（eg: session）從儲存於 Web server 改成儲存於 DB server，使 Web server 成為 Stateless Web server。當 user request 發送到 Web server，相較於一台一台 server 去尋找該 user state data 的存放之處，在 Stateless web server structure 下，Web server 會統一尋找共用的 DB，取得該 user 的 state 資料。&lt;/p&gt;
&lt;p&gt;另外，當變成 Stateless structure 後，就可以引入 auto scaling 機制，讓系統根據流量大小自動添加或移除 Web server。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/4.png&#34;
	width=&#34;974&#34;
	height=&#34;879&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/4_hu382f6b037b20b49579d7f58d0f50b879_52523_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/4_hu382f6b037b20b49579d7f58d0f50b879_52523_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;110&#34;
		data-flex-basis=&#34;265px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;phase-5-data-center&#34;&gt;Phase 5: Data center&lt;/h2&gt;
&lt;p&gt;接著，當使用者再逐漸開始增加，開始有了國際化的使用者族群，我們想要進一步優化 service response time 與可用性，該怎麼做？&lt;/p&gt;
&lt;p&gt;一個常見的方法，就是在不同的地理位置建構資料中心。user request 根據事先定義的流量分配比例，透過 geoDNS 被傳送到最近的資料中心的 servers。建構不同地理位置的資料中心也有其核心議題：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;資料同步：通常不同地理位置的資料都會略有不同，如果一者故障、流量轉移至另一個資料中心時，該怎麼設計資料同步策略，才可以讓不同地區的 request 來到這處的資料中心也可以被 process。&lt;/li&gt;
&lt;li&gt;服務一致性：要怎麼設計一套用於不同地區的測試、部署方法，讓不同地區都可以提供一致性或是相對應的服務？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/5.png&#34;
	width=&#34;964&#34;
	height=&#34;903&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/5_hudb0ab1ec2ef81e3d12c8f8732ef3c18e_52180_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/5_hudb0ab1ec2ef81e3d12c8f8732ef3c18e_52180_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;106&#34;
		data-flex-basis=&#34;256px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;phase-6-message-queue&#34;&gt;Phase 6: Message Queue&lt;/h2&gt;
&lt;p&gt;接著，當使用者再逐漸開始增加，而且我們的服務開始變得複雜：有些 services 需要很長的 process time。我們想要讓所有的 request 都可以順利被處理、同時優化 response time 與可用性，該怎麼做？&lt;/p&gt;
&lt;p&gt;一個常見的的作法，是打造訊息佇列（Message Queue），來支援這種非同步的請求情狀，並把 Web server進一步拆分為 Web server 與 Worker server。&lt;/p&gt;
&lt;p&gt;包含 Message Queue 的系統架構中，我們將發送 request 的 server 稱為 &amp;ldquo;Producer&amp;rdquo;，他會是一般的 Web server 。而接受 request 進行任務處理的 server 稱為 &amp;ldquo;Consumer&amp;rdquo;，他會是一個 Worker server。而 Message Queue 通常可以透過第三方服務 RabbitMQ 或是 AWS 的 SQS 來實現。&lt;/p&gt;
&lt;p&gt;首先，Producer (eg: 接收 user request 的 Web server)會將一個複雜任務請求傳送到 Message Queue中。接著，Consumer (eg: 負責執行複雜任務的 Worker process/cronjob/service) 會從 queue 中提領出任務並解決。整個過程是非同步的，意即當 Producer暫時故障沒有發送 request，Consumer 還是可以繼續從 queue 提領任務；當 Consumer 還在處理上一份複雜工作未完成時，Producer也還是可以繼續接單，並傳送至 queue中。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/6.png&#34;
	width=&#34;1044&#34;
	height=&#34;266&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/6_huf29ad6f0cfe43133391a6d76d5ac9496_21003_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/6_huf29ad6f0cfe43133391a6d76d5ac9496_21003_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;392&#34;
		data-flex-basis=&#34;941px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;phase-7-logging--performance-metrics--automation&#34;&gt;Phase 7: Logging &amp;amp; Performance Metrics &amp;amp; Automation&lt;/h2&gt;
&lt;p&gt;最後，我們需要一個機制，讓系統內部發生的事情被紀錄，另外也需要一個元件來監控系統效能表現。透過設定 logging、建構 Performance metrics 並對其進行可視化，我們可以有效地掌握系統狀態並思考如何做得更好。另外，當系統越來越龐大，我們也需要制定 automation strategy (eg: cicd, testing)，以提高生產力。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://theoutsidelaine.com/p/system-design-1/7.png&#34;
	width=&#34;885&#34;
	height=&#34;1121&#34;
	srcset=&#34;https://theoutsidelaine.com/p/system-design-1/7_hu986689f4271fbf6887258c0ded2e50b2_57745_480x0_resize_box_3.png 480w, https://theoutsidelaine.com/p/system-design-1/7_hu986689f4271fbf6887258c0ded2e50b2_57745_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;78&#34;
		data-flex-basis=&#34;189px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;這章算是用很清楚且易懂的方式建構一個系統擴展的架構與思路出來，我覺得對我而言算是一個很好的思考基礎，之後再碰到關於系統設計從零開始設計的議題時，便可以開始想：web server 與 db server 可以分別怎麼擴展、遇到什麼樣的使用情境可以做什麼樣的優化。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
