乐趣区

关于数据库:腾讯云原生数据库TDSQLC架构探索和实践

作为云原生技术先驱,腾讯云数据库内核团队致力于一直晋升产品的可用性、可靠性、性能和可扩展性,为用户提供更加极致的体验。为帮忙用户理解极致体验背地的关键技术点,本期带来腾讯云数据库专家工程师王鲁俊给大家分享的腾讯云原生数据库 TDSQL- C 的架构摸索和实际,内容次要分为四个局部:

本次分享次要分为四个局部:
第一局部,介绍腾讯云原生数据库 TDSQL-C 产品架构,包含产品的研发背景和架构次要个性;
第二局部,分享用户场景实际,针对线上实在的用户场景做一些剖析和针对性实际;
第三局部,分享零碎要害优化;
第四局部,分享产品将来演进。

点击此处观看残缺视频

TDSQL-C 产品架构

背景

腾讯云原生数据库最后采纳的是传统架构,也就是 MySQL 实例,或者说是采纳 Binlog 复制的主备形式的架构。但这种架构在现有的一些用户需要来看是有很多问题的。

比方 存储容量。传统架构实例的存储下限受限于本地磁盘下限,个别是几百 G,或者几个 T 的量级,做扩大的老本十分高而且麻烦。当用户数据十分多时,会做分库分表,应用现有的分库分表中间件或解决方案会带来一些分布式事务的问题。

做业务的同学晓得,分布式事务处理起来会比拟麻烦,波及如何应答故障,如何应答分布式事务产生的数据不统一等问题。用户在存储容量方面的需要是实例容量大于 100T,并且存储容量可能疾速通明的扩大。

其次是 可靠性 。传统架构基于 BinLog 复制,一般的异步或者半同步的复制形式可能会丢数据,同步的复制形式性能损失会比拟大。用户在可靠性方面的需要是 第一不能丢数据,即 RPO 等于 0;第二数据 是有多正本容灾 的,也就是要达到肯定水平的数据可靠性。

此外还有可用性,可用性对于用户来讲就是 服务有多长时间不可用 ,比方在传统架构产生一次 HA,或者宕机重启,这段时间服务都是不可用的。HA、复原工夫慢对用户来讲很难承受,传统架构 HA 或者正本的复原速度可能达到了分钟级。第二个问题是基于 BinLog 复制的时候,主备正本的提早比拟高,有些可能达到分钟级,甚至达到小时级。用户心愿可能疾速切换 HA,实现秒级复原,还包含回档性能,如果有正本,心愿正本的 提早可能比拟小,最好是秒级以下,甚至是毫秒级

最初是 可扩展性 。传统架构的扩展性是非常复杂的,基于 Binlog 创立只读正本也会非常复杂,要先把原始的数据给复制过去,而后搭建主备同步,只读正本能力开始工作,这个过程至多是分钟级甚至是小时级别的。对用户来讲,他们心愿当读需要有扩展性需要的时候,能够 实现秒级的读正本扩大

咱们针对这四个方面的用户需要,采纳了 存储计算拆散架构,这也是 TDSQL-C 所驳回的外围的架构想法。

简略来说,要解决存储容量和可靠性方面的问题,第一咱们会用 云存储,云存储之间是能够程度扩大的,实践上它的容量是有限的,而且对于每一份数据都有多副原本保障可靠性。数据扩散在云存储的各个节点上,在这个根底上能够做继续备份,并行回档等性能。

在可用性方面,数据放在云存储上之后,数据的分片是能够做 并行复原 的,回档也能够做 并行回档。物理复制的时延个别会比基于 Binlog 的逻辑复制更低一点。

最初在可扩展性方面,共享存储 的劣势更加显著,当新建一个只读正本的时候,数据不须要复制一份进去,因为数据是在云存储上作为共享数据存在的,只须要把数据共享,另外再构建增量的数据复制就能够了。

架构个性

