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

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

分布式数据层中间件:

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),效果图如下:

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

money.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

清华硕士眼中的2021届算法岗秋招

文 | 李金泽一晃接近三个月过去了,秋招也到了尾声,之前一直忙于写毕业论文,现在在这里想总结一些自己求职互联网大厂算法岗的面经和心得,希望帮助后来的学弟学妹们收获自己心仪的offer。今年的算法岗求职较往年竞争也更加激烈&…

LeetCode 124. 二叉树中的最大路径和(DFS)

文章目录1. 题目信息2. 解题1. 题目信息 给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 示例 1:输入: [1,2,3]1/ \2 …

Python的reshape的用法:reshape(1,-1)

Python的reshape的用法:reshape(1,-1)https://blog.csdn.net/qq_29831163/article/details/90112000 目录 numpy中reshape函数的三种常见相关用法 reshape(1,-1)转化成1行: reshape(2,-1)转换成两行: reshape(-1,1)转换成1列: …

阿里P8架构师谈:流量高峰时期的性能瓶颈有哪些、以及如何来解决

在高并发大量用户的场景,系统一般会面临如下三个挑战: 1. 日益增长的用户数量 2. 日渐复杂的业务 3. 急剧膨胀的数据 这些挑战对于性能优化而言表现为:在保持和降低系统TP95响应时间(指的是将一段时间内的请求响应时间从低到高…

详解凸优化、图神经网络、强化学习、贝叶斯方法等四大主题

加入AI行业拿到高薪仅仅是职业生涯的开始。现阶段AI人才结构在不断升级,对AI人才的要求也不断升高,如果对自己没有很高的要求,其实很容易被快速发展的趋势所淘汰。为了迎合时代的需求,我们去年推出了《机器学习高端训练营》班。这…

可扩展的TextView,ExpandableTextView与Scroller类的使用

转载时请注明出处,尊重他人的劳动成果,谢谢。 废话不多说,先上图演示下成果(图有些丑,别见怪): 最近一直在研究Scroller类的使用方法,看了很多遍别人的例子总是感觉不得要领,最后还是自己实践…

消息中间件系列(三):主流的消息队列中间件有哪些?

消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。 当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka&#…

谷歌40人发表59页长文:为何真实场景中ML模型表现不好?

文 | 白鹡鸰编 | 夕小瑶大家好哇,我是上周那篇《NLP太卷了,我去研究蛋白质了》的漫画作者白鹡鸰~前不久,在卖萌屋NLP群里默默潜水的白鹡鸰被群友提到的一篇Google几天前放出的59页超长论文炸得飞了起来。来,大家来感受一下气势浩大…

圆形进度条以及百分率指示器 Scroller类的练习

转载时请注明出处,尊重他人的劳动成果,谢谢。 先附上效果图: 这个控件是动态加载到75%的,主要我忘了怎么做动态图,就先放一个静态图在这里表示表示。旁边这个没有没有喜欢的?有想知道的 我可以告诉答案。…

阿里P8架构师谈:从单体架构、到SOA、再到微服务的架构设计详解

本文涉及的内容以及知识点如下: 1、单体架构 2、单体架构的拆分 3、SOA与微服务的区别 4、微服务的优缺点 5、微服务的消息 6、服务集成 7、数据的去中心化 单体架构 Web应用程序发展的早期,大部分web工程是将所有的功能模块(service…

我拿乐谱训了个语言模型!

文 | 花椒最近在刷EMNLP论文的时候发现一篇非常有趣的论文《Learning Music Helps You Read: Using Transfer to Study Linguistic Structure in Language Models》,来自斯坦福大学NLP组。论文有趣的发现是让语言模型先在乐谱上进行训练,再在自然语言上训…

LeetCode 146. LRU缓存机制(哈希链表)

文章目录1. 题目信息2. 解题2.1 手动实现list2.2 使用内置list1. 题目信息 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。 获取数据 get(key) - 如果密钥 (key) 存在于缓…

微服务系列:服务注册与发现的实现原理、及实现优劣势比较

服务注册与发现的来源 首先,服务注册与发现是来自于微服务架构的产物。 在传统的服务架构中,服务的规模处于运维人员的可控范围内。当部署服务的多个节点时,一般使用静态配置的方式实现服务信息的设定。而在微服务应用中,服务实例…

EMNLP 2020论文分析:知识图谱增强语言模型或是未来的发展趋势!

文 | Michael Galkin源 | AI科技评论在EMNLP 2020的论文投递中,知识图谱的研究热度不减,并成为继续推动NLP发展的重要动力之一。在EMNLP 2020中,知识图谱领域有了哪些最新研究进展呢?作者从中选出了30篇文章,对未来2-3…

如何通过反射来解决AlertDialog标题由于字数过多显示不全的问题

转载前请标明出处:http://blog.csdn.net/sahadev_ 先上一下示例图: 这是默认状态下:这是通过反射后修改的结果: 在解决这个问题之前首先需要了解一下AlertDialog的基本构造,所以先从源码看起: 想要知道为什么显示不…

LeetCode 292. Nim 游戏

文章目录1. 题目信息2. 解题1. 题目信息 你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。 你们是聪明人,每一步都是最优解。 编写一个函数…

配送A/B评估体系建设实践

2019年5月6日,美团点评正式推出新品牌“美团配送”,发布了美团配送新愿景:“每天完成一亿次值得信赖的配送服务,成为不可或缺的生活基础设施。”现在,美团配送已经服务于全国400多万商家和4亿多用户,覆盖28…

ListView原理简单介绍(着重介绍getView被调用的一系列过程)

今天出去面试,被面试官问到一个问题,说是如果使用 LayoutInflate.inflate(int resource, ViewGroup root, boolean attachToRoot);这个方法与AbsListView的实现类结合使用的话,会出现什么问题,先看简单的使用过程: Ove…

一人之力,刷爆三路榜单!信息抽取竞赛夺冠经验分享

文 | JayLou娄杰在现如今的NLP竞赛中,信息抽取(IE)任务已占据半壁江山。来,让我们看看今年的一些IE竞赛都有啥:看到如此众多的IE竞赛,心动的JayJay抽空参加了CHIP2020(中国健康信息处理大会&…

pkuseg:一个多领域中文分词工具包

pkuseg简单易用,支持细分领域分词,有效提升了分词准确度。 目录 主要亮点编译和安装各类分词工具包的性能对比使用方式相关论文作者常见问题及解答主要亮点 pkuseg具有如下几个特点: 多领域分词。不同于以往的通用中文分词工具,此…