分佈式設計

分佈式設計mysql

  • 1.複製
  • 做用
    • 對數據備份,實現高可用
    • 提升吞吐量,實現高性能
  • 分類
    • 主從架構
      • 性能
        • 一主多從,讀寫分離,提升吞吐量
      • 可用性
        • 主庫單點,一旦掛了,沒法寫入
        • 從庫高可用
      • 一致性
        • 數據同步存在延遲,讀時從庫中返回的多是舊數據
          • 解決方案
            • 直接忽略,存在延遲很正常
            • 班不一樣步複製(semi-sync),主從同步完成寫請求才返回,吞吐量下降
            • 選擇讀主
              • 思路
                • 寫操做時,根據庫+表+業務特徵生成key設置到緩存中並設置超時時間(大於等於主從數據同步時間),讀操做時,一樣方式生成key,先去查緩存,若是命中則讀主庫,不然讀從庫
              • 技術難點
                • 主從數據同步時間的計算 不一樣網絡,配置下,時間不同
              • 不少數據庫的中間件就是使用的這種思路,如mycat等,可是中間件的成本一樣不低
            • 對於即時性有要求的接口,直接從主數據庫讀
        • 讀寫分離的狀況下,併發出現更新丟失問題
          • 悲觀鎖
            • 必須加載主數據庫商,這樣就不能作讀寫分離
          • 樂觀鎖
            • 能夠
            • update當前讀,這樣也不能作讀寫分離
          • 有一致性要求的接口,沒法讀寫分離,只能從主庫中操做
    • 多主架構(互爲備份)
      • 性能
        • 負載均衡
      • 可用性
        • 高可用
      • 一致性
        • 和主從架構同樣
    • 主主從從
      • 高性能
      • 高可用
      • 一致性
        • 和主從同樣
    • 主備
      • 主庫提供讀寫服務,備庫作故障轉移用
      • 性能通常
        • 提升性能 設置緩存
      • 高可用
      • 無一致性問題
      • 使用普遍 58和阿里雲
  • mysql主從同步的原理
  • 2.分片/分庫分表
  • 需求分析
    • 用戶請求量太大 -> 分佈式服務器(分散請求到多個服務器上)
    • 單庫太大  單庫所在服務器上磁盤空間不足;處理能力有限;出現IO瓶頸
    • 單表太大 -> CRUD都成問題,索引膨脹,查詢超時
  • 做用
    • 共同組成完整的數據集合,擴充單機存儲的容量上限,讀寫速度上限
  • 每一個服務器節點成爲分片
  • 優勢: 高吞吐
    • 吞吐量越高,同一時間數據的讀寫完成量越高
    • 一個節點可能單日吞吐量只能到達1TB(收硬件限制,硬盤速度有限)
  • 垂直拆分
    • 垂直分表
      • 把字段分開成多張表
    • 垂直分庫
      • 將有關聯的表放在一個數據庫中 如用戶表,用戶頻道表等
    • 項目處理
      • 用戶數據垂直分表  user_basic  user_profile
      • 文章數據垂直分表(文章內容較長且只在詳情頁才須要) article_basic  article_content
        • 兩張表 定義時都包含其關聯數據,這就要求使用事務來保證數據一致性
  • 水平拆分
    • 水平分表
      • 將1000萬條記錄分紅兩張表
      • 分表方式:按時間/id/地理/hash取模 分表
    • 水平分庫分表 分表分別放在不一樣的節點,使用率極高
    • 分佈式ID
      • 需求:水平分表後,須要保證多表id不會出現衝突
      • 解決方案
        • UUID 通用惟一識別碼 缺點:較長,不會趨勢遞增(主鍵若是不是遞增的,索引效率會比較低)
        • 數據庫主鍵自增
          • 方案1: 單獨數據庫 只負責生成主鍵  缺點:一旦宕機,全局癱瘓
          • 方案2: 設置自增步長 全部表都使用相同的步長 缺點:分片規則不能修改,沒法擴展
        • Redis
          • incr("user_id")返回的值自增
          • 不會出現資源搶奪問題,由於redis是單線程的,能夠保證原子性
          • 缺點
            • redis宕機
            • redis易數據丟失
        • 雪花算法-Snowflake
          • twitter提出的算法,目的是生成一個64位的整數

          • 缺點:時間回撥,及其的緣由時間可能出現誤差,雖然會同步進行校訂,但生成時多是錯誤的
            • 若是發生回撥(當前時間<記錄的時間),算法會自動拋出異常,可讓用戶稍等一下子
            • 取消同步ntp時間
          • 項目中的應用
            • 用戶id 文章id 評論id 後期數據量可能會很大
    • 前期數據量和請求次數少時,不要作分片
  • 分佈式問題
    • 一致性問題
      • 主從延遲
        • 對於即時性高的接口,直接從主庫中提取
      • 更新丟失
        • 不進行讀寫分離,在主庫中完成流程
    • 分片id衝突
      • 實現分佈式ID
    • 跨庫原子性
      • 一個業務中可能包含多個庫中的寫操做,該業務須要具備原子性,可是無不具有跨庫原子性
      • 解決辦法
        • 將有關聯的表放在一個數據庫中
        • 使用分佈式事務
          • 核心是二階段提交協議(簡稱 2PC協議/XA協議)
          • 會出現事務等待的狀況,增長死鎖的產生機率,效率低
        • 經過優化業務邏輯,實現基於消息的最終一致性方案(本質是經過消息隊列執行異步任務,部分失敗則不斷重試/或所有取消,通常須要中間件完成任務分發,任務充實,消息冪等等)
          • 分佈式中間件 merge引擎 分庫分表中間件 mycat
    • 跨庫join
      • join不容許跨庫完成
      • 解決辦法
        • 分兩次查詢進行
        • 開啓FEDERATED引擎
    • 跨庫結果集 聚合/排序/分組
      • 不容許跨庫操做
      • 分別查詢,而後再應用端合併
    • 項目中的處理
      • 複製
        • 採用了主從架構,實現了"手動讀寫分離",但沒有對主從延遲進行特殊處理
      • 分片
        • 實現了垂直分表
        • 使用了雪花算法生成了分佈式ID,爲水平分表提供了準備(單錶行數至少超過1000萬)
        • 因爲垂直分表後沒有分庫,因此沒有(不須要)實現分佈式事務(全部寫操做都在一個主庫中)
      • 沒有使用分佈式中間件
    • 應用層設計方案
      • 悲觀鎖
        • 開發者主動設置鎖
      • 樂觀鎖
        • 先不加鎖(假設不會有併發問題),可是更新前校驗數據一致性,須要手動代碼實現
        • Django項目中先判斷庫存,再生成訂單,就是樂觀鎖設計
        • 高級的樂觀鎖可能會採用版本號/時間戳來校驗,須要進行表設計
        • 1 讀取點贊數,如like_count=10
          2 每次更新表中的數據時,爲了防止發生衝突,須要這樣操做
          3 update t_article set like_count = 11 where article_id = 5 and like_count = 10;
相關文章
相關標籤/搜索