偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

詳解美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件MTDDL

數(shù)據(jù)庫(kù) MySQL 分布式
2016年Q3季度初,在美團(tuán)外賣上單2.0項(xiàng)目上線后,商家和商品數(shù)量急速增長(zhǎng),預(yù)估商品庫(kù)的容量和寫峰值QPS會(huì)很快遇到巨大壓力。隨之而來(lái)也會(huì)影響線上服務(wù)的查詢性能、DB(數(shù)據(jù)庫(kù),以下統(tǒng)一稱DB)主從延遲、表變更困難等一系列問(wèn)題。

背景

2016年Q3季度初,在美團(tuán)外賣上單2.0項(xiàng)目上線后,商家和商品數(shù)量急速增長(zhǎng),預(yù)估商品庫(kù)的容量和寫峰值QPS會(huì)很快遇到巨大壓力。隨之而來(lái)也會(huì)影響線上服務(wù)的查詢性能、DB(數(shù)據(jù)庫(kù),以下統(tǒng)一稱DB)主從延遲、表變更困難等一系列問(wèn)題。

[[273412]]

要解決上面所說(shuō)的問(wèn)題,通常有兩種方案。第一種方案是直接對(duì)現(xiàn)有的商品庫(kù)進(jìn)行垂直拆分,可以緩解目前寫峰值QPS過(guò)大、DB主從延遲的問(wèn)題。第二種方案是對(duì)現(xiàn)有的商品庫(kù)大表進(jìn)行分庫(kù)分表,從根本上解決現(xiàn)有問(wèn)題。方案一實(shí)施起來(lái)周期較短,但只能解決一時(shí)之痛,由此可見,分庫(kù)分表是必然的。

在確定分庫(kù)分表的方案之后,我們調(diào)研了外賣訂單、結(jié)算以及主站等業(yè)務(wù)的分庫(kù)分表實(shí)現(xiàn)方案,也調(diào)研了業(yè)界很多分庫(kù)分表中間件。在綜合考慮性能、穩(wěn)定性及實(shí)現(xiàn)成本的前提下,最終決定自主研發(fā)客戶端分庫(kù)分表中間件MTDDL來(lái)支撐外賣商品分庫(kù)分表項(xiàng)目,這也就是MTDDL的由來(lái)。

當(dāng)然,在MTDDL的設(shè)計(jì)研發(fā)過(guò)程中,我們充分考慮了MTDDL的通用性、可擴(kuò)展性、功能的全面性和接入的便利性。到目前為止一共開發(fā)了四期,實(shí)現(xiàn)了MySQL動(dòng)態(tài)數(shù)據(jù)源、讀寫分離、分布式唯一主鍵生成器、分庫(kù)分表、連接池及SQL監(jiān)控、動(dòng)態(tài)化配置等一系列功能,支持分庫(kù)分表算法、分布式唯一主鍵生成算法的高可擴(kuò)展性,而且支持全注解的方式接入,業(yè)務(wù)方不需要引入任何配置文件。

下面就部分業(yè)界方案及MTDDL的設(shè)計(jì)目標(biāo)詳細(xì)展開下,然后從源碼的角度來(lái)剖析下MTDDL的整個(gè)邏輯架構(gòu)和具體實(shí)現(xiàn)。

業(yè)界調(diào)研

