阿里数据库中间件TDDL原理

1)单一数据库无法满足性能需求

随着业务的发展,数据量急剧增大,使用单库单表时,数据库压力过大,因此通过分库分表,读写分离的方式,减轻数据库的压力。

2)系统容灾

使用单机数据库时,如果数据库宕机,则无法对外提供服务,因此产生了主备数据库的方案,当主库宕机后,会自动切换到备库,不影响对外的服务。

3)运维管理

直接连接单机数据库时,无法动态的切换数据源,使用TDDL中间件,可以动态的切换数据源。

tddl是JDBC或者持久框架层与底层JDBC驱动交互的桥梁,或者也可以称之为中转站

TDDL分为三层

Matrix 层、Group层, Atom 层

Matrix 分库分表。包括SQL解释、优化和执行等;

Group 层是经过读写分离和主备切换才会出现最底层。

至Atom 层,它面对的是实实在在的每一个数据库,更多的工作在与对数据库的连接管理,比如说当数据库的 IP 地址发生改变时,Atom 层要动态感知,以免连接找不到地址。


3)Matrix 层
分库分表带来的最直接的影响是数据访问的路由。

路由算法有以下几种:

a)固定哈希算法

固定哈希就再简单不过了,就是根据某个字段(如整形的 id 或者字符串的 hashcode)对分库的数量或者分表的数量进行取模,根据余数路由到对应的位置。下面图中的例子,数据库垂直拆分成 4 个,其中有一张表水平拆分成两张,利用固定哈希算法进行路由的过程如下:

b)一致性哈希算法

固定哈希算法足够简单实用,基本能保证数据均匀分布,它也是 TDDL 的默认路由算法,但是在数据库扩容的时候,固定哈希算法带来的数据迁移成本也是不得不考虑的。依然是上面的例子,数据库拆分成 4 个,当需要增加数据库的时候,假设变成 5 个,由于取模的结果发生变化,原来数据库中的绝大部分数据都要进行迁移,只有在数据库倍增的时候,数据迁移量才是最少的,但也高达 50%,而且倍增的成本比较高。

c)虚拟节点

一致性哈希已经可以解决大部分需求了,但是对于数据集中在热点的情况,一致性哈希同样面临比较大的挑战。比如说,上图的 node2 与 node4 之间集中了整个环中的大部分数据,当加入 node5 之后,其实起到的效果比较有限,因为还是要有大量的数据进行迁移。引入虚拟节点之后,情况就不一样了,所谓虚拟节点,它就是物理节点的映射,一个物理节点可以复制出多个虚拟节点,尽可能的让它均匀分布在环上,那么即使数据再集中,其实也会存储在不同的节点上,很好地起到了负载均衡的作用。

读写分离最大的问题是数据复制,通常有两种复制场景,一种是镜像复制,即主库和从库的数据结构是一模一样的,通常根据主库上的日志变化,在从库中执行相同的操作;另外一种是非对称复制,意思就是主库与备库是以不同的方式分库的,它们的结构虽然相同,但是主备库中存储的记录是不相同的,主要目的是查询条件不同时,把请求分发到更加适合的库去操作。举个例子,对于订单数据库,买家会根据自己的 ID 去查自己的交易记录,所以主库可以用买家 ID 分库,保证单个买家的记录在同一个数据库中;但是卖家如果想看交易记录的话可能就得从多个库中进行查询,这时候可以利用卖家 ID 进行分库作为备库,这样一来主备库的复制就不能简单的镜像复制了,在进行复制操作之前还需要进行路由。

3)Atom层

Atom 模块真正和物理数据库交互,提供数据库配置动态修改能力。

改层负责动态创建,添加,减少数据源。管理着底层的数据库IP,连接等信息;底层对物理数据库做了代理,对单库的JDBC做了一层封装,执行底层单库的SQL;线程数、执行次数等状态的统计等。

3、执行流程

1)执行流程

TDDL的工作流程类似上图,client发送一条SQL的执行语句,会优先传递给Matrix层。由Martix 解释 SQL语句,优化,并根据查询条件路由到各个group,转发sql进行查询,各个group根据权重选择其中一个Atom进行查询,各个Atom再将结果返回给Matrix,Matrix将结果合并返回给client。具体的工作流程的可以拆分成如下图:

Matrix层会先执行以下四个过程:

a)Sql的解析。首先将Sql语句解析成一颗抽象语法树(Abstract Syntax Tree),解析成我们比较好处理的一个结构

b)规则的匹配与计算。基于上一步创建的语法树查找匹配的规则,再根据规则去确定分库分表的结果。这里有一个概念就是规则,规则这里可以简单的看做就是定义数据库怎么进行分库分表,要分成几张库几张表,库名和表名的命名是怎么样的。规则的匹配就是根据SQL的语句确定,具体查询的子表是哪几张。

c)表名替换。对于开发人员来说,它查询的表直接就是select * from A.B limit 10(A为数据库名,B为数据表名)。但底层其实会把这些表名替换成类似select * from A_000.B_001,select * from A_000.B_002,select * from A_001.TABLE_001这样的形式。表名替换就是把总表的名称替换为这些子表的名字。

d)Sql的转发。将上一步生成的各个sql语句转发到对应的Group进行执行。这里如上图,我查询的条件是where id = 2 or 3。那么转发给Group0的查询为where id=3,转发给group1的查询为where id =2 。查询的条件也会发生一定修改。

这样四个步骤可以在Matrix层就实现了分库分表的功能,对原始的Sql进行分解,将原本单库单表的查询语句,底层转发到多库多表并行的进行执行,提高了数据库读写的性能。

