引用:
系統(tǒng)設計入門
主從復制
主庫同時負責讀取和寫入操作,并復制寫入到一個或多個從庫中,從庫只負責讀操作。
樹狀形式的從庫再將寫入復制到更多的從庫中去。如果主庫離線,系統(tǒng)可以以只讀模式運行,直到某個從庫被提升為主庫或有新的主庫出現(xiàn)。
缺點:
- 將從庫提升為主庫需要額外的邏輯。
主主復制
兩個主庫都負責讀操作和寫操作,寫入操作時互相協(xié)調。如果其中一個主庫掛機,系統(tǒng)可以繼續(xù)讀取和寫入。
缺點:
- 你需要添加負載均衡器或者在應用邏輯中做改動,來確定寫入哪一個數(shù)據(jù)庫。
- 多數(shù)主-主系統(tǒng)要么不能保證一致性(違反 ACID),要么因為同步產(chǎn)生了寫入延遲。
- 隨著更多寫入節(jié)點的加入和延遲的提高,如何解決沖突顯得越發(fā)重要。
主從復制和主主復制共同的問題
- 如果主庫在將新寫入的數(shù)據(jù)復制到其他節(jié)點前掛掉,則有數(shù)據(jù)丟失的可能。
- 副本可能因為過多寫操作阻塞住,導致讀取功能異常。
- 讀取從庫越多,需要復制的寫入數(shù)據(jù)就越多,導致更嚴重的復制延遲。
- 在某些數(shù)據(jù)庫系統(tǒng)中,寫入主庫的操作可以用多個線程并行寫入,但讀取副本只支持單線程順序地寫入。
- 復制意味著更多的硬件和額外的復雜度。
聯(lián)合
聯(lián)合(或按功能劃分)將數(shù)據(jù)庫按對應功能分割。
例如,你可以有三個數(shù)據(jù)庫:論壇、用戶和產(chǎn)品,而不僅是一個單體數(shù)據(jù)庫,從而減少每個數(shù)據(jù)庫的讀取和寫入流量,減少復制延遲。
較小的數(shù)據(jù)庫意味著更多適合放入內存的數(shù)據(jù),進而意味著更高的緩存命中幾率。沒有只能串行寫入的中心化主庫,你可以并行寫入,提高負載能力。
缺點:
- 如果你的數(shù)據(jù)庫模式需要大量的功能和數(shù)據(jù)表,聯(lián)合的效率并不好。
- 你需要更新應用程序的邏輯來確定要讀取和寫入哪個數(shù)據(jù)庫。
- 從兩個庫聯(lián)結數(shù)據(jù)更復雜。
- 聯(lián)合需要更多的硬件和額外的復雜度。
分片
分片將數(shù)據(jù)分配在不同的數(shù)據(jù)庫上,使得每個數(shù)據(jù)庫僅管理整個數(shù)據(jù)集的一個子集。
以用戶數(shù)據(jù)庫為例,隨著用戶數(shù)量的增加,越來越多的分片會被添加到集群中。
類似聯(lián)合的優(yōu)點,分片可以減少讀取和寫入流量,減少復制并提高緩存命中率。也減少了索引,通常意味著查詢更快,性能更好。如果一個分片出問題,其他的仍能運行,你可以使用某種形式的冗余來防止數(shù)據(jù)丟失。類似聯(lián)合,沒有只能串行寫入的中心化主庫,你可以并行寫入,提高負載能力。
常見的做法是用戶姓氏的首字母或者用戶的地理位置來分隔用戶表。
缺點:
- 你需要修改應用程序的邏輯來實現(xiàn)分片,這會帶來復雜的 SQL 查詢。
- 分片不合理可能導致數(shù)據(jù)負載不均衡。例如,被頻繁訪問的用戶數(shù)據(jù)會導致其所在分片的負載相對其他分片高。
- 再平衡會引入額外的復雜度?;谝恢滦怨5姆制惴梢詼p少這種情況。
- 聯(lián)結多個分片的數(shù)據(jù)操作更復雜。
- 分片需要更多的硬件和額外的復雜度。
非規(guī)范化
非規(guī)范化試圖以寫入性能為代價來換取讀取性能。在多個表中冗余數(shù)據(jù)副本,以避免高成本的聯(lián)結操作。
在多數(shù)系統(tǒng)中,讀取操作的頻率遠高于寫入操作,比例可達到 100:1,甚至 1000:1。需要復雜的數(shù)據(jù)庫聯(lián)結的讀取操作成本非常高,在磁盤操作上消耗了大量時間。