项目中一直在用着TDDL,但除了接入时简单了解了下他的用法和原理外,也没有过多的深究其背后的实现,毕竟在阿里内部用到的中间件太多,每一个都深入的学习需要的周期太长,再者项目中数据库层也没有用到分布式,没有了业务上的驱动,动力就更显不足。正是因为自己的一知半解的状态,所以当同行的朋友问起TDDL的分库分表原理时我也就没法清晰的回应,鉴于此,今天特地查找资料,对TDDL的架构和原理做个总结,既是对自我知识储备的填充,也希望能帮助有需要的同行朋友理解tddl。
一、分布式数据库的演化
Tddl是一个分布式数据库中间件,主要是为了解决分布式数据库产生的相关问题,因此在学习tddl之前我们先了解一下分布式数据库的演化历程,所谓磨刀不误砍柴工,知其然亦要知其所以然,分布式数据库与数据库中间件息息相关,了解学习是很有必要的。整个分布式数据库的演化过程如下:
1、单库单表
通常刚开始的时候,应用的数据比较少,也不会很复杂,所以应用只有一个数据库,数据库中的业务表是一张对应业务的完整的表,这也是我们刚开始接触数据库时的数据库形态。
2、读写分离
随着业务的发展,数据量与数据访问量不断增长,很多时候应用的主要业务是读多写少的,比如说一些新闻网站,运营在后台上传了一堆新闻之后,所有的用户都会去读取这些新闻资讯,因此数据库面临的读压力远大于写压力,那么这时候在原来数据库 Master 的基础上增加一个备用数据库 Slave,备库和主库存储着相同的数据,但只提供读服务,不提供写服务。以后的写操作以及事务中的读操作就走主库,其它读操作就走备库,这就是所谓的读写分离。
读写分离会直接带来两个问题:
1)数据复制问题
因为最新写入的数据只会存储在主库中,之后想要在备库中读取到新数据就必须要从主库复制过来,这会带来一定的延迟,造成短期的数据不一致性。但这个问题应该也没有什么特别好的办法,主要依赖于数据库提供的数据复制机制,常用的是根据数据库日志 binary-log 实现数据复制。
2)数据源选择问题
读写分离之后我们都知道写要找主库,读要找备库,但是程序不知道,所以我们在程序中应该根据 SQL 来判断出是读操作还是写操作,进而正确选择要访问的数据库。
3、垂直分库
数据量与访问量继续上升时,主备库的压力都在变大,这时候可以根据业务特点考虑将数据库垂直拆分,即把数据库中不同的业务单元的数据划分到不同的数据库里面。比如说,还是新闻网站,注册用户的信息与新闻是没有多大关系的,数据库访问压力大时可以尝试把用户信息相关的表放在一个数据库,新闻相关的表放在一个数据库中,这样大大减小了数据库的访问压力。
垂直分库会带来以下问题:
1)ACID 被打破
数据分到不同的数据库之后,原来的事务操作将会受很大影响,比如说注册账户的时候需要在用户表和用户信息表中插入一条数据,单机数据库利用事务可以很好地完成这个任务,但是多机将会变得比较麻烦。以下两点也是因为数据库在不同的机子上而导致简单的操作变得复杂。
2)Join 操作困难
3)外键约束受影响
4、水平分表
经过长时间积累,特别对于 ugc 的业务,数据量会达到惊人的地步,每张表存放着大量的数据,任何 CRUD 都变成了一次极其消耗性能的操作,这个时候就会考虑水平分表,把一张表内大量的数据拆分成多张子表,比如说原来一张表中存放 50000 条数据,水平分成 5 张表之后,每张表只要存放 10000 条数据。这种结构可以比较容易的存储和维护海量数据。
水平分表会在垂直分库的基础上带来更多的影响:
1)自增主键会有影响
这个影响很明显,分表中如果使用的是自增主键的话,那么就不能产生唯一的 ID 了,因为逻辑上来说多个分表其实都属于一张表,自增主键无法标识每一条数据。
2)有些单表查询会变成多表
比如说 count 操作,原来是一张表的问题,现在要从多张分表中共同查询才能得到结果。
二、TDDL介绍
1、产生背景
由一中可以看出,数据库从单机走向分布式将会面临很多很多的问题,分布式数据库中间件就是为了解决这些问题而生的。Tddl作为开源分布式数据库中间件之一,由阿里研发,其出现解决了以上分布式数据库需求带来的问题,总结起来如下:
1)单一数据库无法满足性能需求
随着业务的发展,数据量急剧增大,使用单库单表时,数据库压力过大,因此通过分库分表,读写分离的方式,