下面这张图是 TDSQL-C 的整体架构,从这个架构中咱们能够看到,它整体上分为上一层的计算层和下一层的存储层。

计算层 有一个读写节点,能够提供读写申请,还有多个只读节点,能够提供读申请,也就是图里边的 Master 节点和 Slave 节点。当读写申请,尤其是写申请进来当前,Master 节点也就是读写节点产生数据的批改,而后它会把批改产生的 InnoDB 的 Redo Log 下传到整个存储层,同时把 Redo Log 散发到本人的 RO 节点。

存储层 负责管理数据,当产生的 Redo 日志发送到存储层之后,它能够负责 Redo 日志的回放,Segment 把它存储的页面对应的 redo 日志 apply 到本人的页面上来。整个存储层是架设在 COS 存储服务上。

TDSQL-C 的存储能够 主动扩容,最大反对超过 1PB 的容量,目前咱们的产品最大反对到 96CPU 和 768GiB 的规格。性能方面,只读大略能跑到一百万以上 QPS,写性能也能超过 40 万 QPS。

基于这种 共享存储 的架构,咱们能够做到秒级故障切换,包含秒级的快照备份和回档,并且因为存储层自身能够做弹性,计算层也能够做弹性,所以能够实现肯定水平的 Serverless。

此外,当须要扩大只读的时候,能够很容易的减少只读节点,TDSQL-C 当初最多能够挂 15 个只读节点,并且在读写节点和只读节点之间只有毫秒级的提早。因为整个工程是基于 MySQL 代码库演变过去的,所以是 百分之百兼容 MySQL 的

场景实际

接下来,我会介绍并剖析几个比拟典型的场景实际。

Serverless

上图形容的是一些业务预测将来一段时间的数据存储或者数据计算的需要是继续上涨的,但实际上可能实在的用户需要是图中灰色的曲线。为了做好服务,用户要提前买好服务库实例,比方图中红色的折线,一开始就要筹备好这种规格的数据库实例。

这种状况有一个害处,理论买的规格都是比实在需要偏大的,这就会造成存储资源或计算资源的节约。如果某些时刻有突发的流量进来,忽然对存储或者计算的资源要求十分高,就会呈现机器实例资源跟不上、规格太小等状况,这会对业务造成很大的影响。

咱们认为现实的状况应该是图中蓝色的曲线,这个曲线的整个资源容量跟实在业务需要的变化规律是一样的,并且总是比实在的需要略微多一点。这样就能 真正把资源充分利用起来,而且最大水平上降低成本开销

在一些实在的例子里,咱们发现有些业务是开发测试场景,业务真正上线之前,会做一些零碎的测试开发,这个过程对数据库的需要频率是非常低的。还有一些像 IoT、边缘计算、SaaS 平台,他们的负载变动有十分大的规律性,白天压力比拟大,然而早晨压力比拟小。

TDSQL-C 做到了智能极致的弹性,可能依据负载来疾速启停实例 。第二是 按需计费,用了多少花多少,不必不付费,能够做到按秒的计量,按小时的结算。

弹性扩容

另一个咱们在线上业务中发现的实际需要是弹性扩容。有些业务每天都能产生大量的数据,比方有的业务一天产生几百 G 的数据,并且这种业务对单库的容量要求很高,通常都是几十 T,甚至上百 T 的数据。

有些场景,像开发测试场景,开发完或者某一次测试完,数据库间接就删掉了,生命周期十分短。另外有些历史库场景,历史数据存储只是存储最近一段时间的,特地老的数据间接就删除了,删除了这些数据心愿空间立即回收,不要再产生存储老本了。

TDSQL-C 能够做到按需扩容,存储依据操作页面按需扩容,如果产生的数据比拟多就扩大进去,不须要事后布局好要做多少存储。第二点是主动回收,有一些闲暇空间,比方数据曾经删除了,这些数据理论不须要了,然而传统的 RDS 是逻辑删除的,这块可能还会持续产生费用,TDSQL-C 能够做到按理论的容量来计费