業(yè)界組件簡(jiǎn)介實(shí)現(xiàn)方案功能特性優(yōu)點(diǎn)缺點(diǎn)AtlasQihoo 360開發(fā)維護(hù)的一個(gè)基于MySQL協(xié)議的數(shù)據(jù)中間層項(xiàng)目。它實(shí)現(xiàn)了MySQL的客戶端與服務(wù)端協(xié)議,作為服務(wù)端與應(yīng)用程序通信,同時(shí)作為客戶端與MySQL通信proxy-based實(shí)現(xiàn)讀寫分離、單庫(kù)分表功能簡(jiǎn)單,性能跟穩(wěn)定性較好不支持分庫(kù)分表MTAtlas原美團(tuán)DBA團(tuán)隊(duì)在開源Atlas基礎(chǔ)上做的一系列升級(jí)改造proxy-based在讀寫分離、單庫(kù)分表的基礎(chǔ)上,完成了分庫(kù)分表的功能開發(fā)在Atlas基礎(chǔ)上支持了分庫(kù)分表當(dāng)時(shí)還處于測(cè)試階段,暫不推薦業(yè)務(wù)方使用TDDL淘寶根據(jù)自己的業(yè)務(wù)特點(diǎn)開發(fā)了TDDL框架,主要解決了分庫(kù)分表對(duì)應(yīng)用的透明化以及異構(gòu)數(shù)據(jù)庫(kù)之間的數(shù)據(jù)復(fù)制,它是一個(gè)基于集中式配置的JDBC datasource實(shí)現(xiàn)client-based實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源、讀寫分離、分庫(kù)分表功能齊全分庫(kù)分表功能還未開源,當(dāng)前公布文檔較少,并且需要依賴diamond(淘寶內(nèi)部使用的一個(gè)管理持久配置的系統(tǒng))ZebraZebra是原點(diǎn)評(píng)內(nèi)部使用數(shù)據(jù)源、DAO以及監(jiān)控等和數(shù)據(jù)庫(kù)打交道的中間件集client-based實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源、讀寫分離、分庫(kù)分表、CAT監(jiān)控功能齊全且有監(jiān)控接入較為復(fù)雜,當(dāng)時(shí)只支持c3p0、Druid、Tomcat JDBC等連接池,且分庫(kù)分表算法只支持Groovy表達(dá)式不易擴(kuò)展。

設(shè)計(jì)目標(biāo)

MTDDL(Meituan Distributed Data Layer),美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件,旨在為全公司提供一個(gè)通用數(shù)據(jù)訪問(wèn)層服務(wù),支持MySQL動(dòng)態(tài)數(shù)據(jù)源、讀寫分離、分布式唯一主鍵生成器、分庫(kù)分表、動(dòng)態(tài)化配置等功能,并且支持從客戶端角度對(duì)數(shù)據(jù)源的各方面(比如連接池、SQL等)進(jìn)行監(jiān)控,后續(xù)考慮支持NoSQL、Cache等多種數(shù)據(jù)源。

功能特性

  • 動(dòng)態(tài)數(shù)據(jù)源
  • 讀寫分離
  • 分布式唯一主鍵生成器
  • 分庫(kù)分表
  • 連接池及SQL監(jiān)控
  • 動(dòng)態(tài)化配置

邏輯架構(gòu)

下圖是一次完整的DAO層insert方法調(diào)用時(shí)序圖,簡(jiǎn)單闡述了MTDDL的整個(gè)邏輯架構(gòu)。其中包含了分布式唯一主鍵的獲取、動(dòng)態(tài)數(shù)據(jù)源的路由以及SQL埋點(diǎn)監(jiān)控等過(guò)程:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

具體實(shí)現(xiàn)

動(dòng)態(tài)數(shù)據(jù)源及讀寫分離

在Spring JDBC AbstractRoutingDataSource的基礎(chǔ)上擴(kuò)展出MultipleDataSource動(dòng)態(tài)數(shù)據(jù)源類,通過(guò)動(dòng)態(tài)數(shù)據(jù)源注解及AOP實(shí)現(xiàn)。

動(dòng)態(tài)數(shù)據(jù)源

MultipleDataSource動(dòng)態(tài)數(shù)據(jù)源類,繼承于Spring JDBC AbstractRoutingDataSource抽象類,實(shí)現(xiàn)了determineCurrentLookupKey方法,通過(guò)setDataSourceKey方法來(lái)動(dòng)態(tài)調(diào)整dataSourceKey,進(jìn)而達(dá)到動(dòng)態(tài)調(diào)整數(shù)據(jù)源的功能。其類圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

動(dòng)態(tài)數(shù)據(jù)源AOP

ShardMultipleDataSourceAspect動(dòng)態(tài)數(shù)據(jù)源切面類,針對(duì)DAO方法進(jìn)行功能增強(qiáng),通過(guò)掃描DataSource動(dòng)態(tài)數(shù)據(jù)源注解來(lái)獲取相應(yīng)的dataSourceKey,從而指定具體的數(shù)據(jù)源。具體流程圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

