字數總計:0 個 | 閱讀時長:0 分鐘 |閱讀次數: 次
前言
從單一主機系統,隨著用戶與服務的擴展,到達百萬用戶的過程,會有哪些改變
單伺服器設置
- 包含的組件:Web server(應用程式、資料庫、快取)、網域、使用者端應用程式
- 網域(DNS)是由第三方提供的付費服務,不是由伺服器託管
- 資料流程:
- 使用者透過網域訪問網站或服務,例如:api.mysite.com
- 透過第三方DNS取得主機IP位置,例如:15.125.23.214
- 取得IP位置後,向伺服器發送HTTP請求
- 伺服器回應HTML頁面或JSON內容
問題:你如何設計一個單伺服器系統來處理來自 Web 與移動端的請求?這樣的設計有什麼優缺點?
- 初期可以將所有組件(Web 伺服器、應用程式、資料庫、快取)部署在同一台機器上
- 流程上:用戶從 DNS 解析取得 IP,再直接發送 HTTP 請求給該伺服器,由伺服器產生 HTML 或 JSON 格式的回應
- 優點:部署簡單、成本較低
- 缺點:隨著流量成長,單機容易成為瓶頸且無法提供高可用性
從單伺服器獨立資料庫出來
- 隨著用戶的增長,單伺服器已經不夠,需要變成一個處理Web/App流量,另一個處理資料庫,因此將伺服器拆分成Web層與數據層,允許他們獨立發展
- 關聯式資料庫:
- 資料以表格(Tables)方式組成,每個表格由列(Columns)與行(Rows)構成
- 資料模式 (Schema) 預先定義,確保數據結構的一致性與規範化
- 提供主鍵 (Primary Key)、外鍵 (Foreign Key) 等機制,強制數據之間互相關聯的正確性
- ACID 特性:交易具有原子性 (Atomicity)、一致性 (Consistency)、隔離性 (Isolation) 與持久性 (Durability)
- 確保在並發操作與系統故障時,數據能夠正確保存與回滾
- 範例:MySQL、PostgreSQL、Oracle、SQL Server
- 非關聯式資料庫:
- 關鍵值資料庫 (Key-Value Store)
- 以鍵(Key)對應值(Value)的方式儲存資料
- 查詢速度極快,適用於快取、會話資料等需要高效讀寫場景
- 範例:Redis、Memcached、DynamoDB(可作為鍵值儲存)
- Columnar 資料庫 (Column-family Database)
- 假設儲存一個使用者資料,資料會根據欄族來切分,各欄族包含相關欄位資料,資料表:Users,利用 row key(使用者ID)來識別,每個 row 內可能包含多個欄族(如個人基本資料、聯絡資訊)
- 對於大量資料的讀寫及分析查詢有良好效能
- 範例:Apache Cassandra、HBase
- 圖形資料庫 (Graph Database)
- 以節點、邊、屬性來表示及儲存資料間的關係,用於推薦系統與社交網路,包含紀錄節點以及節點間的關係
- 關鍵值資料庫 (Key-Value Store)
負載平衡
- 垂直擴展:又稱為縱向擴展,透過增加單一個伺服器的計算能力,例如增加CPU、RAM來增加效能
- 水平擴展:又稱為橫向擴展,透過增加更多伺服器
- 負載平衡
- 使用者直接連線負載平衡伺服器,而不是直接連線Web伺服器
- 為了提高安全性,Web伺服器間的資訊流都是使用私有IP(10開頭、192開頭),確保使用者無法直接連線Web伺服器
- 透過Load balancer伺服器與兩個Web伺服器後,解決Web伺服器故障切換問題,提高伺服器的可用性,以滿足SLA要求
資料庫複製
- 透過負載平衡解決伺服器可用性的問題,但是資料庫要怎麼應付大流量,一般都會建立主從資料庫,寫入主資料庫(main DB),讀從資料庫(Slave DB),從資料庫定期從主資料庫同步資料
- 優勢:
- 更好的性能:在這個主/從模型中,所有的寫入和更新都發生在主節點,而所有的讀操作分佈在從節點。這種模型提高了性能,因為它允許平行處理更多的查詢。
- 可靠性:如果你的其中一臺資料庫被颱風、地震等自然災害破壞,資料仍然會被保留。你無需擔心資料遺失,因為資料被複製到多個位置。
- 高可用性:透過在不同位置複製資料,即使一臺資料庫離線,你的網站仍然可以運行,因為你可以存取儲存在另一個資料庫伺服器中的資料。
- 如果一個DB掛掉怎麼辦
- 如果只有一個從資料庫可用,但它離線,讀操作將臨時指向主資料庫。
- 如果有多個從資料庫可用,讀操作則會被轉發到其他健康的從資料庫。
- 如果主資料庫離線,一個從資料庫會被提升為新的主資料庫,所有的資料庫操作都會臨時在新的主資料庫上執行。
快取
- 快取是一個臨時儲存區,用於將昂貴的回應結果或頻繁存取的資料儲存在記憶體中,以便之後的請求能更快地處理
- 在接收到請求後,Web 伺服器首先檢查快取是否有可用的回應
- 如果有,它會將數據發送回客戶端
- 如果沒有,它將查詢資料庫,將回應結果保存到快取中,並將其發送回客戶端。
- 快取使用時的注意事項
- 決定何時使用快取:
- 當資料頻繁讀取但不經常修改時
- 由於快取資料存儲在易失的記憶體中,因此快取伺服器不適合持久化資料。例如,如果快取伺服器重啟,記憶體中所有的資料都會遺失,因此重要的資料應該保存在持久性資料存儲中。
- 過期策略:
- 一旦快取資料過期,就會從快取中刪除。若沒有過期策略,快取資料將會永久保存在記憶體中
- 建議不要將過期時間設定得太短,因為這會導致系統過於頻繁地從資料庫重新載入資料。同時,建議不要將過期時間設定得太長,因為資料可能會過時。
- 一致性:
- 快取與後端資料庫的同步機制(包含跨資料中心)
- 後端資料庫更新後,快取資料的更新機制
- 快取失效(Cache Invalidation):當資料庫中的資料更新時,對應的快取數據要自動標記為失效或直接清除,迫使用戶重新從資料庫獲取最新資料。
- 雙寫策略(Write-Through 或 Write-Behind):同步更新資料庫和快取,但這通常需要更精細的控制來避免鴿子失效或競爭條件。
- 決定何時使用快取:
- 減少故障:
- 單一快取伺服器代表著潛在的單點故障(SPOF),單一的快取伺服器如果故障,就會導致整個系統連帶出現問題
- **多伺服器部署:**為了避免單點故障,可以在不同的資料中心或伺服器上部署多個快取伺服器
- 預留內存的策略:配置比所需大小多出一定百分比的記憶體,這在記憶體使用量上升時可起到緩衝效果
- 驅逐策略:
- 一旦快取滿了,任何嘗試向快取中添加內容的請求都可能導致現有項目被移除
- 最近最少使用(LRU)是最流行的快取驅逐策略
- 其他逐出策略,例如:最不常用(LFU)或先進先出(FIFO)
無狀態的Web層
現在是時候考慮橫向擴展 Web 層了,為此,我們需要將狀態(例如使用者會話資料)移出 Web 層。一個好的做法是將會話資料儲存於持久性存儲中,例如關聯式資料庫或 NoSQL。集群中的每個 Web 伺服器都可以從資料庫取得狀態資料,這種方式稱為無狀態的 Web 層。
- 有狀態架構
- 伺服器會記錄用戶相關識別資料 ex.Session,供下一個請求時記住用戶端數據(狀態)