接續 Day 2 內容
數據系統現在 Reliable 不代表未來也是 Reliable,系統會進步,
這裡討論的 Scalble 是我們有什麼選項去應對未來的成長 和 如何因應額外的流量,
比如 10,000 concurrent user 進步到 100,000 concurrent user,或者未來要處理的資料比現在大的情況。
就是描述系統的關鍵負載指標 (很多東西真的超難用中文講- -),有了這個指標後才能思考成長的策略 (load paremter 變 2 倍時怎辦),
load parameter 會依各系統不同而有不同的指標,例如 網路服務是 每秒查詢次數 (request per seconds) 、聊天室是 同時在線人數、資料庫是 每秒寫入、讀取的次數 等等。
書中使用 Twitter 在 2012 年 11 月的演講 來說明,Twitter 有 2 個主要的操作:
他們主要的挑戰是如何達成 fan-out ,就是名人貼文後,所有的追蹤者的 首頁 timeline 都要有這篇貼文,
fan-out 是從電機工程來的,用來描述一個邏輯閘的 output 到另一個閘當 input 的量,output 需要滿足且能導向所有連接的 input。
他們有 2 個方法來實現:
用 SQL 查詢
SELECT tweets.*, users.* FROM tweets
JOIN users ON tweets.sender_id = users.id JOIN follows ON follows.followee_id = users.id WHERE follows.follower_id = current_user
維護每個 user 的首頁 timeline chche
Twitter 一開始是使用方法 1,但在 300k reads/sec 的情況下方法 1 就越來越慢了,方法 2 好一點,讀取首頁 timeline 的事變的簡單了,瓶頸就在寫入首頁 timeline cache 這一端了,
若 user 的追蹤者少,首頁 timeline cache 很快就寫完,但當某個 user 的追蹤者爆炸多時,例如 3 千萬追蹤者,Twitter 若想在 x 秒內讓追蹤者看到這篇貼文就有難度了,
所以 Twitter 的關鍵 load parameter 就是 fan-out 的量。
前公司在設計新聞推薦系統時,是採用 fan-out on read 的概念,我們一樣要確保新發佈的新聞要送給符合的 user 看,但我們是在推薦行為發生時才做完計算並做快取,而不是先建立好每個人的新聞推薦列表,我們的 load parameter 是 QPS。
有了 load paremter 後再來就是要如何衡量 Performance (執行效率) 了,這裡通常會問 2 個簡單的問題:
常用的的 performance 指標就是 response time,就是在送出 request 到接收 response 的時間差。
上圖為 response time 的示意圖,可以看到大部份的 response time 都很低,但有幾個 outlier 讓 response time 變超長,這發生原因可能又是一脫拉庫了,前一天講的各種錯誤情況、 TCP 連線滿載或機器的物理限制等等都有可能讓 outlier 的 response time 變長,
response time 對 user 的最直接影響就是使用觀感,尤其現在人越來越沒有耐心了。
通常在觀察 response time 時我們會用 percentile (百分位) 來衡量,而不會看 mean (平均),平均很容易受 outliar 值影響,常用的 percentile 是 P50, P90, P95, P99
,舉例來說 P50 2.75 ms
,代表有一半的 request 是在 2.75 ms 內回覆,
下圖是某公司 API reponse time 的 percentile 數字:
可以看到 P99 有一個 request 衝到 一秒,P50, P90 都很低。
依公司或系統的不同,追逐的 percentile 目標就不一樣,像 Amazon 看的是 P99.9,然後我們團隊是 P99 要低於 1 秒。
關於 response time 還有個很重要的一點是要做到 dependency 隔離,如下圖,只要有一個 request 的 response time 特別長,整體的 response 的時間就拉長了,前公司是用 Hystrix 來分離我們的 backend request。
Scalable 最重要的問題就是:當 load parameter 增加時如何保持好的 performance?
工程師常簡單的一分為二成 Scaling up (垂直擴充,加大機器) 和 Scaling out (水平擴充,都小機器),實務上來看,最好的方式依然是混合版,用有點強度的機器跑服務。
若能用一台 (Scaling up) 就能搞定的需求何必一開始就往 Sacling out 的方向去架構系統呢?
無狀態分散式運算是現在許多數據系統的標配,本系列之路的後續章節將會介紹這些技術,除了幫助工程師更方便的設計 Scaling out 外,更能簡單的達到 Maintainable (可維護的)。
工程師都喜歡開發新系統,而沒這麼喜歡維護原有系統,我曾聽過一種系統開發循環:
工程師快速的寫完新系統 -> 另一批工程師接手維護 -> 覺得技術債太多越來越難以維護 -> crash -> 規劃 v2.0 新系統 -> 工程師快速的寫完新系統
工程師最多的時間都是在維護原有系統,無論你喜不喜歡,當你接手時你就應該跟隨你自己的紀律,把 code 寫好、新功能寫好、測試寫好,保持系統的程式處在 Maintainable 狀態,讓未來的其他工程師不會想拿刀砍你。(但如果是 legacy 系統就算了,這真的該改版!)
前面提到的 Reliable, Scalable 或許沒這麼容易達成,但我們在 Maintainable 中有 3 個軟體開發設計原則我們可以放在心上。
好的維運單位能保持系統執行的圓滑,以下列個幾點我覺得重要的點:
直接推薦看另一本書 Clean Code,工程師沒看過這本就慘了。
書中針對數據系統的 Agile (敏捷) 能力給它了 evolvability 這個形容詞,其實就是要做到敏捷開發,
數據系統怎麼做到敏捷開發呢?我們可以試想稍早講的 Twitter 例子,要如何從 方法1 進化到 方法2,
這本書後面就是在講這些數據系統、工具背後使用的技術,讓大型數據系統更易於迭代,
例如用 document 的方式儲存 資料能讓你頻繁的變更 Schema。
最概念性的東西講完了,數據系統要完全符合 reliable, scalable 和 maintainable 是條不簡單的路,
希望看完能把這 3 點放在心上,不管是自己寫或用別人的工具都能觀察學習囉!