接下来由Group执行两个过程:

e)根据权重选择AtomDs。通常会在主节点和副节点上读取数据,只在主节点上写入数据。

f)具有重试的策略地在AtomDs上执行SQL。这个可以防止单个的AtomDs发生故障,那么会进入读重试,以确保尽可能多的数据访问可以在正常数据库中访问。

然后是Atom层执行两个过程:

g)读写数控制、线程并发数控制 。同时会统计线程数、执行次数等信息。

h)执行sql,返回结果集。Atom底层利用druid进行连接池的管理,具体查询还是对JDBC做了一定封装。执行完Sql后对将结果返回给Matrix。

最后Matrix执行最后一个过程:

i)结果集合并。Matrix将Atom层的返回的各个结果集进行合并Merge,返回给Client端。

2)路由与扩容(固定哈希算法为例)

a)数据库水平拆分路由

f(pavarotti17)= hash(pavarotti17) % 1024,然后根据该值找对应的DB,

b)扩容

固定哈希算法是常用的算法,其扩容一般推荐每次以2倍的形式扩容,这样只需要迁移一半的数据。

4、Senquence全局唯一id标识生成原理

1)背景

目前基于tddl进行分库分表后,原本一个数据库上的自增id的结果,在分库分表下并不是全局唯一的。所以,分库分表后需要有一种技术可以生成全局的唯一id。

2)工作原理

a)主要职责

生成全局唯一的id;保持高性能;保持高可用。

b)目前常见的几种全局ID的思路

方案一

oracle sequence:基于第三方oracle的SEQ.NEXTVAL来获取一个ID

优势:简单可用。

缺点:需要依赖第三方oracle数据库。

方案二

mysql id区间隔离:不同分库设置不同的起始值和步长,比如2台mysql,就可以设置一台只生成奇数,另一台生成偶数. 或者1台用0~10亿,另一台用10~20亿.。

优势:利用mysql自增id 。

缺点:运维成本比较高,数据扩容时需要重新设置步长。

方案三

基于数据库更新+内存分配:在数据库中维护一个ID,获取下一个ID时,会对数据库进行ID=ID+100 WHERE ID=XX,拿到100个ID后,在内存中进行分配 。

优势:简单高效。

缺点:无法保证自增顺序。

目前tddl sequence也是选择的方案3进行实现,但会有几点额外的要求:

a. 只要生成id的数据库不全部挂掉,均可以顺畅提供服务;

b. 生成id的数据库数量不定,按照应用对容灾的需求指定不同机架不同机房的数据库; (比如需要考虑单元化多机房的id生成)

c. 支持生成id的数据库hang住快速略过和恢复自动加入 。

总结一下:生成id的数据库可以是多机,其中的一个或者多个数据库挂了,不能影响id获取,保证严格高可用。

目前我们针对多机的id生成方案: 每个数据库只拿自己的那一段id,如下图左:

sample_group_0-sample_group_3是我们生成全局唯一id的4个数据库,那么每个数据库对于同一个id有一个起始值,比如间隔是1000。

应用真正启动的时候,可能某一台机器上去取id,随机取到了sample_group_1,那么这台机器上的应用会拿到1000-1999这一千个id(批量取,这个也就保证了应用端取id性能),而这个时候4个数据库上id起始值会变成右图所示,你也许注意到了,下次从sample_group_1上取得的id就变成了4000-4999。那么也就是这样,完全避免了多机上取id的重复。比如sample_group_1他会永远只会取到1000-1999,4000-4999,8000-8999,12000-12999…其他数据库也一样,相互不会重叠。

这种产生全局唯一id的方式相当有效,保证基本的全局唯一特性和高性能的同时,可以对生成id的数据库分机架分机房部署达到容灾的目的。

3)配置

?

1

2

3

4

5、tddl适用场景

1)高并发实时交易场景

面向客户端的电商、金融、O2O、零售等行业普遍存在用户基数大、营销活动频繁、核心交易系统数据库响应日益变慢的问题,制约业务发展。 TDDL 提供线性水平扩展能力,能够实时提升数据库处理能力,提高访问效率,峰值 TPS 达150万+,轻松应对高并发的实时交易场景。

2)海量数据存储访问场景

企业客户随着业务的快速发展,业务数据增长迅猛,会产生超过单机数据库存储能力极限的数据,造成数据库容量瓶颈,限制业务发展。 TDDL 可以线性扩展存储空间,提供 PB 级存储能力,可广泛应用于工业制造、智能家居、车联网等超大规模数据存储访问场景。

3)高性价比数据库解决方案

初创型企业初期发展阶段技术积累相对比较薄弱,资金投入有限,业务发展快,数据库的稳定性风险高。TDDL 继承了阿里巴巴多年的分布式数据库技术积累,能够提供简单易用的数据库运维系统,降低企业的技术运维成本,赋予企业强大的数据库支撑能力。

当业务数据和访问量增加到一定量时,如政务机构、大型企业、银行等行业为了支持大规模数据存储和高并发数据库访问,传统方案需要强依赖小型机和高端存储等高成本的商业解决方案,以达到扩展服务能力的目的。TDDL 能够利用普通服务器提供阿里巴巴双十一同等处理能力的高性价比国产数据库解决方案。

4)数据存储平滑扩容

当应用单机存储(MySQL)出现容量或性能瓶颈时,TDDL 提供在线数据扩容功能(该功能需要结合阿里其它内部中间件使用)。传统数据库容量扩展往往意味着服务中断,很难做到业务无感知或者少感知。


https://www.2cto.com/database/201806/752199.html

你可能感兴趣的:(阿里数据库中间件TDDL原理)