讀寫分離和橫向擴容那些事

jopen 10年前發布 | 16K 次閱讀 分離

前言

文章可能比價淺顯,但還是希望大家看過能有共鳴之處

引子

前兩天和同事聊天,他問了我一些問題,關于系統設計的。我說,謹記三點,基本上就不大有問題了:

  1. 做好讀寫分離
  2. 支持橫向擴容
  3. 規劃好每個服務/模塊/類/方法的職責
  4. </ol>

    第三個我就不說了,因為想說也不大能在小篇幅能說好。

    1,2兩點很重要。很多初創公司或者小公司,一般都是先把功能實現了再說,但我認為一個好的系統設計師,或者程序員,都應該做到:

    • 讓系統支持讀寫分離,橫向擴容
    • 設計時留下退路,讓系統非常容易支持
    • </ul>

      為什么這么說呢,因為我看到了不少創業公司,甚至包括我們公司部分產品,一開始不考慮這些,接著開始遇到性能問題,這個時候才開始想到要做讀寫分離之類的功能,但是改起來比較困難,要動大手術,而產品已經積累了大量用戶和內容,如果是新功能增加還好,像這種大改動,研發還是很忌憚的。所以就會想辦法拖著,譬如添加各種緩存,來緩解性能和擴展性問題。而隨著功能越來越多,勢必會讓性能進一步下降。

      橫向擴容在某些程度和讀寫分離有比較緊密的關系,一般如果做了讀寫分離,那么很多情況橫向擴容也就自然是水到渠成的,所以我這里重點講的是如何做好讀寫分離

      如何做好讀寫分離

      我們現在和產品的對接過程中,所有數據寫入的是一套流程,所有查詢的是另一套流程,而且是由不同的服務群集組成,所以天然實現了讀寫分離,并且能夠很好的支持了橫向擴容。

      所以我對數據庫讀寫分離沒有做過太多工作,但很多東西是相同的,我這里只是提提自己的看法。

      讀寫分離說起來容易,其實做起來也有些麻煩,往往一個讀的邏輯環節(外部看來),其實也會有大量的寫。最簡單的例子是,我閱讀一篇文章,文章閱讀數會變更(姑且認為是寫數據庫),會記錄最近訪問用戶等。也就是從功能意義上來看,讀和寫往往是混合的,

      這里就會有三套很直觀的方案:

      1. 在數據層面區分讀寫,應用發現是update,insert等操作就走主庫,如果是select 就走從庫
      2. 做一個proxy,該proxy 攔截所有sql,具體功能類似1所說的。
      3. 對寫單獨做一個服務,提供寫API。
      4. </ol>

        三種方案都基于數據庫的主從結構。類似:

        數據庫

        1. master
        2. slave-1~slave-n
        3. </ol>

          其中第三種具體方案如下:

          應用層,則要分為讀服務和寫服務。 應用 master 只負責和數據庫master打交道,并且只負責寫操作。應用的slave則可多個對應一個數據庫slave就行。

          應用slave 涉及到任何寫數據庫的部分,則轉換為調用應用master提供的API服務,其實就是把寫庫操作服務API化了。

          大概結構如下:

          對我而言,肯定是偏向3的方案。為什么?因為我們要看到最后架構的演化方向。一個系統不管是因為功能復雜了,還是為了易于擴展,最終都會是一個系統由N個服務組合起來的,不會是一個單單的進程就完成的。

          通常來說,讀寫分離是系統服務模塊化的前兆。這個時候我們的系統其實由原來的單一系統演化出來了一個單獨的寫服務。隨著壓力上升及時是寫服務無我們可能也會劃分成多個服務,讀的部分就更不用說了。

          加入設計一個博客系統讀寫分離時,可這樣操作:

          1. 所有寫操作由master實現API化
          2. 每個slave是一個正常的博客應用,接受讀和寫,只是內部寫的時候,不寫數據庫,而是調用master API
          3. </ol>

            對于現有系統的改造做讀寫分離也比較簡單:

            1. 新建一個master項目,實現寫操作API化
            2. 原有的程序,將所有寫數據庫操作都轉化成對master API的調用
            3. </ol>

              橫向擴容

              讀的橫向擴容比較好做,某些情況可能需要注意將session會話粘滯在一臺服務器上。

              對于寫的橫向擴容,我們現在的做法是,通過消息隊列 ,可參看我這篇關于消息隊列應用場景的介紹文章 大數據技術棧-Web框架&消息隊列,所有寫的動作都會發布到消息隊列,然后通過后端起服務消費消息隊列執行真正寫的動作。所以后端是可以任意起多個服務的。在數據產品中,這個后端服務其實叫數據鏈路處理服務。主要執行類似ETL一類的工作,進行規整化后存入索引,HBase,Redis等存儲器中。

              好處是什么

              1. 讀寫分離是能橫向擴容的基礎
              2. 其實讀寫分離本質上是模塊化,系統解耦
              3. 系統擴展性好,可以充分利用云時代擴充服務器的便利。
              4. 上線(更新)可以實現不中斷服務。我們現在就是rolling update(有點類似灰度發布),所以能感覺到它的好。

                切掉A服務器流量 -> 更新服務 -> 測試 -> 切回A服務器流量 -> 監控查看 -> 依次升級所有服務器 </li> </ol>

                題外話一下,別小看上線更新發布,如果你做的不是項目,而是一個一直用的產品,系統設計能給上線帶來方便的話,真是一件功德無量的事情。 

                最后的話

                前面也提到了,為什么采用方案3,讀寫分離是第一步,其實最后我們的目標可能還是會把一個服務拆成N個服務,協同運作。理論都是通的,這就好比這些年規模PC服務器取代中小型機是一樣的。

                來自:http://weibo.com/p/1001603835554767706247

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!