开发者学堂课程【高校精品课-西安交通大学-数据库理论与技术:阿里工程师讲座】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/12/detail/15865
阿里工程师讲座(二)
内容介绍:
一. 传统数据库架构和云的本质
二. 云原生数据库
三. 下一代云原生数据库
二.云原生数据库
所以详细来介绍一下这个计算存储分离的原生数据库的架构。这个架构最早是 Amazon 提出的,在2014年他发了一篇文章介绍了它的云原生数据库 Aurora 这个架构。Amazon 毕竟是当年的强者,所以现在对于市场来说也是当之无愧。阿里是17年推出了第一款云原生数据库 polarDB,架构就是像下边这样,也是存储质量分离。如下所示:
待会介绍相对于 Aurora 来说的一些优势点,后推出肯定是有一些后发优势的,但是一定程度上就是云原生数据库这块的推出,也能看出各个企业的数据库研发这块的功底,后面会介绍到,因为阿里在数据库这块有多年的研发经验,是一直是做这项交易系统的,对数据库的依赖是非常重的。所以早年的时候就是 LE 时代就有大量的数据库的研发以及相关的人员,相关的同学,所以这块积累会比较深,这个后面会介绍到。
所以云原生数据库现在逐渐已经成为各个互联网厂商的主力数据库了,因为头部的这几家,Amazon,阿里,腾讯,华为,国内的几家都已经陆续推出来了,当然也有先后。这里简单插入一下阿里数据库的一个例子,因为现在2010年的数据2020年的数据,2020年阿里基本上, Gartner 是美国一个比较权威的评级机构,基本上都差不多。阿里巴巴目前是在领导的象限,因为是在18年第一个进入这个象限的,这几年发展又比较快,已经跟一些头部厂商,因为现在是全球第三,所以是头部厂商一起是领导者相见。数据库产品也比较多,整体积累会深一些。
17年是国内第一个推出云原生数据库的,整个架构就是1写16读,最大100TB,相对于 Aurora 来说最大的一个contribution,就是采用了软硬件一体化的设计。因为在17年的像新的硬件,包括 IDV,就是高性能的网络就彻底颠覆了整个网络通信的招务方式跟一个性能,所以在那时候包括 optane 这种新的存储硬件,那时就在架构上做了眼镜。Aurora 可能那时候觉得贷款比较高,所以它的架构设计是偏向于节约成本,那么阿里完全可以发挥新硬件的优势,主要是做软件结合这块的优势,这块是阿里率先提出的,第二个特点是对于一致性协议也做了很多的优化,来保证共享存储层的性能以及在 feover 时的一个性能表现。
这是阿里巴巴数据库的整个眼镜过程,如下图:
阿里是有蛮多的历史积累的,包括早年的去 IOE 时代,最早淘宝是最大的用户,后来用户量特别大,所以需要把它清除掉,因为这个成本实在是太高了。所以是第一次 把 myscale 真的放到大规模的商业系统里面,这需要对myscale做很多的改造。所以推出了开源的分子就是阿里 scale 时代。接着因为这些人的存在,所以其实在15.16六年时就开始做云原生这块的演进了,17年是推出产品。
这个是阿里云的大图来简单介绍一下,左边就是整个阿里云的体系,这个体系是很强的,是在线交易的核心部分。
再来介绍 polarDB 的几个创新点,刚才也提到一个是共享存储,一个是软件结合,另外一个是存储层的一些一致性的优化。那这里会提一下,是因为共享存储,存储计算分离,那么要把存储层做的性能足够的好,因为存储计算分离以后带来的通信的 overhear 肯定是比较大的,所以它会对性能有所下降。因为可以看到写本地盘跟写一个远程的分布式稳健系统,那肯定是会变慢的,所以技术上最大的挑战就是怎么把分离以后的性能保持好,那就结合这个软件,用RDMA 来做计算层跟存储层之间的通信。
因为 RDMA 是一个 Bypass cpu 的,其实在数据传输时是不需要 cpu 参与的,因为它的网卡可以直接做数据传输,它既然能 bypass cpu,肯定是能摆 pass os 的,它的 os 只是用来做控制信道的传输,所以在整个通信架构里面,就是一个数据如果要写到远程的盘,整个过程都是没有 cpu 参与的,也没有大量的这种数据拷贝,都是交给硬件来实现的,在存储层也是交给SPTK这种。所以整个链路的时间可以做到非常短,就是几十 u 秒 US 这个级别,基本跟本地盘还是在一个数量级,而不是通过传统的ipc的网络通信。那这种肯定就到毫秒级了,这个性能就很难介绍了。
第二个在共享存储层,因为共享存储层以后它不是像单机那样告诉磁盘坏了,可以作 feover,如果任意一个磁盘坏了就像 read 一样,必须要把整个分布式存储还是能继续运行。所以这里就需要有一些分布式一致性协议来保证存储层的多个冗于分片的数据,比较常用的就是 raft 这种分布式协议,在工业中用的比较多。但 raft 本身是有问题的,也不能说有问题,也就是它的性能是有缺陷的,因为它是一个串型的协议,那一个串型的协议在流量特别大时会造成拥堵,拥堵以后它就会有延迟的矛刺。
那么阿里 d 在这块是有比较大的贡献,提出了一个并行的 parallel Raft 协议,这个协议针对于共享存储在Raft上做了比较多的优化,就可以让原来串行的ratf协议并行起来。这个工作是发表在 VLDB 2018上的。VLDB 是现在数据库这块的一个顶级会议,三大顶级会议之一,SIGMOD,ICDE 跟 VLDB。如果后面读博士就会深有感触。
Raft 这块主要做了什么?主要是做了两点,一个点是 Out -of-Order ACK,就是原来串型的结合存储层的这块的协议,全新设计了一个新的协议,它就可以乱续的去提交原来需要串型的数据,继续保证整个协议的正确性。这个detail后面有时间可以蹲下论文。第二个就是 Fast Catchup 如果出现任意一个节点,比如一年故障,做的还是三个副本,那feel 其他部分怎么去快速 takeover 继续提供服务,这个也是一个比较大的亮点,也是在论文上强调的。
所以基于这些技术点,一个是目联合另外一个是协议上的创新,所以整个共享存储层的性能是做的比较好的,导致整个系统不单是性能没有下降,而且有比较大的提升。因为共享内存以后它的带宽会变得比较大,因为是可以跟下面的多个 server 进行通信,所以带宽就变得更大,对数据库的性能是不但没有下降还提升。那么数据库这边除了共享存储以外,还有很大的挑战,就是上面的计算节点。
刚才也提到了,这幅图上可以看到:
下面这个存储是存储层,那么存储计算分离本身性能的下降,可以通过这个文链结合以及协议的优化来保证。那另外一块的还可以通过共享同一份存储的情况下,去扩展更多的只读节点。上面的架构里面提到一份共享存储下面,不单是有一个计算节点,就是一个节点是做读写节点,它可以读写数据还有其他一些节点是不可以做读的。它们是跟读写节点共享同一份数据,但是它可以读到最新的数据,再把读的这个部分提取出来。
因为数据库里面大部分的流量还是读的,这样就可以扩展这个读的能力,而且又是共享同一数据,所以在共享存储,计算存储分离这个架构下只读节点的作用是非常大的。那么在扩展只读节点时,也是有很多挑战,这个是原来传统数据库架构没有的一个问题。只读节点 read write node ,read only node,它是要分享这个内存状态的,但它是又是分享同一份存储,所以它们有大量的数据库内部的数据结构的一致性需要来保证。如果已经上完数据库那就会了解,传统数据库的核心数据结构还是 beprostree。
这个架构以后,一个 RW 节点跟读写节点跟只读节点,其实是会访问同一 BW,那怎么 Bplustread,怎么保证多个计算节点访问同一个 B+TREE 时的正确点,比如一个节点要做一些结构变更,那另外一个节点怎么感知到,怎么能不让自己出错。第二部分就是只读节点也需要感知读写节点的事物的变化。
如果了解格力级别,比如 repeat for read,或者 read committed,那需要的是所有读还是要保证 acid,就是在读写节点上还没有提交的事物只读节点是不应该读到的。但是读写节点上已经修改的事物把某些配置修改了,比如它已经插入了行,那怎么识别出这些行,还是给其他事物一个一致性的事物状态,这是比较有挑战的。最后就是各种Cache层的同步,也是工作量比较大的一些事情。
所以逐一来介绍一下这几个挑战。如果没有了解,还没有学到 B+TREE 那可能不一定要感受,但是在这个理论点就是方向点其实是可以 cache 到的。首先面临的问题就是在两个节点上,要访问同样的 TREE,虽然只有读写节点能修改这个 TREE,但是读写节点修改这个 TREE 时它是通过锁来保证,就是某一部分指数,别的读流量是不能访问到它的,因为它把这些指数给锁住了,在主节点上的,在读写节点上的其他读事物是不能访问的这些配置,它需要进行等待。
但是在只读节点上,它并不知道这些配件已经被锁住了,这是很常见,因为不可能用分布式锁把所有只读节点的配置都锁住,所以就会有一个并发问题,因为整个信息通信是并行的,有可能它的父节点还是老版本的,但是子节点已经变成新版本了。那 topdone trouble 时状态就不对了,所以需要引入新的机制来解决这个问题,这里是引入了结构化的版本。
知道某一个配置它所处的结构变更的版本,在读写节点上如果发生这种结构变更,因为它组织怎么TREE,肯定是要做节点分裂或者节点合并,通过版本对比在读节点上感知到这个结构不变更。它就可以知道已经是老的访问到新的指针了,那它可以 restart travel。来解决这个问题的思路就是这样。
那第二个点就是一写多读的事物的隔离性,Mecc 这个机制其实是多版本快照这个机制,是数据库里面并发控制比较核心的一个机制。主节点上它是通过标志事物是否活跃,来通过 ondo 或者通过多版本来构造一个一次性的镜像。那读写事物上分成只读节点跟读写节点以后,那只读节点其实并不知道读写节点上的一个数状态。所以它可能会出现问题,要做的就是需要把读写节点的事务状态,通过redo给同步到只读节点上去,那么只读节点再重新回放这个事物状态,构造一个读写节点的一个事物状态的镜像。
那么只读节点在读事物时,通过这个构造的镜像来生成一个 readview,通过这个 readview 来探取现在真正的布置业,然后来通过 ondo,通过多版本来构造一个一致性的 readview 镜像来保证这个读还是一致的。相对来说另外一块就是,如果是通过原来的逻辑复制是完全没有这个问题,但是这是一写多读以后迎来的新的挑战。所以这是PolarDB为例子。
所以 PolarDB 除了上面做的这些还做了很多其他的优化,比如就是B-Link Tree,其实是要锁一个指数的,在这块又做了进一步的优化,就是 B-Link Tree 它完全是可以做成单配原子性,提升B+TREE的一个必发访问的能力。这这有很多点基本上都是在做一个性能的优化,就是能让用户感到更大的性能,包括 parallel Query,一个 Query 可以有多个线程来协助执行。原来一个线程基本是一个服务,从头服务到尾,那现在一个 Queryd 可以把一个单表的查询扩展成多个子任务,交给多个 worker 去处理。
因为现在的硬件盒越来越多了,所以这样可以提升整个 Query 的资源性能,包括独立的 buffer pool,包括并行的DDL,Hash Join 这种都是,所以在 polarDB 有了这些原来架构眼镜,以及上面的这些特性以后,现在在国内市场还是遥遥领先的。
那么在共享存储架构其实还有一些性能的挑战,就是写扩展性能。那刚才看到都是传统的云原生架构,都是一写多读的这个架构,所以它只有一个写节点多个读节点。那么刚才介绍了这个架构的一些挑战,这个架构本身存在的问题还是这个写节点的问题。虽然读能力能够扩展出去,但是写的能力还是在单节点上面,那对于这种流量比较大的,比如淘宝,那基本上一个写节点肯定是不能解决的,所以它要做写节点的扩展。
但现有的技术,写节点的扩展会引入很多新的基础的挑战,刚才介绍那些内存线图都是单向的,因为一个读写节点单向传递这些信息就可以,但是如果是多个写节点,比如说像下面这种图的形态。
那它就需要内存页的一个交叉同步,它的事物也是多个节点都可以去修改这个次数状态,所以要有一个分布式事务的处理机制。它的锁也是,所以又要有一些分锁的处理基础,这个挑战是非常大的。那么现在只有头部的,比如亚马逊,它前两年推出了一个多点可写的数据库的形态,就是想试图来在共享存储上来解决这个问题。
那么它是基于冲突检测来做这个机制,因为事务级别的这种信息同步,内存状态的同步,它的要求是非常高的,比如原来两个事物在同一个节点上的信息同步,它其实是一个内存的交互,都在同一块做一个信息的同步,写入一部分信息,看能不能看到,看到了就知道已经修改了这个页面。那么如果是在多个写入节点的情况下,这个页面要跨节点来传输,如果共享存储只有存储层来做这个快节点的信息传输。存储层跟计算节点通信代价是比较大的,刚才也提到肯定跟内存总线比大多了,因为内存总线是100纳秒左右,所以到了几十 u 秒几百 u 秒是很难接受的。
所以如果只能在共享存储上做,只能做一个乐观的机制。亚马逊就是做了一个乐观的机制,但乐观的机制就是在事务提交时才去做冲突检测。那这个对用户的损伤是比较大,用户可能做了一大半最后失败了,所以现在他们形态推广的不太好。因为1年就开始推推出这个 polarDB 这个形态,后面马上就开始做下一阶段的价格研究,后面会提到在做一个是共享云数据的库表级的冲突。
库表级没有冲突的,会分成两个阶段,一个库表级没有冲突的一个读写机制。所以大部分情况下,只要在多读节点之间做流量迁移就行。不需要去做这个完全冲突的数据,完全冲突的多写。另外一个是认为共享存储层做存储检测实在是太慢了,所以提出了在共享内存层做存储检测这个机制。
首先是无冲突的多库表写入这个,现在 polarDB 已经接近发布了,所以是 polarDB2.0的架构,而这个架构就是多个节点都可以访问不同库表,不同库表之间是可以做一个快速的流量迁移之类的动作,这个会在下半年发布。
以现在的一些测试情况来看,它的弹性性能非常好,它可以做写入节点的扩展,比如原来是四个写入节点,扩到八个写入节点,基本是秒级就可以扩出去。
基于存储层的 serverless,跨节点的数据迁移也在共享存储层上面做更多的优化,就是把整个跨物理机 serverless的迁移做得更加的柔和。
同时也提出了一个热备节点,热备节点这个架构就是可以把新的节点先 warmup 起来,可以再通过 proxy跟事务层的一个联合的优化,包括存储层的分布式锁,再做深配时可以做到用户无感知,因为可以做到连接的保持跟事务的保持,整个过程其实用户是没有感觉,或者说只是觉得当时连接稍微慢一点。这块是一个比较核心的架构,相关的结果也是发表在今年的 SIGMOD21上的。