当业务波及到分布式时就开启了 TDSQL 的另外一种状态。接下来咱们就聊一聊 分布式 TDSQL 跟单节点的 TDSQL 有什么不同,以及这种分布式架构下又是如何实现一系列的保障,同时如何做到对业务通明、对业务无感知。
分表,当在单机模式下,用户看到的一张逻辑表,其实也是一张物理表,存储在一个物理节点(物理机)上。在分布式状态下,用户看到的逻辑表的理论物理存储可能是被打散散布到不同的物理节点上。所以 TDSQL 分表的指标,心愿做到对业务齐全通明,比方业务只看到一个残缺的逻辑表,他并不知道这些表其实曾经被 TDSQL 平均拆分到各个物理节点上。比方:之前可能数据都在一台机器上,当初这些数据均匀散布在了 5 台机器上,但用户却丝毫没有发觉,这是 TDSQL 要实现的一个指标——在用户看来是齐全的一张逻辑表,实际上它是在后盾打散了的。
这个表在后盾如何去打散,如何去散布呢?咱们心愿对用户做到通明,做到屏蔽,让他不关怀数据分布的细节。怎么将这个数据分布和打散呢?这就引出了一个概念:shardkey——是 TDSQL 的分片关键字,也就是说 TDSQL 会依据 shardkey 字段将这个数据去扩散。
咱们认为,shardkey 是一个很天然的字段,天然地通过一个字段去将数据打散。举个例子,腾讯外部咱们喜爱用 QQ 号作为一个 shardkey,通过 QQ 号主动把数据打散,或者微信号;而一些银行类的客户,更喜爱用一些客户号、身份证号以及银行卡号,作为 shardkey。也就是说通过一个字段自然而然把这个数据分散开来。咱们认为引入 shardkey 后并不会减少额定的工作,因为首先用户是最理解本人得数据的,晓得本人的数据依照什么字段均匀分布最佳,同时给用户自主抉择分片关键字的权力,有助于从全局角度实现分布式数据库的全局性能最佳。
所以这里可能有些人会想,是不是主键是最好的或者尽可能地扩散?没错,的确是这样的,作为 TDSQL 的分片关键字越扩散越好,要求是主键或者是惟一索引的一部分。确定了这个分片关键字后,TDSQL 就能够依据这个分片关键字将数据平均分散开来。比方这张图,咱们依照一个字段做了分片之后,将 1 万条数据均匀分布在了四个节点上。
既然咱们理解了 shardkey 是一个分片关键字,那怎么去应用呢?这里咱们就聊聊如何去应用。
举个例子,咱们创立了 TB1 这个表,这里有若干个字段,比如说 ID,从这个名字上来看就应该晓得它是一个不惟一的,或者能够说是一个比拟扩散的值。咱们看到这里,以“ID”作为调配关键字,这样六条数据就平均扩散到了两个分片上。当然,数据平均扩散之后,咱们要求 SQL 在发往这边的都须要带上 shardkey,也就是说发到这里之后能够依据对应的 shardkey 发往对应的分片。
如果不带这个 shardkey 的话,它不晓得发给哪个分片,就发给了所有分片。所以强调通过这样的改善,咱们要求尽可能 SQL 要带上 shardkey。带上 shardkey 的话,就实现了 SQL 的路由散发到对应的分片。
讲完数据分片,咱们再看一下数据的拆分。
程度拆分
对于分布式来说,可能最后咱们所有的数据都在一个节点上。当一个节点呈现了性能瓶颈,须要将数据拆分,这时对咱们 TDSQL 来说非常简单,在界面上的一个按纽:即一键扩容,它就能够将这个数据主动拆分。拆分的过程也比拟容易了解,其实就是一个数据的拷贝和搬迁过程,因为数据自身是能够依照一半一半这样的划分的。
比方最先是这么一份数据,咱们须要拆成两份,须要把它的下半局部数据拷到另外一个节点上。这个原理也比较简单,就是一个数据的拷贝,这里强调的是在拷贝的过程中,其实业务是不受任何影响的。最终业务只会最终有一个秒级解冻。
为什么叫秒级解冻?因为,最初一步,数据分布到两个节点上波及到一个路由信息变更,比方原来的路由信息要发到这个分片,当初改了之后须要依照划分,上半局部要发给一个分片,下半局部发给另一个分片。咱们在改路由的这个过程中,心愿这个数据是没有写入绝对静止的。
当然改路由也是毫秒级别实现,所以数据拆分时,真正最初对业务的影响只有不到 1s,并且只有在最初改路由的解冻阶段才会触发。
讲完数据拆分,咱们开始切入分布式外面最难解决的这个问题,分布式事务。
强壮、牢靠的分布式事务
单节点的事务是很好解决的,然而在分布式场景下想解决分布式事务还是存在肯定的困难性,它须要思考各种各样简单的场景。
其实分布式事务实现不难,但首要是保障它的健壮性和可靠性,能应答各种各样的简单场景。比如说波及到分布式事务的时候,有主备切换、节点宕机……在各种容灾的测试环境下,如何保证数据总帐是平的,不会多一分钱也不会少一分钱,这是分布式事务须要思考的。
TDSQL 分布式事务基于拆的规范两阶段提交实现,这也是业内比拟通用的办法。咱们看到 SQL 引擎作为分布式事务的发起者,联结各个资源节点共同完成分布式事务的解决。
分布式事务也是依据 shardkey 来判断,具体来说,对于 SQL 引擎读发动一个事务,比方第一条 SQL 是改用户 ID 为 A 的用户信息表。第二条 SQL 是插入一个用户 ID 为 A 的流水表,这两张表都以用户 ID 作为 shardkey。咱们发现这两条 SQL 都是发往一个分片,尽管是一个开启的事务,然而发现它并没有走分布式事务,它理论还是限度在单个分片外面走了一个单节点的事务。当然如果波及到转帐:比方从 A 帐户转到 B 帐户,正好 A 帐户在第一个分片,B 帐户是第二个分片,这样就波及到一个分布式事务,须要 SQL 引擎实现整个分布式事务处理。
分布式事务是一个去中心化的设计,无论是 SQL 引擎还是后端的数据节点,其实都是具备高可用的同时反对线性扩大的设计。分布式事务比较复杂,独自讲的话可能能讲一门课,这外面波及的内容十分多,比方两级段提交过程中有哪些异样场景,失败怎么解决,超时怎么解决,怎么样保障事务最终的一致性等等。这里不再深刻,心愿有机会能独自给大家分享这块内容。
所以,这里只对分布式事务做一个总结,咱们不再去探讨它的细节:
首先是基于两阶段提交,咱们在 MySQL 原生 XA 事务的根底上做了大量的优化和 BUG 修复。比如说原生的 XA 在主备切换时会产生数据不统一和失落,TDSQL 在这个根底上做了大量的修复,让 XA 事务可能保证数据一致性。
第二个是强劲的性能。起初咱们引进原生分布式事务的时候,分布式事务的性能还达不到单节点的一半。当然通过一系列的优化调优,最初咱们的性能损耗是 25%,也就是说它能达到单节点 75% 的性能。
第三个是对业务通明,因为对业务来说其实基本无需关怀到底是分布式还是非分布式,仅须要依照失常业务开启一个事务应用即可。
第四个是齐备的异样容错。分布式事务是否强壮也须要思考容错性的能力。
第五个是全局的锁检测。对于分布式环境下锁检测也是不可或缺的。TDSQL 提供全局视角的分布式死锁检测,可清晰查看多个分布式事务之间的锁期待关系。
第六点是齐全去中心化。无论是 SQL 引擎还是数据节点,都是反对高可用并且可能线性扩大。
以上是 TDSQL 分布式事务的总结。如果说用户要求放弃跟 MySQL 的高度兼容性,那可能 Noshard 版 TDSQL 更适宜。然而如果对于用户来说,单节点曾经达到资源的瓶颈,没有方法在单节点下做数据重散布或者扩容,那必须抉择 Shard 模式。然而在 Shard 模式下,咱们对 SQL 有肯定的束缚和限度,前面会有专门的一门课去讲分布式 TDSQL 对 SQL 是如何束缚的。
咱们看到无论是 Noshard 还是 Shard,都具备高可用、数据强统一、主动容灾的能力。
同时 TDSQL 也反对 Noshard 到 Shard 的迁徙,可能晚期咱们布局的 Noshard 还能够承载业务压力,然而随着业务的突增曾经撑不住了,这个时候须要全副迁到 Shard,那么 TDSQL 也有欠缺的工具帮忙用户疾速进行数据迁徙。