架構思考-業務快速增長時的容量問題

来源:https://www.cnblogs.com/xiexj/archive/2020/06/16/13138052.html

背景 之前做過一個項目,資料庫存儲採用的是mysql。當時面臨著業務指數級的增長,存儲容量不足。當時採用的措施是 1>短期解決容量的問題 mysql從5.6升級5.7,因為數據核心且重要,資料庫主從同步採用的是全同步, 利用5.7並行複製新特性,減少了主從同步的延遲,提高了吞吐量。 當時業務量高峰是 ...


背景

之前做過一個項目,資料庫存儲採用的是mysql。當時面臨著業務指數級的增長,存儲容量不足。當時採用的措施是

 

1>短期解決容量的問題

mysql從5.6升級5.7,因為數據核心且重要,資料庫主從同步採用的是全同步, 利用5.7並行複製新特性,減少了主從同步的延遲,提高了吞吐量。

 

當時業務量高峰是2000TPS,5.6時可承受的最大TPS是3000,升級到5.7壓測可承受的最大TPD是5000.

 

2>流量拆分,從根本上解決容量問題

首先進行容量評估,通過對於業務開展規劃、活動預估,年底的容量會翻5倍。由於目前指數級增長的特性,資料庫要預留至少4倍的冗餘。

 

要對資料庫進行擴容,因為我們已經使用的是最頂配的SSD物理機了,就算可以在linux內核層面對numa進行綁核和非綁核等測試調參優化性能,提升容量也很有限。註意:一般的業務系統numa綁核會提高性能,但是mysql等資料庫系統是相反的。

 

所以垂直擴容不成功,就看看是否可以拆分流量。mysql流量拆分方式有x軸拆分(水平拆分)、y軸拆分(垂直拆分)、z軸拆分。

 

其中y軸拆分(垂直拆分)就是目前都在說做垂直領域,就是在一個細分領域里做深入的意思。由此可以很容易的記住垂直拆分的意思就是按照業務領域進行拆分,專庫專用。實際上能按領域拆分是最理想的,因為這種拆分業務清晰;拆分規則明確;系統之間整合或擴展容易。但是因為當時的業務已經很簡單,y軸拆分已經沒有什麼空間,這種拆分不能達到擴容20倍的目的。

 

z軸拆分近幾年沒有聽說過了,實際上大家也一直在用。這種方式是將一張大表拆分為子母表,就是分為概要信息和詳細信息。這種拆分方式對解決容量問題意義不大。

 

比較可行的一個方案是水平拆分。就是常說的分庫分表。按照容量評估,資料庫水平拆分一拆十,根據業務特點找一個標準欄位來進行取模。

 

水平拆分一個技術點在於新老切換。

採用的是資料庫雙寫的方式,採用非同步確保性的補償型事務,發送實時和延遲兩個MQ,通過開關來控制以老數據為準還是新資料庫為準。開始時以老資料庫為準,觀察新老數據沒有一致性問題之後,在一個低峰期,關閉了系統入口,等資料庫沒有任何變更之後切換開關,再打開系統入口。

 

問題

對於容量問題,上面採用的是一次性拆分到位的方法。對於一個規模稍大的公司來講,10組物理機(1組包含1主N從)的成本還好。

1>如果量級再次升級,需要每周增加10台資料庫才能支撐容量呢?

2>並且對系統可用性還有強要求,1s的停機都不可以接受呢?

 

解決方案分析

垂直流量拆分

首先我要分析的是每周增加10台資料庫這個容量是不是合理的。是否存在放大效應或者說可以減少對mysql這種昂貴資源的使用,轉為增加對HBase、Elasticsearch這種低成本高擴展性資源的使用呢?

 

基於這個思路,我們需要梳理下是否有可垂直拆分的流量。比如正向流量和負向流量。所謂正向流量是指比如交易下單,負向流量就是取消訂單,包括已付款取消、未付款取消、已到貨取消、未到貨取消等等。實際上負向流量在總訂單里占比很少,但是業務要比正向交易業務複雜。將正向和逆向拆分的一個主要優勢是分治思想,可以降低兩部分各自的複雜度。將流量拆分重心轉移到正向流量上。

 

對於正向流量,一個業務比較常用的流量拆分思路是CQRS命令查詢分離,也就是常說的讀寫分離。如果讀流量大於寫流量。可以考慮能否將讀流量進一步拆分。拆分成實時和離線,將實時性要求不高的查詢走ES。ES的數據可以通過同步binlog變更獲得。

 

另外一個思路是將資料庫按照歷史數據來拆分。就是資料庫里只保存一定時間內的實時數據。超過指定時間則進行數據歸檔。將數據歸檔到HBase等,一般對於歷史的查詢實時性要求也不是很高。

 

垂直流量拆分可能遇到的問題

