我的架構師同事問我:「為什麼你總說要在服務層實現讀寫分離,我們已經在資料庫實現了讀寫分離,是不是已經夠用」。以下是我的解釋,
在做**效能優化的時候,我常常忘記還有資料庫讀寫分離這件事,因為資料庫讀寫分離,對效能帶來的提高太有限了,實際上,就是一倍(一台伺服器變成兩台伺服器)。當你的**業務發展,如果從無到有地使用資料庫讀寫分離,提高了一倍的服務能力,你很快就需要想新的優化方案。實際上,資料庫的讀寫分離,更像是資料安全的乙個副產品,用一台資料庫伺服器不安全(怕資料丟失),用一台伺服器作為備份,既然有了兩台伺服器,就充分利用吧,於是有了「讀寫分離」,提高一倍也是好的。
於是,能夠十倍百倍提高效能的方案出現了,快取加伺服器集群,這是最常用且有效的提高**訪問量的設計。使用共享快取(memcached,redis)可以獲得十到幾十倍的效能提公升,使用程序內快取,可以得到百倍的效能提公升;集群中增加一倍的伺服器,可以增加一倍的計算能力,服務更多的併發請求。等一下,上面所說的方案,其實只對「讀」操作才有效,對「寫」操作可以說是毫無用處。
那麼有什麼辦法可以提高「寫」操作的效能,在架構部署的設計方面,我的答案是,「沒有」。
從硬體入手,可以使用ssd硬碟。願意替換底層資料庫,可以使用hbase或者cassandra,都不在今天討論的範圍。我想說的是,既然使用快取和增加伺服器,對於「寫」操作沒有優化作用,在一開始,「寫」操作相關的服務,就不該和「讀」操作一起,被分配到數量龐大的計算機集群裡。
想象這樣的架構設計,我有乙個「讀」服務的集群,一共4臺伺服器,我有一台「寫」伺服器(另一台備用,故障時切換)。當我的**訪問量上公升,我增加「讀」伺服器集群到8臺,簡單就能應付問題。因為「讀」服務是狀態無關的,增加到100臺也不會帶來錯誤的資料,這是乙個重要的思想,狀態無關的服務,才可以放心地水平擴充套件,事實上,狀態無關的服務,通常只有「讀」服務。
那麼當「寫」服務撐不住的時候,怎麼辦,嗯。。。總會有辦法,反正不是加快取或者是使用集群,這個可以做架構師面試題。
然後我解釋一下為什麼不該在集群裡面執行「寫」服務,我把「寫」服務分為兩種。
2. 和「狀態」(可能發生衝突的情形)強相關,比如包含庫存操作的電商**,上千人「秒殺」熱門商品,允許這樣的操作在集群內併發,是架構師自己作死的節奏啊
明白了這個道理,你就知道我之前為什麼說是「一台」寫伺服器,只有一台伺服器,才可以保證在「秒殺」場景下,不會在沒有庫存的情況下繼續售賣成功。
細心的讀者(嗯,就是你)會繼續追問,在一台伺服器的情況下,現在都是多核併發程式設計,保證序列操作也不是容易的事啊。問得太好了,我這大半年寫的系列文章,都是為了解決這個問題,你需要的是actor模型。非同步程式設計加上程序內的訊息佇列,可以高效地對併發操作進行序列的處理。
結論,使用伺服器集群提高效能只對「讀」服務有效,對「寫」服務無效,「寫」伺服器應該使用主/從模式,同一時間只使用一台伺服器。在「寫」伺服器內部,使用支援actor模型的程式語言,保證關鍵操作的序列。最後老生常談,支援actor模型的程式語言是:erlang,go,scala,f#
**:
為什麼要在服務層設計讀寫分離?
我的架構師同事問我 為什麼你總說要在服務層實現讀寫分離,我們已經在資料庫實現了讀寫分離,是不是已經夠用 以下是我的解釋,在做 效能優化的時候,我常常忘記還有資料庫讀寫分離這件事,因為資料庫讀寫分離,對效能帶來的提高太有限了,實際上,就是一倍 一台伺服器變成兩台伺服器 當你的 業務發展,如果從無到有地...
為什麼要在傳輸層做校驗呢?
size large 資料鏈路層對幀資料做了校驗,為什麼還要在傳輸層做校驗呢?size size large 資料鏈路層對幀資料做了校驗保證了資料可以完整的從主機a傳遞到主機b,但主機b也在不停地從主機c收資料,這樣網路資料可能擁塞超出緩衝區,所以資料流失。如果兩份從主機a中傳遞到主機b中,主機b中...
為什麼要在專案中應用三層架構?
區分層次的目的即為了 高內聚,低耦合 的思想。優點 1 開發人員可以只關注整個結構中的其中某一層 2 可以很容易的用新的實現來替換原有層次的實現 3 可以降低層與層之間的依賴 4 有利於標準化 5 利於各層邏輯的復用。缺點 1 降低了系統的效能。這是不言而喻的。如果不採用分層式結構,很多業務可以直接...