本章概述#

企業應用程式需要盡可能快速地存取資料。在應用程式效能管理中,最重要的兩個指標是 response timethroughput。Response time 越低,應用程式的回應速度越快,因此它是衡量效能的核心指標。而 scaling 的目標是在系統負載增加的情況下維持低 response time,throughput 則是衡量可擴展性的指標。

Response Time 與 Throughput#

Transaction Response Time 的組成#

一筆 transaction 的 response time 包含以下時間區段:

  • Connection acquisition time — 取得資料庫連線的時間
  • Statement transmission time — 將 SQL 語句透過網路傳送到資料庫的時間
  • Execution time — 資料庫執行語句的時間
  • Result set transmission time — 將結果集回傳給客戶端的時間
  • Idle time — 在釋放連線前,應用程式層的運算所耗費的時間

Throughput 的定義#

Throughput 是在單位時間內完成的 transaction 數量。降低單筆 transaction 的執行時間,系統就能處理更多請求。

以單一資料庫連線測量的 throughput 是進一步並行優化的基準線。理想情況下,增加更多連線應能線性提升 throughput,但由於資源 contention 與維護 coherency 的成本,實際的 throughput 增幅會呈現曲線而非直線。

Universal Scalability Law (USL)#

USL 可用來估算在特定並行連線數下的最大相對 throughput:

  • contention coefficient — 資料處理中可序列化部分的比例
  • coherency coefficient — 維持所有並行 session 一致性的成本

當 coherency coefficient 為零時,USL 退化為 Amdahl’s Law。Contention 會降低可擴展性的上限,而 coherency 則負責造成擴展曲線的反轉點 — 當並行 session 數過多時,throughput 反而會下降。

Figure 1.1: Universal Scalability Law

降低 response time 不僅讓應用程式回應更快,同時也能提升 throughput。但在高並行環境中,僅靠降低 response time 是不夠的,還需要根據流量增長來擴充系統容量。

Database Connections 的邊界#

每一條資料庫連線都需要一個從客戶端到伺服器的 TCP socket。資料庫伺服器能提供的連線總數取決於底層硬體資源:

  • SQL ServerMySQL 使用 thread-based 的連線處理模型
  • PostgreSQL 為每個連線使用一個獨立的作業系統 process
  • Oracle 在 Windows 上使用 thread,在 Linux 上使用 process(Oracle 12c 開始也支援 Linux 上的 thread-based 模型)

資料庫系統內部高度依賴 CPUMemoryDisk 資源。由於 I/O 操作成本高昂,資料庫使用 buffer pool 將資料和索引頁快取在記憶體中,變更先在記憶體中套用,再批次刷寫到磁碟。

高 throughput 的資料庫應用程式會在 CPU、Memory、Disk 和 Locks 上產生資源競爭。當所有資源都已飽和時,增加更多工作負載只會加劇 contention,反而降低 throughput。改善 throughput 的第一步是根據當前的資料存取模式來調校系統配置。

Scaling Up 與 Scaling Out#

  • Scaling up(垂直擴展)— 對單一機器增加更多資源(CPU、記憶體、磁碟)
  • Scaling out(水平擴展)— 增加更多機器來分擔負載

傳統上,為資料庫伺服器增加硬體資源是提升容量的首選方式。但分散式系統比集中式系統更難管理,水平擴展的挑戰也更大。然而,以相同的價格可以購買多台商用機器,其總資源可能超過單一高效能伺服器。

無論單一伺服器多麼強大,它仍然是 single point of failure。一旦系統無法使用,throughput 即歸零。因此,database replication 在許多企業系統中是不可或缺的。

Master-Slave Replication#

適用於 read/write ratio 高的企業系統:

  • Master 是唯一接受寫入的節點(system of record)
  • 所有變更會被複製到 Slave 節點
  • 複製方式:binary replication(使用 WAL)或 statement-based replication(重播 SQL 語句)
  • Slave 節點可處理 read-only transaction,將讀取流量從 Master 分流

Asynchronous replication(warm standby):

  • Slave 節點是 eventually consistent,可能落後於 Master
  • Master 故障時需透過投票機制選出新的 Master
  • 選舉過程不是即時的

Synchronous replication(hot standby):

  • Master 必須等待 synchronous Slave 確認更新
  • 增加 transaction response time,但確保資料一致性
  • Master 故障時,synchronous Slave 可立即接替

大多數資料庫系統允許設置一個 synchronous Slave 節點。這種配置既能確保 Master 故障時的資料一致性(hot standby),又不會因為過多 synchronous Slave 而嚴重拖慢寫入效能。

Figure 1.2: Master-Slave replication

Multi-Master Replication#

所有節點地位平等,都能接受 read-write 和 read-only transaction:

  • 可將負載分散到多個節點,提升 throughput 並降低 response time
  • 因為沒有單一 source of truth,資料一致性是最大挑戰
  • 同一筆資料可能在不同節點上被同時修改,產生衝突

衝突處理策略:

  • 避免衝突 — 使用 two-phase commit protocol,所有節點在同一分散式交易中保持同步。代價是寫入操作變慢,且若節點間透過 WAN 連接,同步延遲會大幅增加
  • 偵測並解決衝突 — 使用自動衝突解決演算法。若自動解決失敗,則需人工介入

Figure 1.3: Multi-Master replication

Sharding#

當資料量超過 replicated multi-node 環境的整體容量時,就需要進行 sharding — 將資料分散到多個節點,每個節點只存放整體資料的子集:

  • 不同於同一伺服器內的 horizontal partitioning,sharding 將資料分布在不同機器上
  • 每個 shard 必須是 self-contained,因為跨 shard 的 JOIN 成本過高
  • 每個 shard 內部通常仍會搭配 Master-Slave replication 架構
  • 資料中心可服務不同的地理區域,較小的共用資料表可透過 asynchronous replication 在各 shard 間同步

Figure 1.4: Sharding

Sharding 通常是提升系統容量的最後手段,應在窮盡其他選項後才考慮:

  • 優化資料存取層以降低 transaction response time
  • 將每個 replicated node 擴展到性價比最佳的配置
  • 增加更多 replicated node,直到同步延遲降至可接受的門檻

Figure 1.5: Auto-sharding

Little’s Law#

在任何系統中,response time 與 throughput 之間的最終關係由 Little’s Law 描述:當 incoming throughput 過高時,會因資源飽和導致 response time 呈指數級增長。因此,本書後續章節的核心目標就是盡可能降低 transaction response time。