以上方法都是只考慮問題1如果量級再次升級,需要每周增加10台資料庫才能支撐容量的方案。如果再考慮問題2並且對系統可用性還有強要求,1s的停機都不可以接受。就需要看上述方案可能會遇到的問題。

 

拆分正向流量和負向流量、CQRS都需要改造,改造過程就需要過渡。過渡可以採用上面說的雙寫方式,觀察運行情況進行切換。切換過程中也可以不關閉流量。

 

麻煩的是數據歸檔。因為數據歸檔後刪除資料庫的數據,變更生效時,針對innodb來說,意味著數據結構重建,頻繁IO。這會影響OLTP線上事務的處理。可以考慮按表來歸檔,控制操作頻率,控制單位時間內對IO的影響。

 

分散式關係型資料庫

分散式關係型資料庫本質上是通過增加代理等方式將分庫分表做的更加隱蔽。

 

阿裡巴巴分散式關係資料庫(DRDS),前身是淘寶分散式數據層(TDDL),核心就是用於分庫分表管理的代理層,宣稱可實現平滑擴容。

 

 

擴容過程實際是物理數據遷移的過程,引擎層按照分庫遷移後的邏輯先在物理節點上建立新的分庫,然後保留一個時間點進行全量的數據遷移。完成全量遷移後,開始基於先前保留的時間點進行增量的數據追趕。當增量數據追趕到兩邊的數據幾乎一致時,對資料庫進行瞬時停寫,將最後的數據追平,引擎層進行分庫邏輯的路由切換,路由規則切換完成後就完成了核心的擴容邏輯,整個切換過程在毫秒級別完成。

 

因為整個過程是毫秒級,所以可以做到業務層沒有感知,等多就是看到擴容過程中請求延時增加了不到1s。從原理上來說是可行的。

 

NOSQL解決方案

像這麼大的數據量一個很好的參考是12306。12306採用的是Geode。它是有資料庫功能的記憶體數據網格(In-Memory Data Grid,IMDG)。其重要特性是

 

1)集群記憶體總容量,現在Geode可以實現單個節點200-300GB記憶體,總集群包含300個節點的大型集群,因此總容量可以達到90TB左右的級別。

 

2)Geode集群功能非常強大,實現了記憶體中數據Shard分佈,自動管理,集群故障自動恢復,自動平均分佈等一系列企業級的功能,而且有自帶的集群間數據同步功能。

 

3)在CAP原理下(不瞭解的話可以百度一下CAP不可能三角),Geode可以保證集群內數據的強一致性,註意是真正的強一致性而不是最終一致性,再加上分區可用性,因此是一個CP型的產品,可以提供統一的數據視圖,支持高併發下的acid事務。

 

採用新的解決方案最大問題是平滑過渡,平滑過渡方面我還是覺得上面提到的資料庫雙寫方式安全可靠。

 

系統共建的解決方案

如果達到我所說的量級,基本上在一個行業中是處於壟斷地位的。並不是一家純的互聯網公司。這種公司可以採用和互聯網大廠合作的方式、用已經有這方面經驗的大廠,來根據自己內部系統的特性共建一套合適自己的定製化資料庫。


您的分享是我們最大的動力!