配置和使用方式舉例

  1. /** 
  2. * 參考配置 
  3. */ 
  4. <bean id="multipleDataSource" class="com.sankuai.meituan.waimai.datasource.multi.MultipleDataSource"
  5. /** 數(shù)據(jù)源配置 */ 
  6. <property name="targetDataSources"
  7. <map key-type="java.lang.String"
  8. /** 寫數(shù)據(jù)源 */ 
  9. <entry key="dbProductWrite" value-ref="dbProductWrite"/> 
  10. /** 讀數(shù)據(jù)源 */ 
  11. <entry key="dbProductRead" value-ref="dbProductRead"/> 
  12. </map> 
  13. </property> 
  14. </bean> 
  15. /** 
  16. * DAO使用動(dòng)態(tài)數(shù)據(jù)源注解 
  17. */ 
  18. public interface WmProductSkuDao { 
  19. /** 增刪改走寫數(shù)據(jù)源 */ 
  20. @DataSource("dbProductWrite"
  21. public void insert(WmProductSku sku); 
  22. /** 查詢走讀數(shù)據(jù)源 */ 
  23. @DataSource("dbProductRead"
  24. public void getById(long sku_id); 

分布式唯一主鍵生成器

眾所周知,分庫(kù)分表首先要解決的就是分布式唯一主鍵的問(wèn)題,業(yè)界也有很多相關(guān)方案:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

綜上,方案3的缺點(diǎn)可以通過(guò)一些手段避免,但其他方案的缺點(diǎn)不好處理,所以選擇第3種方案。目前該方案已由美團(tuán)點(diǎn)評(píng)技術(shù)工程部實(shí)現(xiàn)——分布式ID生成系統(tǒng)Leaf,MTDDL集成了此功能。

分布式ID生成系統(tǒng)Leaf

美團(tuán)點(diǎn)評(píng)分布式ID生成系統(tǒng)Leaf,其實(shí)是一種基于DB的Ticket服務(wù),通過(guò)一張通用的Ticket表來(lái)實(shí)現(xiàn)分布式ID的持久化,執(zhí)行update更新語(yǔ)句來(lái)獲取一批Ticket,這些獲取到的Ticket會(huì)在內(nèi)存中進(jìn)行分配,分配完之后再?gòu)腄B獲取下一批Ticket。整體架構(gòu)圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

每個(gè)業(yè)務(wù)tag對(duì)應(yīng)一條DB記錄,DB MaxID字段記錄當(dāng)前該Tag已分配出去的最大ID值。

IDGenerator服務(wù)啟動(dòng)之初向DB申請(qǐng)一個(gè)號(hào)段,傳入號(hào)段長(zhǎng)度如 genStep = 10000,DB事務(wù)置 MaxID = MaxID + genStep,DB設(shè)置成功代表號(hào)段分配成功。每次IDGenerator號(hào)段分配都通過(guò)原子加的方式,待分配完畢后重新申請(qǐng)新號(hào)段。

唯一主鍵生成算法擴(kuò)展

MTDDL不僅集成了Leaf算法,還支持唯一主鍵算法的擴(kuò)展,通過(guò)新增唯一主鍵生成策略類實(shí)現(xiàn)IDGenStrategy接口即可。IDGenStrategy接口包含兩個(gè)方法:getIDGenType用來(lái)指定唯一主鍵生成策略,getId用來(lái)實(shí)現(xiàn)具體的唯一主鍵生成算法。其類圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

分庫(kù)分表

在動(dòng)態(tài)數(shù)據(jù)源AOP的基礎(chǔ)上擴(kuò)展出分庫(kù)分表AOP,通過(guò)分庫(kù)分表ShardHandle類實(shí)現(xiàn)分庫(kù)分表數(shù)據(jù)源路由及分表計(jì)算。ShardHandle關(guān)聯(lián)了分庫(kù)分表上下文ShardContext類,而ShardContext封裝了所有的分庫(kù)分表算法。其類圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

分庫(kù)分表流程圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

分庫(kù)分表取模算法

分庫(kù)分表目前默認(rèn)使用的是取模算法,分表算法為 (#shard_key % (group_shard_num * table_shard_num)),分庫(kù)算法為 (#shard_key % (group_shard_num * table_shard_num)) / table_shard_num,其中g(shù)roup_shard_num為分庫(kù)個(gè)數(shù),table_shard_num為每個(gè)庫(kù)的分表個(gè)數(shù)。

例如把一張大表分成100張小表然后散到2個(gè)庫(kù),則0-49落在第一個(gè)庫(kù)、50-99落在第二個(gè)庫(kù)。核心實(shí)現(xiàn)如下:

  1. public class ModStrategyHandle implements ShardStrategy { 
  2. @Override 
  3. public String getShardType() { 
  4. return "mod"
  5. @Override 
  6. public DataTableName handle(String tableName, String dataSourceKey, int tableShardNum, 
  7. int dbShardNum, Object shardValue) { 
  8. /** 計(jì)算散到表的值 */ 
  9. long shard_value = Long.valueOf(shardValue.toString()); 
  10. long tablePosition = shard_value % tableShardNum; 
  11. long dbPosition = tablePosition / (tableShardNum / dbShardNum); 
  12. String finalTableName = new StringBuilder().append(tableName).append("_").append(tablePosition).toString(); 
  13. String finalDataSourceKey = new StringBuilder().append(dataSourceKey).append(dbPosition).toString(); 
  14. return new DataTableName(finalTableName, finalDataSourceKey); 

分庫(kù)分表算法擴(kuò)展

MTDDL不僅支持分庫(kù)分表取模算法,還支持分庫(kù)分表算法的擴(kuò)展,通過(guò)新增分庫(kù)分表策略類實(shí)現(xiàn)ShardStrategy接口即可。ShardStrategy接口包含兩個(gè)方法:getShardType用來(lái)指定分庫(kù)分表策略,handle用來(lái)實(shí)現(xiàn)具體的數(shù)據(jù)源及分表計(jì)算邏輯。其類圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

全注解方式接入

為了盡可能地方便業(yè)務(wù)方接入,MTDDL采用全注解方式使用分庫(kù)分表功能,通過(guò)ShardInfo、ShardOn、IDGen三個(gè)注解實(shí)現(xiàn)。

ShardInfo注解用來(lái)指定具體的分庫(kù)分表配置:包括分表名前綴tableName、分表數(shù)量tableShardNum、分庫(kù)數(shù)量dbShardNum、分庫(kù)分表策略shardType、唯一鍵生成策略idGenType、唯一鍵業(yè)務(wù)方標(biāo)識(shí)idGenKey;ShardOn注解用來(lái)指定分庫(kù)分表字段;IDGen注解用來(lái)指定唯一鍵字段。具體類圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

配置和使用方式舉例

  1. // 動(dòng)態(tài)數(shù)據(jù)源 
  2. @DataSource("dbProductSku"
  3. // tableName:分表名前綴,tableShardNum:分表數(shù)量,dbShardNum:分庫(kù)數(shù)量,shardType:分庫(kù)分表策略,idGenType:唯一鍵生成策略,idGenKey:唯一鍵業(yè)務(wù)方標(biāo)識(shí) 
  4. @ShardInfo(tableName="wm_food", tableShardNum=100, dbShardNum=1, shardType="mod", idGenType=IDGenType.LEAF, idGenKey=LeafKey.SKU) 
  5. @Component 
  6. public interface WmProductSkuShardDao { 
  7. // @ShardOn("wm_poi_id") 將該注解修飾的對(duì)象的wm_poi_id字段作為shardValue 
  8. // @IDGen("id") 指定要設(shè)置唯一鍵的字段 
  9. public void insert(@ShardOn("wm_poi_id") @IDGen("id") WmProductSku sku); 
  10. // @ShardOn 將該注解修飾的參數(shù)作為shardValue 
  11. public List<WmProductSku> getSkusByWmPoiId(@ShardOn long wm_poi_id); 

連接池及SQL監(jiān)控

DB連接池使用不合理容易引發(fā)很多問(wèn)題,如連接池最大連接數(shù)設(shè)置過(guò)小導(dǎo)致線程獲取不到連接、獲取連接等待時(shí)間設(shè)置過(guò)大導(dǎo)致很多線程掛起、空閑連接回收器運(yùn)行周期過(guò)長(zhǎng)導(dǎo)致空閑連接回收不及時(shí)等等,如果缺乏有效準(zhǔn)確的監(jiān)控,會(huì)造成無(wú)法快速定位問(wèn)題以及追溯歷史。

再者,如果缺乏SQL執(zhí)行情況相關(guān)監(jiān)控,會(huì)很難及時(shí)發(fā)現(xiàn)DB慢查詢等潛在風(fēng)險(xiǎn),而慢查詢往往就是DB服務(wù)端性能惡化乃至宕機(jī)的根源(關(guān)于慢查詢,推薦閱讀《MySQL索引原理及慢查詢優(yōu)化》一文)。MTDDL從1.0.2版本開始正式引入連接池及SQL監(jiān)控等相關(guān)功能。

連接池監(jiān)控

實(shí)現(xiàn)方案

結(jié)合Spring完美適配c3p0、dbcp1、dbcp2、mtthrift等多種方案,自動(dòng)發(fā)現(xiàn)新加入到Spring容器中的數(shù)據(jù)源進(jìn)行監(jiān)控,通過(guò)美團(tuán)點(diǎn)評(píng)統(tǒng)一監(jiān)控組件JMonitor上報(bào)監(jiān)控?cái)?shù)據(jù)。整體架構(gòu)圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

連接數(shù)量監(jiān)控

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

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

獲取連接時(shí)間監(jiān)控

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

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

SQL監(jiān)控

實(shí)現(xiàn)方案

采用Spring AOP技術(shù)對(duì)所有DAO方法進(jìn)行功能增強(qiáng)處理,通過(guò)美團(tuán)點(diǎn)評(píng)分布式會(huì)話跟蹤組件MTrace進(jìn)行SQL調(diào)用數(shù)據(jù)埋點(diǎn)及上報(bào),進(jìn)而實(shí)現(xiàn)從客戶端角度對(duì)SQL執(zhí)行耗時(shí)、QPS、調(diào)用量、超時(shí)率、失敗率等指標(biāo)進(jìn)行監(jiān)控。整體架構(gòu)圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

實(shí)現(xiàn)效果

登錄美團(tuán)點(diǎn)評(píng)的服務(wù)治理平臺(tái)OCTO選擇服務(wù)查看去向分析,效果圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

動(dòng)態(tài)化配置

為了滿足業(yè)務(wù)方一些動(dòng)態(tài)化需求,如解決線上DB緊急事故需動(dòng)態(tài)調(diào)整數(shù)據(jù)源或者分庫(kù)分表相關(guān)配置,要求無(wú)需重啟在線修改立即生效,MTDDL從1.0.3版本開始正式引入動(dòng)態(tài)化配置相關(guān)功能。

實(shí)現(xiàn)方案

在Spring容器啟動(dòng)的時(shí)候自動(dòng)注冊(cè)數(shù)據(jù)源及分庫(kù)分表相關(guān)配置到美團(tuán)點(diǎn)評(píng)的統(tǒng)一配置中心MCC,在MCC配置管理頁(yè)面可以進(jìn)行動(dòng)態(tài)調(diào)整,MCC客戶端在感知到變更事件后會(huì)刷新本地配置,如果是數(shù)據(jù)源配置變更會(huì)根據(jù)新的配置構(gòu)造出一個(gè)新數(shù)據(jù)源來(lái)替換老數(shù)據(jù)源,最后再將老的數(shù)據(jù)源優(yōu)雅關(guān)閉掉。具體流程圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

動(dòng)態(tài)化數(shù)據(jù)源

目前支持dbcp、dbcp2、c3p0等數(shù)據(jù)源,效果圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

分庫(kù)分表動(dòng)態(tài)化

支持動(dòng)態(tài)化配置分庫(kù)分表數(shù)量、分庫(kù)分表策略、唯一鍵生成策略、唯一鍵業(yè)務(wù)方標(biāo)識(shí)等,效果圖如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件

版本迭代

MTDDL到目前為止總共開發(fā)了四期,后續(xù)考慮逐步開源,具體版本迭代如下:

干貨分享:MTDDL—美團(tuán)點(diǎn)評(píng)分布式數(shù)據(jù)訪問(wèn)層中間件
責(zé)任編輯:華軒 來(lái)源: 今日頭條
相關(guān)推薦

2024-12-11 12:41:33

2021-11-14 16:07:35

中間件阿里Seata

2025-03-27 11:03:18

2024-05-07 07:58:10

數(shù)據(jù)架構(gòu)大數(shù)據(jù)中間件架構(gòu)

2017-12-04 09:00:00

金融開源軟件分布式消息中間件

2021-10-24 06:49:08

線程池中間件開源

2022-08-09 08:31:29

RocketMQ消息中間件

2015-06-19 07:50:47

2017-02-05 09:59:58

軟件

2016-09-23 09:22:12

2019-10-10 09:16:34

Zookeeper架構(gòu)分布式

2023-05-08 08:09:26

路由元信息謂詞

2019-08-23 13:10:39

美團(tuán)點(diǎn)評(píng)Kubernetes集群管理

2011-05-24 15:10:48

2021-02-11 08:21:02

中間件開發(fā)CRUD

2018-02-01 10:19:22

中間件服務(wù)器系統(tǒng)

2018-07-29 12:27:30

云中間件云計(jì)算API

2017-02-20 19:23:13

2024-07-11 11:17:00

消息隊(duì)列Java

2016-11-11 21:00:46

中間件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)