MTDDL 美團分散式數據訪問中間件(轉)

来源:https://www.cnblogs.com/lenovo_tiger_love/archive/2019/06/27/11098627.html
-Advertisement-
Play Games

MTDDL 美團分散式數據訪問中間件(轉) "原文地址:MTDDL——美團點評分散式數據訪問層中間件" 因原文文字和圖顯示有問題,故整理於此,僅供參考。 業界方案 | 組件 | 簡介 | | : : | : | | Atlas | Qihoo 360開發維護的一個基於MySQL協議的數據中間層項目。 ...


MTDDL 美團分散式數據訪問中間件(轉)

原文地址:MTDDL——美團點評分散式數據訪問層中間件

因原文文字和圖顯示有問題,故整理於此,僅供參考。

業界方案
組件 簡介
Atlas Qihoo 360開發維護的一個基於MySQL協議的數據中間層項目。它實現了MySQL的客戶端與服務端協議,作為服務端與應用程式通信,同時作為客戶端與MySQL通信。
Cobar 阿裡巴巴B2B開發的關係型分散式系統,管理將近3000個MySQL實例。 在阿裡經受住了考驗,後面由於作者的走開的原因cobar沒有人維護 了,阿裡也開發了tddl替代cobar。
MyCAT 社區愛好者在阿裡cobar基礎上進行二次開發,解決了cobar當時存 在的一些問題,並且加入了許多新的功能在其中。目前MyCAT社區活 躍度很高,目前已經有一些公司在使用MyCAT。
TDDL 淘寶根據自己的業務特點開發了TDDL(Taobao Distributed Data Layer 框架,主要解決了分庫分表對應用的透明化以及異構資料庫之間的數據複製,它是一個基於集中式配置的 jdbc datasource實現,具有主備,讀寫分離,動態資料庫配置等功能。
Zebra 點評集團統一使用的MySQL資料庫訪問層的中間件。主要提供對業務開發透明、讀寫分庫、分庫分表能力,並提供了端到端SQL監控的集成方案

MTDDL(Meituan Distributed Data Layer),美團點評分散式數據訪問層中間件,旨在為全公司提供一個通用數據訪問層服務,支持MySQL動態數據源、讀寫分離、分散式唯一主鍵生成器、分庫分表、動態化配置等功能,並且支持從客戶端角度對數據源的各方面(比如連接池、SQL等)進行監控,後續考慮支持NoSQL、Cache等多種數據源。

  • 動態數據源
  • 讀寫分離
  • 分散式唯一主鍵生成器
  • 分庫分表
  • 連接池及SQL監控
  • 動態化配置

下圖是一次完整的DAO層insert方法調用時序圖,簡單闡述了MTDDL的整個邏輯架構。其中包含了分散式唯一主鍵的獲取、動態數據源的路由以及SQL埋點監控等過程:

動態數據源及讀寫分離

在Spring JDBC AbstractRoutingDataSource的基礎上擴展出MultipleDataSource動態數據源類,通過動態數據源註解及AOP實現。

動態數據源

MultipleDataSource動態數據源類,繼承於Spring JDBC AbstractRoutingDataSource抽象類,實現了determineCurrentLookupKey方法,通過setDataSourceKey方法來動態調整dataSourceKey,進而達到動態調整數據源的功能。其類圖如下:

動態數據源AOP

ShardMultipleDataSourceAspect動態數據源切麵類,針對DAO方法進行功能增強,通過掃描DataSource動態數據源註解來獲取相應的dataSourceKey,從而指定具體的數據源。具體流程圖如下:

配置和使用方式舉例
/**配置參考*/
<bean id="multipleDataSource" class="com.sankuai.meituan.waimai.datasource.multi.MultipleDataSource">
    /** 數據源配置 */
    <property name="targetDataSources">
        <map key-type="java.lang.String"> 
            /** 寫數據源 */
            <entry key="dbProductWrite" value-ref="dbProductWrite"/>
            /** 讀數據源 */
            <entry key="dbProductRead" value-ref="dbProductRead"/>
        </map>
    </property>  
</bean>
/**
 * DAO使用動態數據源註解
 */
public interface WmProductSkuDao {

    /** 增刪改走寫數據源 */
    @DataSource("dbProductWrite")
    public void insert(WmProductSku sku);

    /** 查詢走讀數據源 */
    @DataSource("dbProductRead")
    public void getById(long sku_id);
}
分散式唯一主鍵生成器

眾所周知,分庫分表首先要解決的就是分散式唯一主鍵的問題,業界也有很多相關方案:


























序號 實現方案 優點 缺點
1 UUID
本地生成,不需要RPC,低延時,擴展性好,基本沒有性能上限
無法保證趨勢遞增,UUID過長128位,不易存儲,往往用字元串表示
2 Snowflake或MongoDB ObjectId
分散式生成,無單點;趨勢遞增,生成效率快
沒有全局時鐘的情況下,只能保證趨勢遞增;當通過NTP進行時鐘同步時可能會出現重覆ID;數據間隙較大
3 proxy服務 + 資料庫分段獲取ID
分散式生成,段用完後需要去DB獲取,同server有序
可能產生數據空洞,即有些ID沒有分配就被跳過了,主要原因是在服務重啟的時候發生;無法保證有序,需要未來解決,可能會通過其他介面方案實現

綜上,方案3的缺點可以通過一些手段避免,但其他方案的缺點不好處理,所以選擇第3種方案。目前該方案已由美團點評技術工程部實現——分散式ID生成系統Leaf,MTDDL集成了此功能。

分散式ID生成系統Leaf

美團點評分散式ID生成系統Leaf,其實是一種基於DB的Ticket服務,通過一張通用的Ticket表來實現分散式ID的持久化,執行update更新語句來獲取一批Ticket,這些獲取到的Ticket會在記憶體中進行分配,分配完之後再從DB獲取下一批Ticket。整體架構圖如下:


每個業務tag對應一條DB記錄,DB MaxID欄位記錄當前該Tag已分配出去的最大ID值。

IDGenerator服務啟動之初向DB申請一個號段,傳入號段長度如 genStep = 10000,DB事務置 MaxID = MaxID + genStep,DB設置成功代表號段分配成功。每次IDGenerator號段分配都通過原子加的方式,待分配完畢後重新申請新號段。

唯一主鍵生成演算法擴展

MTDDL不僅集成了Leaf演算法,還支持唯一主鍵演算法的擴展,通過新增唯一主鍵生成策略類實現IDGenStrategy介面即可。IDGenStrategy介面包含兩個方法:getIDGenType用來指定唯一主鍵生成策略,getId用來實現具體的唯一主鍵生成演算法。其類圖如下:

分庫分表

在動態數據源AOP的基礎上擴展出分庫分表AOP,通過分庫分表ShardHandle類實現分庫分表數據源路由及分表計算。ShardHandle關聯了分庫分表上下文ShardContext類,而ShardContext封裝了所有的分庫分表演算法。其類圖如下:

  • 分庫分表流程圖如下:

    分庫分表取模演算法
    分庫分表目前預設使用的是取模演算法,分表演算法為 (#shard_key % (group_shard_num * table_shard_num)),分庫演算法為 (#shard_key % (group_shard_num * table_shard_num)) / table_shard_num,其中group_shard_num為分庫個數,table_shard_num為每個庫的分表個數。

    例如把一張大表分成100張小表然後散到2個庫,則0-49落在第一個庫、50-99落在第二個庫。核心實現如下:
public class ModStrategyHandle implements ShardStrategy {

    @Override
    public String getShardType() {
        return "mod";
    }

    @Override
    public DataTableName handle(String tableName, String dataSourceKey, int tableShardNum, 
        int dbShardNum, Object shardValue) {

        /** 計算散到表的值 */
        long shard_value = Long.valueOf(shardValue.toString());
        long tablePosition = shard_value % tableShardNum;
        long dbPosition = tablePosition / (tableShardNum / dbShardNum);
        String finalTableName = new StringBuilder().append(tableName).append("_").append(tablePosition).toString();
        String finalDataSourceKey = new StringBuilder().append(dataSourceKey).append(dbPosition).toString();

        return new DataTableName(finalTableName, finalDataSourceKey);
    }
}
分庫分表演算法擴展

MTDDL不僅支持分庫分表取模演算法,還支持分庫分表演算法的擴展,通過新增分庫分表策略類實現ShardStrategy介面即可。ShardStrategy介面包含兩個方法:getShardType用來指定分庫分表策略,handle用來實現具體的數據源及分表計算邏輯。其類圖如下:

全註解方式接入

為了儘可能地方便業務方接入,MTDDL採用全註解方式使用分庫分表功能,通過ShardInfo、ShardOn、IDGen三個註解實現。

ShardInfo註解用來指定具體的分庫分表配置:包括分表名首碼tableName、分表數量tableShardNum、分庫數量dbShardNum、分庫分表策略shardType、唯一鍵生成策略idGenType、唯一鍵業務方標識idGenKey;ShardOn註解用來指定分庫分表欄位;IDGen註解用來指定唯一鍵欄位。具體類圖如下:

配置和使用方式舉例
// 動態數據源
@DataSource("dbProductSku")

// tableName:分表名首碼,tableShardNum:分表數量,dbShardNum:分庫數量,shardType:分庫分表策略,idGenType:唯一鍵生成策略,idGenKey:唯一鍵業務方標識
@ShardInfo(tableName="wm_food", tableShardNum=100, dbShardNum=1, shardType="mod", idGenType=IDGenType.LEAF, idGenKey=LeafKey.SKU)  

@Component
public interface WmProductSkuShardDao {

    // @ShardOn("wm_poi_id") 將該註解修飾的對象的wm_poi_id欄位作為shardValue
    // @IDGen("id")  指定要設置唯一鍵的欄位
    public void insert(@ShardOn("wm_poi_id") @IDGen("id") WmProductSku sku);

    // @ShardOn 將該註解修飾的參數作為shardValue
    public List<WmProductSku> getSkusByWmPoiId(@ShardOn long wm_poi_id);
}
連接池及SQL監控

DB連接池使用不合理容易引發很多問題,如連接池最大連接數設置過小導致線程獲取不到連接、獲取連接等待時間設置過大導致很多線程掛起、空閑連接回收器運行周期過長導致空閑連接回收不及時等等,如果缺乏有效準確的監控,會造成無法快速定位問題以及追溯歷史。

再者,如果缺乏SQL執行情況相關監控,會很難及時發現DB慢查詢等潛在風險,而慢查詢往往就是DB服務端性能惡化乃至宕機的根源(關於慢查詢,推薦閱讀《MySQL索引原理及慢查詢優化》一文)。MTDDL從1.0.2版本開始正式引入連接池及SQL監控等相關功能。

連接池監控

實現方案

結合Spring完美適配c3p0、dbcp1、dbcp2、mtthrift等多種方案,自動發現新加入到Spring容器中的數據源進行監控,通過美團點評統一監控組件JMonitor上報監控數據。整體架構圖如下:

連接數量監控

監控連接池active、idle、total連接數量,Counter格式:(連接池類型.數據源.active/idle/total_connection),效果圖如下:

獲取連接時間監控

監控獲取空閑連接時間,Counter格式:(ds.getConnection.數據源.time),效果圖如下:

SQL監控

實現方案

採用Spring AOP技術對所有DAO方法進行功能增強處理,通過美團點評分散式會話跟蹤組件MTrace進行SQL調用數據埋點及上報,進而實現從客戶端角度對SQL執行耗時、QPS、調用量、超時率、失敗率等指標進行監控。整體架構圖如下:

實現效果

登錄美團點評的服務治理平臺OCTO選擇服務查看去向分析,效果圖如下:

動態化配置

為了滿足業務方一些動態化需求,如解決線上DB緊急事故需動態調整數據源或者分庫分表相關配置,要求無需重啟線上修改立即生效,MTDDL從1.0.3版本開始正式引入動態化配置相關功能。

實現方案

在Spring容器啟動的時候自動註冊數據源及分庫分表相關配置到美團點評的統一配置中心MCC,在MCC配置管理頁面可以進行動態調整,MCC客戶端在感知到變更事件後會刷新本地配置,如果是數據源配置變更會根據新的配置構造出一個新數據源來替換老數據源,最後再將老的數據源優雅關閉掉。具體流程圖如下:

動態化數據源

目前支持dbcp、dbcp2、c3p0等數據源,效果圖如下:

分庫分表動態化

支持動態化配置分庫分表數量、分庫分表策略、唯一鍵生成策略、唯一鍵業務方標識等,效果圖如下:

MTDDL到目前為止總共開發了四期,後續考慮逐步開源,具體版本迭代如下:

項目名 功能 開始時間 結束時間 正式版本 快照版本 版本備註
MTDDL一期 動態數據源 2016.05.30 2016.06.16 0.0.1 0.0.1-SNAPSHOT MTDDL第一版
讀寫分離
分散式唯一主鍵生成器
分庫分表
MTDDL二期 分散式唯一主鍵生成演算法可擴展 2016.08.23 2016.09.05 1.0.1 1.0.1-SNAPSHOT MTDDL接入優化
支持零配置接入MTDDL
優化shardkey配置方式
MTDDL三期 連接池及SQL監控 2016.09.06 2016.09.20 1.0.2 1.0.2-SNAPSHOT MTDDL監控完善
緩存優化
MTDDL四期 唯一主鍵生成註解化 2016.10.11 2016.11.08 1.0.3 1.0.3-SNAPSHOT MTDDL配置動態化
動態化配置

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

-Advertisement-
Play Games
更多相關文章
  • 獲取客戶端公網IP 獲取客戶端內網IP(IE不支持) 原文鏈接:https://ourcodeworld.com/articles/read/257/how-to-get-the-client-ip-address-with-javascript-only ...
  • 單個的點擊展示下拉菜單比較簡單。比如點擊右上角的設置按鈕會彈出修改密碼和退出功能等。 多個的點擊式展示下拉菜單,在之前有發過。 ...
  • 記錄對象的一些實用使用方法及屬性 // Object.assign() 多個對象合併 key相同則後面的覆蓋前面的 const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object. ...
  • 1.Javascript是什麼?可以做什麼? 1) JavaScript是一種基於對象和事件驅動的解釋性腳本語言, 它具有與Java和C語言類似的語法。 2) JavaScript可直接嵌入HTML頁面。由客戶端的瀏覽器解釋執行代碼,不進行預編譯。 3) 所有現代的html頁面都使用Javascri ...
  • ...
  • 現在越來越多的項目就算是一個管理後端也偏向於使用前後端分離的部署方式去做,為了順應時代的潮流,一前後端分離就產生了跨域問題,所以許多同學把跨域和前後端分離項目聯繫在了一起,其實跨域產生的原因並不是前後端分離導致的,那我們一起來看一下,希望可以靠這一篇文章解答大家所有的跨域問題 一、跨域產生的條件 使 ...
  • 背景介紹 上篇介紹了利用Nginx反向代理實現負載均衡,本文詳細講述Nginx下的幾種負載均衡策略。 輪詢 輪詢,顧名思義,就是輪流請求,基於上篇文章的介紹,我們將負載均衡策略聚焦於 文件的 。 在瀏覽器中對 連續發出請求,根據nginx請求日誌可以看出web02與web03訪問的次數是相同的。 加 ...
  • 1、簡介 SOA(Service Oriented Architecture)“面向服務的架構”:他是一種設計方法,其中包含多個服務, 服務之間通過相互依賴最終提供一系列的功能。一個服務 通常以獨立的形式存在與操作系統進程中。各個服務之間 通過網路調用。 2、和微服務對比 微服務架構其實和 SOA ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...