更多相關文章
  • 在平時的開發過程中,父子 / 兄弟組件間的通信是肯定會遇到的啦,所以這裡總結了 6 種 Vue 組件的通信props / $e$emit / Vuex$attrs / $listeners $parent / $children 與 ref provide / inject 前言 如上圖所示,A/B ...
  • 只要接觸過前端,都會指導web前端的知識主要由三部分組成:分別為靜態html,樣式css,動態javascript(簡稱js)這三大部分組成。其三部分組成的一個體系的複雜程度不亞於其他一門技術的複雜程度。當然對於跟我一樣厲害的那些web前端來說那就是小菜一碟,但是很多人都只學了錶面,基礎部分,很多重 ...
  • 在日常開發中,項目中的菜單欄都是已經實現好了的。如果需要添加新的菜單,只需要在`路由配置`中新增一條路由,就可以實現菜單的添加。 相信大家和我一樣,有時候會躍躍欲試自己去實現一個菜單欄。那今天我就將自己實現的菜單欄的整個思路和代碼分享給大家。 ...
  • 1.let 和 const 命令 在es5時,只有兩種變數聲明,var 和function。在es6中新增了四種let和const,以及另外兩種聲明import和class。 我們先講解let和const,後續會補充import和class (1)let 我們先來看基本語法 { let a = 10 ...
  • 目錄: 1.擴展運算符2.Array.form()3.Array.of()4.數組實例的copyWithin()5.數組實例的find()和findIndex()6.數組實例的fill()7.數組實例的entries(),keys(),vlaues()8.數組實例的includes()9.數組的空位 ...
  • 也許你瞧不起以前的 css ,但是你不該再輕視眼下的 css 。近年來 css 的變數系統已逐步得到各大瀏覽器廠商支持,自定義選擇器等強勢襲來,嵌套系統/模塊系統也在路上…為了更好的掌握 css 這門語言,很有必要把之前零零散散的 css 知識回爐重造下。 css 作為一門語言而,也有其繼承原理,雖 ...
  • 將一些零散的知識點進行整理, 以便加深理解,方便查閱,也希望能幫到大家。 一、負載均衡演算法 1. 隨機 完全隨機 通過系統隨機函數,根據後端伺服器列表的大小值來隨機選擇其中一臺進行訪問。由概率統計理論可以得知,隨著調用量的增大,其實際效果越來越接近於平均分配流量到每一臺後端伺服器,也就是輪詢的效果。 ...
  • /** * 1.模式定義: * 過濾器(Filter Pattern)又稱為標準模式(Criteria Pattern)是一種設計模式,這種模式允許開發人員使用不同的標準來過濾一組對象, * 通過預算邏輯以解耦的方式將他們聯繫起來。這種類型的設計模式屬於結構模型,說白了,就是按條件篩選一組對象出來。 ...
一周排行
  • 本次課程就正式進入開發部分。 首先我們先搭建項目框架,還是和之前漸進式風格保持一致,除必備組件外,儘量使用原生功能以方便大家理解。 開發工具:vs 2019 或以上 資料庫:SQL SERVER 2017 或以上 其他需要用到的我們在項目過程中再提。 一、新建 MVC項目 1、打開VS 2019,C ...
  • 一.背景說明: 之前分享過一個微服務開發框架, “享一個集成.NET Core+Swagger+Consul+Polly+Ocelot+IdentityServer4+Exceptionless+Apollo+SkyWalking的微服務開發框架”,前兩天在Github上收到一個Issues,是想我 ...
  • 前言 Http我們都已經耳熟能詳了,而關於Http學習的文章網上有很多,各個知識點的講解也可說是深入淺出。然而,學習過後,我們對Http還是一知半解。問題出在了哪? Http是一個客戶機與伺服器之間的通信的協議,真的想學習Http,就必須把客戶機和伺服器也學了,也就是說,必須立體的學習,不然我們永遠 ...
  • 本人製作的這個 “簡易日誌 (SimpleLogger)” 包裡面包含的代碼邏輯,最開始也就是簡單地寫入文本,後來經過實際使用的演化,做了各種優化,添加了一些實用的特性,感覺用著還不錯。正所謂獨樂樂不如眾樂樂,於是將其打包上傳到微軟的包管理庫 NuGet 中,大家可以使用試試,相互交流。 ...
  • 1.需求示意圖 2.需求描述 原本是為了給做unity3d客戶端開發的同事提供不定時的消息推送,比如商城購買道具後服務端將道具信息推送給客戶端。 本篇文章簡化理解,用“相關部門開展活動,向全市人民徵集社會服務改善意見”為例子。但核心想法一致:單向推送(指這個需求上只需要單向)。所以這個功能並不是聊天 ...
  • 找到項目中ServiceStack.Text.dll文件的版本,比如我的版本是5.0.0,到GitHub上下載對應的源碼(https://github.com/ServiceStack/ServiceStack.Text/tags) 打開解決方案,重新生成ServiceStack.Text項目,如果 ...
  • 前言 上一篇文章主要介紹了IL的概念以及基礎的示例代碼,在這一篇文章中我們將通過對象調用看IL。 創建對象與調用方法 class Program { static void Main(string[] args) { var obj = new MyClass(); Console.WriteLin ...
  • abp版本5.9 概述 數據遷移無非就是兩件事情,1、創建資料庫,並根據實體創建對應的表;2、添加一些初始數據 abp的數據遷移也是完成這兩件事,比較特殊的是它是多租戶saas系統,而且支持不同的租戶有獨立的資料庫。所以abp中的遷移要先遷移戶主Host,再遷移租戶Tenant的資料庫 它的遷移定義 ...
  • 本文屬於OData系列 目錄 武裝你的WEBAPI-OData入門 武裝你的WEBAPI-OData便捷查詢 武裝你的WEBAPI-OData分頁查詢 武裝你的WEBAPI-OData資源更新Delta 武裝你的WEBAPI-OData之EDM 武裝你的WEBAPI-OData常見問題 武裝你的WE ...
  • 前言 面試總是會被問到有沒有用過分散式鎖、redis 鎖,大部分讀者平時很少接觸到,所以只能很無奈的回答 “沒有”。本文通過 Spring Boot 整合 redisson 來實現分散式鎖,並結合 demo 測試結果。 首先看下大佬總結的圖 正文 添加依賴 <!--redis--> <depende ...