今天是第二個應用的總結,想講講一般系統上遇到高流量的一些設計要點,首先想講幾個我覺得重要的觀念。第一個是極限,你必須詳細的去解析每一個環節的極限,你系統的極限就是最弱那個環節的極限
。第二個是知道極限後,在到達極限之前開始擋人總比大家都擠進來死翹翹來的好,這告訴我們要適度的做流量上的控管。第三個選擇最適合的東西去使用,了解經典為何為經典,例如為什麼 RDBMS 不死反而再度大紅,是因為他跟 NoSQL 本不存在零和關係,他們是可以共存的,各有各自適合的場景。有一句經典的廢話是解決一個無解難題的最好方法就是什麼都不做,其實它體現的概念正是如果這個難題真的無解,也許該思考的是你是不是一開始就想錯方向了。
請參考之前系統架構的演進這一篇。
load balancer & stateless service 可以解決 service 層的 CPU 和 IO Bound,但無限擴展散掉壓力也沒用,瓶頸會出現在 DB!慎思。
index沒中、query範圍太大、查詢欄位太多、回傳筆數太多、關聯table太多張、用錯函數、讀寫分離、水平分表、業務分庫...等等。如此一層一層排查實作下去,即時在幾G的單一張資料表,應該也可以在幾秒內回來。
減少request db次數 (多合一)、call stored procedure、合理的使用 cache ... 等等。基本上的邏輯是合理的使用外部的服務,取其優勢。
主寫備讀,避免query update lock,並且讓索引只建立在備庫,提高主庫新增的效能。
NoSQL 的軟肋是大量即時聚合型查詢,因為索引跟交易功能絕對不會有傳統 RDBMS 來的成熟。但如果選擇對的資料型態,NoSQL 在儲存的量級與新增修改的速度絕對是讓人滿意的。
這不一定適合用在每一個業務場景,但是如果你的業務場景允許非同步,那麼擋個 Queue 絕對可以解決你大部分問題!
緩存資源即使在今天,因為是整個系統共用,它也依舊是珍貴的。所以通常我們回實作一個本地緩存來保護它,如果本地緩存有資料就直接返回,避免過高的 QPS 請求直接轟炸緩存伺服器。但是太多層級的緩存就會有同步議題,處理這個上要注意。
雖然 RDBMS 到今天已經強壯得很,但是你亂搞它還是會死。無論是擋 Cache 直接返回 或是擋 Queue 慢慢消化都是常見的作法。核心概念一樣,避免過高的 QPS 請求直接轟炸 RDBMS。
About Me
Jian-Min Huang
wide range skill set backend engineer
Research, Architecture, Coding, DB, Ops, Infra.
mainly write Java but also ❤️ Scala, Kotlin and Go