為什么要在服務層設計讀寫分離?


作者:陳葉皓(攜程郵輪研發部軟件架構師)

我的架構師同事問我:“為什么你總說要在服務層實現讀寫分離,我們已經在數據庫實現了讀寫分離,是不是已經夠用”。以下是我的解釋,

在做網站性能優化的時候,我常常忘記還有數據庫讀寫分離這件事,因為數據庫讀寫分離,對性能帶來的提高太有限了,實際上,就是一倍(一台服務器變成兩台服務器)。當你的網站業務發展,如果從無到有地使用數據庫讀寫分離,提高了一倍的服務能力,你很快就需要想新的優化方案。實際上,數據庫的讀寫分離,更像是數據安全的一個副產品,用一台數據庫服務器不安全(怕數據丟失),用一台服務器作為備份,既然有了兩台服務器,就充分利用吧,於是有了“讀寫分離”,提高一倍也是好的。

 

於是,能夠十倍百倍提高性能的方案出現了,緩存加服務器集群,這是最常用且有效的提高網站訪問量的設計。使用共享緩存(memcached,redis)可以獲得十到幾十倍的性能提升,使用進程內緩存,可以得到百倍的性能提升;集群中增加一倍的服務器,可以增加一倍的計算能力,服務更多的並發請求。等一下,上面所說的方案,其實只對“讀”操作才有效,對“寫”操作可以說是毫無用處。

那么有什么辦法可以提高“寫”操作的性能,在架構部署的設計方面,我的答案是,“沒有”。

從硬件入手,可以使用SSD硬盤。願意替換底層數據庫,可以使用hbase或者cassandra,都不在今天討論的范圍。我想說的是,既然使用緩存和增加服務器,對於“寫”操作沒有優化作用,在一開始,“寫”操作相關的服務,就不該和“讀”操作一起,被分配到數量龐大的計算機集群里。

想象這樣的架構設計,我有一個“讀”服務的集群,一共4台服務器,我有一台“寫”服務器(另一台備用,故障時切換)。當我的網站訪問量上升,我增加“讀”服務器集群到8台,簡單就能應付問題。因為“讀”服務是狀態無關的,增加到100台也不會帶來錯誤的數據,這是一個重要的思想,狀態無關的服務,才可以放心地水平擴展,事實上,狀態無關的服務,通常只有“讀”服務。

那么當“寫”服務撐不住的時候,怎么辦,嗯。。。總會有辦法,反正不是加緩存或者是使用集群,這個可以做架構師面試題。

然后我解釋一下為什么不該在集群里面運行“寫”服務,我把“寫”服務分為兩種。

1.       和“狀態”(可能發生沖突的情形)弱相關,比如用戶提供內容(UGC)的操作,每個用戶提交自己的評論,或者發布自己的微博,不太容易發生沖突。對於這類“寫”服務,部署在集群里面勉強可行,雖然沒帶來什么好處,但也沒有引入錯誤

2.       和“狀態”(可能發生沖突的情形)強相關,比如包含庫存操作的電商網站,上千人“秒殺”熱門商品,允許這樣的操作在集群內並發,是架構師自己作死的節奏啊

明白了這個道理,你就知道我之前為什么說是“一台”寫服務器,只有一台服務器,才可以保證在“秒殺”場景下,不會在沒有庫存的情況下繼續售賣成功。

細心的讀者(嗯,就是你)會繼續追問,在一台服務器的情況下,現在都是多核並發編程,保證串行操作也不是容易的事啊。問得太好了,我這大半年寫的系列文章,都是為了解決這個問題,你需要的是actor模型。異步編程加上進程內的消息隊列,可以高效地對並發操作進行串行的處理。

結論,使用服務器集群提高性能只對“讀”服務有效,對“寫”服務無效,“寫”服務器應該使用主/從模式,同一時間只使用一台服務器。在“寫”服務器內部,使用支持actor模型的編程語言,保證關鍵操作的串行。最后老生常談,支持actor模型的編程語言是:Erlang,Go,Scala,F#

原文鏈接:http://techshow.ctrip.com/archives/784.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM