日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离

發布時間:2024/7/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


分布式數據層中間件:

1.簡介:

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

2.功能特性

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

常見的數據層中間件:

1.TDDL

淘寶根據自己的業務特點開發了TDDL框架,主要解決了分庫分表對應用的透明化以及異構數據庫之間的數據復制,它是一個基于集中式配置的JDBC datasource實現。

特點

實現動態數據源、讀寫分離、分庫分表。

缺點

分庫分表功能還未開源,當前公布文檔較少,并且需要依賴diamond(淘寶內部使用的一個管理持久配置的系統)

2.Atlas

Qihoo 360開發維護的一個基于MySQL協議的數據中間層項目。它實現了MySQL的客戶端與服務端協議,作為服務端與應用程序通信,同時作為客戶端與MySQL通信

特點:

實現讀寫分離、單庫分表

缺點:

不支持分庫分表

3.MTDDL(Meituan Distributed Data Layer)

美團點評分布式數據訪問層中間件

特點

實現動態數據源、讀寫分離、分庫分表,與tddl類似。

下面我以MTDDL為例,也可以參考淘寶tddl,完整詳解分布式數據層中間件的架構設計。

分布式數據層中間件架構設計

下圖是一次完整的DAO層insert方法調用時序圖,簡單闡述了MTDDL的整個邏輯架構。

其中包含了:

1.分布式唯一主鍵的獲取

2.動態數據源的路由

3.以及SQL埋點監控等過程

分布式數據層中間件:具體實現

1.動態數據源及讀寫分離

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

2.動態數據源

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

3.動態數據源AOP

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

4.配置和使用方式舉例

/*** 參考配置*//** 數據源配置 *//** 寫數據源 */ /** 讀數據源 */ /*** DAO使用動態數據源注解*/ public interface WmProductSkuDao {/** 增刪改走寫數據源 */@DataSource("dbProductWrite")public void insert(WmProductSku sku);/** 查詢走讀數據源 */@DataSource("dbProductRead")public void getById(long sku_id); }

5.分布式唯一主鍵生成器

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

序號實現方案優點缺點UUID本地生成,不需要RPC,低延時;

擴展性好,基本沒有性能上限無法保證趨勢遞增;

UUID過長128位,不易存儲,往往用字符串表示2Snowflake或MongoDB ObjectId分布式生成,無單點;

趨勢遞增,生成效率快沒有全局時鐘的情況下,只能保證趨勢遞增;

當通過NTP進行時鐘同步時可能會出現重復ID;

數據間隙較大3proxy服務+數據庫分段獲取ID分布式生成,段用完后需要去DB獲取,同server有序可能產生數據空洞,即有些ID沒有分配就被跳過了,主要原因是在服務重啟的時候發生;

無法保證有序,需要未來解決,可能會通過其他接口方案實現

綜上,方案3的缺點可以通過一些手段避免,但其他方案的缺點不好處理,所以選擇第3種方案:分布式ID生成系統Leaf。

6.分布式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號段分配都通過原子加的方式,待分配完畢后重新申請新號段。

7.唯一主鍵生成算法擴展

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

8.分庫分表

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

分庫分表流程圖如下:

9.分庫分表取模算法

分庫分表目前默認使用的是取模算法,分表算法為 (#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 {@Overridepublic String getShardType() {return "mod";}@Overridepublic 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);} }

10.分庫分表算法擴展

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

11.全注解方式接入

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

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

12.配置和使用方式舉例

// 動態數據源 @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 將該注解修飾的參數作為shardValuepublic ListgetSkusByWmPoiId(@ShardOn long wm_poi_id); }

連接池及SQL監控

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

連接池監控

實現方案

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

連接數量監控

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

獲取連接時間監控

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

你可能也喜歡:

  • Redis系列教程(八):分布式鎖的由來、及Redis分布式鎖的實現詳解
  • 阿里P8架構師談:深入探討HashMap的底層結構、原理、擴容機制
  • 淘寶發展歷程最具決定性的一次技術架構演變
  • 阿里P8架構師談:分布式Session共享的4類技術方案,與優劣勢比較
  • 阿里P8架構師談:分布式事務的解決方案,以及原理、總結
  • 阿里P8架構師談:分布式數據庫數據一致性的原理、與技術實現方案

  • 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。