备份回档

很多场景对 备份回档 要求比拟高,比方金融行业,因为金融行业对 数据安全关注度 十分高,他们对备份的速度和备份的时效性都有很高的要求。还有像游戏业务,可能会波及到频繁的回档,所以对备份回档的速度要求也比拟高。

回档作为“后悔药”,对很多业务来讲都是很重要的一个性能,用户可能会产生一些误操作。

TDSQL-C 能够做到 继续备份,存储分片能够依据备份点进行并发的独立备份,同时能够做到设定全局的一致性备份点来进行备份。此外,TDSQL-C 也能够做到并行回档,每一个分片并行回档各自的数据的全量和增量的备份,并行回放本人的日志。还有 PITR,也就是能够疾速的复原到数据库的任意工夫点的数据的状态。

零碎要害优化

极速启停

第一个优化就是后面提到的,如何做到极速启停,也就是反对更好的 Serverless。

这边有个测试数据,第一个测试数据叫 停机工夫,指的是打算内的停机工夫,即被动停机。TDSQL-C 跟传统的 RDS 数据库比照,传统 RDS 数据库停机须要 26 秒,TDSQL-C 能够做到 3 秒内停机。

第二个是 启动工夫,就是停机之后从新把数据库实例拉起来,大略须要多少工夫可能复原起来,RDS 须要 48 秒,TDSQL-C 能够做到 4 秒就启动起来。

咱们剖析了一下,这 48 秒有 21 秒是在做 事务复原,也就是第三个柱状图,咱们对事务零碎的并行初始化、表锁复原做了一些优化,能够把复原工夫降到一秒。

第四个指标叫 性能复原工夫,这个指的是比方重启之前数据库的 QPS 大略跑到了 20 万 QPS,重启之后大略须要多长时间能力从新复原到 20 万 QPS。这对很多业务来说都是很重要的,是复原品质的问题。传统 RDS 在有些场景下须要 260 秒能力复原,然而用 TDSQL-C 3 秒就能复原了。

这里咱们做了一些优化,用的 独立 BP 的优化形式。Buffer Pool 跟数据库实例过程是解耦的,由这台机器上的另外一个过程来负责管理这块内存,当数据库实例重启之后,Buffer Pool 是能够持续用的,这种形式就防止了重启之后,整个 Buffer Pool 都是冷的,须要很长时间缓缓预热,省了这个过程,所以复原工夫会十分快。

二级缓存

另一个零碎要害优化是二级缓存。二级缓存是 TDSQL-C 在存储计算拆散架构下做的比拟翻新的优化,也是对架构的一个重要补充。

如此前所说,存储层是能够程度扩大的,这意味着数据量收缩了很多倍,可能几十倍、上百倍。数据量多了,然而计算层计算节点的 Buffer cache,也就是 InnoDB 的 Buffer Pool 的容量并没有太大的变动,这就意味着须要用以前雷同大小的 Buffer Pool 来服务更多的数据。

大家晓得 InnoDB 的 Buffer Pool 在肯定水平上承当了读缓存的作用,服务更多的数据,意味着读缓存的效率可能会降落。以前一些并不是 IO Bound 的场景,在这种数据量大了的场景下就变成 IO Bound 了,或者以前原本就是 IO Bound 的场景,IO Bound 更重大了,这样对性能影响还是比拟大的。

其次,传统 RDS 的 BufferPool 和本地磁盘空间的存储两头,是没有其余硬件存储设备的。然而在存储计算拆散架构下,Buffer Pool 可能跑得十分快,它的 IO 提早很低,但数据是寄存在远端的机器上的,咱们这边叫 Remote IO。须要通过网络拜访其余机器的 SSD,在这之间有至多两个档次的硬件存储设备,一个是 SSD,就是本机硬盘,另外一块是 Persistent Memory,就是长久化内存,这些是咱们能够利用起来的。咱们把这一类存储用作 secondary cache,通过这种形式可能无效的减缓 IO Bound 场景下 Buffer Pool 命中率低的问题,因为咱们能够缓存很多的热数据,可能减速数据的拜访。

通过测试能够看到,随着数据量的增大,整个性能晋升还是比拟显著的,在很多场景下性能能够晋升到百分之一百以上,达到一倍多

当然这个问题也有其余的解决方案,有些产品用的是程度扩大 DRAM,相似于咱们的 Buffer Pool,就是把 Buffer Pool 放在远端的机器上,通过更好的 RDMA 来拜访这部分内存,而且这个内存可能扩散在多台机器上,这种形式也能减缓 IO Bound 场景的一些开销。

但绝对来讲,我集体认为应用 Secondary cache 这种形式零碎的整体利用老本更低一点,因为毕竟内存的老本比 SSD 的老本高的多,尤其是非易失性内存,像 3D Xpoint,缓缓流行起来之后,价格是缓缓升高的。用二级缓存的形式,整体的实例老本可能降落十分多

极致伸缩

还有一个优化是极致伸缩,咱们把存储性能下放到存储层之后,存储层会有 存储池 这样一个概念。

有一些逻辑跟传统 RDS 形式是相似的,比方段治理还是以 1M 的 extent 为粒度来治理。也有些逻辑有很大的差别,比方咱们把存储空间的扩大,整个 offload 到存储层,整个空间都池化。当咱们发现某个 extent 外面的所有页面都回收了之后,变成了一个 Free Extent,就能够物理上真正的把它删除,而不只是标记为删除。通过这种形式真正删除之后,客户的存储老本就升高下来了,也就是可能实现按需计费的能力

极速备份回档

极速备份回档的实现蕴含两局部:备份、回档。

此前提到,咱们的数据是扩散到分布式存储组件上的,分布式存储蕴含很多的存储节点,而且它自身还有肯定的计算能力。当实例须要做备份的时候,每个存储节点都能够单独的去做备份,咱们叫 自治备份,它能够继续的做备份。当咱们须要全局统一的备份位点时,能够由计算节点来负责协调,通过一些非凡的命令,或者日志来告诉所有存储层的节点基于快照做一个对立的备份。

跟备份相同的一个操作是 回档,基于备份再把实例的数据恢复到某个工夫点,回档也是并行回档的,每个计算节点都能够独立的做本人的回放。

针对极速备份回档的测试数据看,1TB 的备份工夫,RDS 实例须要 61 分钟,TDSQL-C 只须要 21 分钟就够了。1TB 的回档复原工夫,RDS 须要 168 分钟之多,但 TDSQL-C 22 分钟就能够复原进去。

Instant DDL

还有一些优化是功能性优化,蕴含 Instant DDL 和并行构建索引。

Instant DDL 是 MySQL 8.0 新增的一个性能,它指的是在解决新增列,或批改列类型,或删除列 DDL 的时候,能够仅仅批改原数据就间接返回。

大略的原理是,比方这张表原来有三列,当初须要新增一列,变成四列,只须要在零碎表外面标记一下,这张表就从原来的三列变成了四列。之后再新写入的数据都是按四列写入的,原来的数据在磁盘上存的是三列的,新插入的数据会打上新格局数据的标记,原来的数据是没有标记的,当用户读取的时候,返回客户之前依据标记来决定。如果是旧数据,咱们就给它补一个新的列,个别补默认值 default value;如果是新列就间接返回,通过这种形式就做到了 O(1) 的 DDL,工夫十分短。

并行构建索引

接下来介绍下并行构建索引,比方 create index,或者 optimize table 的时候,都会波及到一些表的重建。

RDS 构建索引的时候,尤其是 8.0 的绝对早一点的版本,都是单线程构建的。构建过程是先扫描所有的主表数据,扫描之后,依据扫描到的每一行主表数据,再依据索引信息,生成对应的索引行,这些索引行生成后存储到临时文件外面。

第二步是对这个临时文件依照索引行的索引键进行排序,个别是 mergesort,实现之后把它导入到一个空的 Btree 里,这样就实现了整个索引的构建。咱们针对这块做了并行化优化,扫描主表、外排,还有把数据导入到 Btree,这三个过程都是能够并行化的。
在第一个阶段,咱们基于 InnoDB 8.0 的 parallel DDL 做了并行扫描。第二步的 mergesort 咱们也做了基于采样的并行化,通过这种形式来晋升并行度。第三步构建 Btree 的时候,也是能够并行化的,比方产生了八万行的索引行,如果八并发,每一个并发线程负责一万行数据的构建。最初再把造成的八个子 Btree 合并成一个大的 Btree,再去压缩层高等等。咱们测下来 很多场景下能晋升到两倍以上,还有很多场景能够进步的更多

将来演进

第一个咱们在摸索的演进叫 Global Database。

如上图所示,右边有一个 Primary 实例,这个实例读写节点产生了 Redo log,Redo log 须要散发到存储层,咱们当初新增了 Log Store 模块,它负责接管和散发日志,通过这种形式,Log Store 肯定水平上能够晋升日志的响应速度和整体 Redo log 的 IO 吞吐,进一步晋升写性能

另外一个很重要的点是 Primary 实例跟右侧 Standby 实例能够通过各自的 Log Store 来建设数据复制的链路。通过这种形式,相当于扩大出了一个只读节点,实现读扩大,而且是 跨 Region 的读 ,因为 Standby 能够部署在另外一个 Region 上。另外咱们通过这种形式实现了 跨 Region 容灾,这对于很多金融业务来讲都是刚需

另一个咱们在摸索的演进是计算下推。

依据咱们的架构,存储和计算是离开的,计算在下面,存储在上面,存储不只有存储能力,还领有肯定的计算能力,像方才提到的备份复原,每个节点能够独立继续的做备份,就是利用存储层计算能力的一个例子。

除此之外还有很多业务逻辑也能够通过这种形式把存储层的计算资源利用起来,第一个是 页面内计算下推。比方当初要做一个有条件的扫描,扫描到了某个页面,这个页面可能有一百行数据,满足条件的有五条,能够把条件下推到存储层,间接放在存储层做过滤,只把这五条数据返回给计算层就能够了,这就防止了把这一百行全副读到计算层,在计算层再做计算,缩小了两头网络带宽的耗费。

第二个是 Undo 页面间的计算下推,咱们 InnoDB 是反对 MVCC 即多版本的,举个例子,咱们当初启动一个只读,这个读事务快照绝对比拟老,比方读一小时之前的,当我当初去读的时候,发现某一行数据太新了,不是我想要的那个数据,须要找到以前的版本。

这个过程在 InnoDB 外面,须要找到这一行对应的 Undo 页面,把它的前镜像找进去,要读的是 Undo 页面记录的前镜像,这个过程如果放在计算节点做,须要把原始的页面数据加载到计算节点,而后依据读快照把 Undo 页面找进去,再把 Undo 页面利用到数据页面上,产生一个旧版本的数据。这整个过程都能够在存储层来做,咱们当初也是把这个下沉下来的。

还有一个下推叫 写下推。比方我就改某个页面 Header 局部的前几个字节,或者 Page Header 的某个字段,这种状况很多是盲写的,不须要读出来,间接能够更新,这种状况也是能够下推的。

计算下推在存储计算拆散的架构下是很天然的一个事件,方才讲到了存储计算拆散,它的存储层带有肯定的计算能力,大量的计算实际上都是能够下沉到存储层的,哪些计算能够下推并没有很显著的边界。我集体感觉除了事务之外,大部分计算型的都能够下推到存储层,甚至能够把存储层的一些计算资源当成纯正的计算资源,不关怀它是不是存数据。

退出移动版