滴滴 NewSQL 演进之 Fusion 实践

本文根据滴滴数据库存储专家余汶龙,在DTCC中国第十届数据库大会的演讲整理而成。

余汶龙

滴滴出行技术专家,曾经在VMware、淘宝、阿里云从事虚拟网络及存储领域的工作。现负责滴滴自研的NoSQL存储、NewSQL存储以及DTS项目。从零组建了Fusion存储团队,并带领团队完成了上述3个大型项目的架构设计、方案落地以及线上护航。

大家都知道,NewSQL 是对各种新型数据库的简称,这类数据库不仅具有NoSQL对海量数据处理的高扩展能力和高吞吐能力,还具有传统数据库的事务能力和SQL能力。

那么在一套成熟的NoSQL系统上,是否可以孵化出NewSQL系统来呢?答案是肯定的。

因为在滴滴,就有这么一个成熟的自研的NoSQL系统Fusion,基于他之上我们成功孵化了NewSQL系统。因此本次的分享大纲就分成3个部分,前面先讲我们在NoSQL上取得的成功,然后讲如何演变到NewSQL,最后讲这个演进方案的缺陷,指出未来的演进方向。

接下来,先看本次分享的大纲概述,如下。

这块是我们所有存储产品的整体架构视图,我们的产品都是在RocksDB引擎层基础之上构建。首先增加了网络层、集群管理层、接入层的工作,构建了我们的NoSQL存储系统Fusion,然后在Fusion的基础之上,我们整合了滴滴的调度系统和Hadoop计算平台的能力,构建了我们的DTS服务FastLoad;第3块是在Fusion的基础上,增加了schema管理、二级索引、事务、binlog等能力,构建了我们的NewSQL存储dise;第4块是面向未来规划的分布式数据库。围绕这些核心服务,我们做了一套完善的智能管控系统,它是依托于salt-stack平台,实现了用户系统和运维系统,分别解决了用户接入问题和自动化运维的问题。

接下来,我们从NoSQL讲起。

第一章:成熟的NoSQL存储系统Fusion

这块首先讲Fusion的背景介绍。可以看到Fusion是用C++自研的分布式NoSQL数据库,支持Redis协议,数据通过RocksDB落盘,现在线上业务已经接入400多个业务,覆盖了全公司;当前线上规模是300多个集群,全自动化运维跑着,没有专门的OP人员参与,总数据量达到1500TB,峰值QPS超过1400W。

接下来讲Fusion的架构,如下。讲架构之前,先看Fusion的诞生背景,他诞生初期主要解决两个业务的数据存储:历史订单和司机行程轨迹。大家都知道滴滴是个每天订单千万级的业务,那么历史订单很快就会突破百亿级,而每条订单都会对应一条司机行程轨迹,而且打车距离越长,单条行程轨迹数据越大,这是一个比历史订单数据量更大的业务。在Fusion诞生之前,滴滴的存储主要是用Redis和MySQL,很显然在这种规模下的数据量,用Redis和MySQL并不是最优解。因此诞生了Fusion。

因为Redis的协议实现很简单,且数据结构非常丰富,因此我们在磁盘上去实现了Redis的存储结构,基于这样的核心思想,我们实现了Fusion的集群架构,从上往下分别是接入层、集群管理层、持久层、高可用层。

接下来,总结了5个亮点,挑其中4个来说明Fusion的产品成熟度,如下:

亮点1:数据流动

第一个是数据流动能力。做为一个自研的存储系统,他必须融入整个公司的开发生态,具备与其他存储系统、中间件、离线计算、实时计算等平台打通的能力,才能推广开。因此,我们在这方面做了很多工作,其中挑hive到Fusion打通,以及Fusion与Fusion之间打通的例子来展开介绍。

为了解决离线hive到Fusion的数据流动,我们做了一站式DTS平台FastLoad,其架构设计如下:

首先,他诞生初期是为了解决标签平台和特征平台的业务问题。这两个业务的数据是通过离线计算产生,因此数据是存放在hive上,很显然hive的优势并不是OLTP。

因此他们希望有个存储系统能够满足两个需求:

1. 支撑每天数百亿次的高速查询;

2. 支持他们快速的从离线更新TB级别的数据到在线。

很显然Fusion很容易满足第一个需求。那么第二个需求如何解决呢?业务很容易想到的办法是:遍历读取hive的数据,然后构造成一条条Redis协议支持的KV数据,然后调用Redis客户端写到我们的VIP->proxy->Fusion。整个过程链路比较长,总结下有3个核心痛点:

  1. 浪费研发资源。凡是有从hive到Fusion数据打通的业务,都得维护一套相同逻辑的代码。
  2. 难以保证稳定性。离线平台意味着高吞吐、高并发,用它往在线数据库灌数据,显然得注意流控和错峰,因此稳定性难以保证。
  3. 生产效率低。业务使用Redis协议的方式灌库,很多batch和压缩能力都没法用上。

基于上述的业务需求和核心痛点,我们做了FastLoad一站式DTS平台。它主要给RD、产品经理等用户提供服务,因此提供了两种接入方式:web console和open API。用户通过这两种方式,把FastLoad任务上传到我们服务器,然后服务器会注册一个调度任务,该调度任务通过用户传入参数,判定数据源,然后从数据源捞取目标数据,再把目标数据分片通过may/reduce做排序,构建SST文件,然后通过TCP协议的方式下载到Fusion存储节点,绕过proxy,利用RocksDB的ingest功能,加载到Fusion当中,再通知用户,用户就可以通过Redis协议读到导入的数据了。

第二个流动能力是集群迁移。

它是指一个Fusion集群到另一个Fusion集群的数据在线热迁移,包括全量和增量,迁移过程是在线不停服的,对用户无感知的,这个功能可以用于业务一建开城、机房迁移等。它实现了两个异构集群间节点的点对点数据迁移。迁移的过程大概是:首先源节点保留增量日志,同时构建全量快照,然后遍历快照生成临时的SST,再以SST文件的方式发送到对端master,master收到后转发到slave,待全量同步完成,再打开增量日志的同步,其他细节如下。

亮点2:降级容灾

首先Fusion具有主库降级能力,当业务流量高峰时,导致主库响应慢,此时扩容已经来不及,因此我们在proxy上实现了读写分离能力,即牺牲一定的一致性,把一部分读流量路由到从库,达到保全主库的目的。

然后是集群容灾。即Fusion底层实现了两个集群间的数据自动同步。正常情况,用户通过VIP1访问集群1的数据,当集群1不可用时,我们提供两种切流方案:第一种是,需要用户切换访问链路到VIP2,这可能需要用户重启;第二种是假设VIP可用,我们可以通过一键切流平台,把VIP1指向的Real Server改到集群2。

接下来看看是如何实现集群间数据同步的。

我们实现了异构集群间节点的点对点数据传输,不依赖任何中间件,每个节点会感知对端集群的路由信息,且能适应两端集群的状态变化,比如切主、扩容等,都能保证数据由正确的节点发起,然后同步到正确的节点。整个数据的可靠性是由滑动窗口来保证的,即我们用写到Fusion的key的唯一seq做滑动窗口的元素,实现了一个send/ack机制,保证了顺序发送、顺序重传、可靠传送。

另外,该方案还支持数据的自动补偿。即当集群1挂掉后,用户把流量切到集群2,在集群1恢复之前的这部分增量数据,会在集群1恢复之后,自动同步过去。

最后,这个方案也支持双写。我们利用RocksDB的merge功能,做了一个基于NTP的去重方案。

亮点3:极致效率

这块是针对RocksDB的一些特性做些优化。第一个我们实现了key粒度且具有热点预测功能的cache,解决RocksDB随机读问题,命中率能达到原生的3倍;第二个是实现了compact的24小时调度,磁盘能节约25%,延迟和毛刺均有大幅度降低;第三个优化内存占用,比如slave的page-cache是无用的,需要GC,block-cache在低峰时期是无用的,也需要GC等。

亮点4:安全保障

第一个是升级时数据备份。常规升级时,我们都会备份二进制文件和配置文件,但是对于数据并没有备份。我们针对RocksDB的SST文件特性,即只会被创建和删除,而不会被修改,做了一个硬链接备份方案,该方案是写时拷贝,因此备份速度非常快且磁盘空间占用非常少。更关键的是,这个方案是实现在智能管控平台的升级流程里面,不需要改服务端代码,只需要修改管控程序就可以了,因此很方便做到100%线上覆盖,保证数据安全。

第二个是提供用户级别快照,利用了RocksDB的checkpoint,可以做到秒级快照。

第三个是数据多版本存放。即在FastLoad场景里面,我们会保留多版本数据,用于用户随时随地的切换他需要的数据,比如A/Btest,数据回滚等。

第二章:基于Fusion的NewSQL探索实践

接下来讨论NewSQL探索实践的细节。

首先,需要回答一个问题,我们为什么要做NewSQL演进?我想大家的出发点都是一样的,都是为了解决在大数据量存储下的MySQL的几个核心问题,即:灵活问题、扩展问题、成本问题。那么对应的NewSQL,我认为就该具备这样几个能力:轻松加字段、存储不限量、更高性价比。

那要实现这样的目标,面临哪些挑战呢?

  1. 如何在KV系统上感知用户schema?
  2. 如何在KV系统上吐出兼容MySQL的binlog?
  3. 如何实现二级索引的存储和查询?
  4. 如何实现事务和事务的交互?

接下来,给出我们的NewSQL架构图。首先我们把用户的DDL操作,收敛到控制台,不让用户直接给DB发起DDL操作,用户发起的DDL操作,改变的schema信息,会保存到配置中心,同时会推送给我们的proxy,所有proxy推送成功后,返回给用户成功信息。用户在通过MySQL客户端访问我们的proxy,我们在原来Redis协议的proxy上,增加了SQL-parser等工作,并将接受到的用户SQL请求,转成KV,再写到Fusion。Fusion服务端会生成MySQL格式的binlog,再吐出到MQ,我们的索引服务器会异步消费这部分信息,然后根据用户自定义的索引key,把他写到索引存储里即可。

schema管理

这块的核心思路,就是把DDL操作与数据流分离,通过配置中心来解耦。Proxy这边重点需要解析SQL,转换KV等。目前Fusion支持insert/replace/delete/select/update语句,它的定位是解决单表大表的存储问题,与MySQL做一定程度的互补,因此在兼容MySQL上做了较大的舍弃。

这里给了一个SQL到KV转换的例子,左边是一个student表,三行四列,右边是Redis的hash编码,大key有表名加主键组成,field是列名,value是行列值。

binlog兼容

这块是讲如何吐出binlog的,因为滴滴的通用binlog是需要原值的,而KV默认的log是只有当前值,因此我们在产生log的时候,先判断用户的插入类型,如果是update就先取原值,再一起写到log里,如果是insert则不需要。

二级索引(唯一和非唯一)

上述binlog吐出到MQ之后,这里的索引模块会来消费MQ,并异步构建索引(因为性能考虑和不具备分布式事务能力,因此没有做实时索引)。索引key的拼接方式如下两种,这里需要注意的是,看前面Fusion的架构图,我们知道Fusion集群的数据分片是通过hash实现的,因此分片之间是不连续的,无法做到跨节点scan,因此我们对同一个列索引,增加了一个分区健,即Redis协议的hash-tag,来保证同一个索引,必须存到同一个节点,方便我们做scan。

事务功能

事实上我们不支持分布式事务,还是通过redis的hash-tag,规避了分布式事务,即跟用户约定,让用户把希望做事务保证的行的主键,带上hash-tag,让这些行放到同一个节点。分布式事务就转成单机事务了。而单机事务,我们利用了RocksDB的事务引擎,因为RocksDB再给MyRocks提供引擎时,支持了完备的事务能力,因此我们直接加以利用。最后要解决的是事务交互问题,这里我们通过lua来解决。

事务交互

原生Redis对于事务交互处理支持的并不好,比如不支持回滚等,因此我们想要通过Redis来实现事务交互,就得增加一些接口,但这些接口显然不是标准SDK提供的,就很难推广。好在Redis客户端提供了lua的脚本支持,那么Fusion也实现lua解释器的功能,就可以让用户通过lua脚本传递任何接口过来,这个特性可以很好的解耦。同时用户可以在lua脚本里实现各种if/else等逻辑。那么当我们把事务交互通过lua提供后,用户跟Fusion交互时,就可以把相关逻辑放到Fusion来执行,整个过程是一阶段事务,不需要复杂的begin/commit/rollback等。我们的proxy也不需要维护事务状态,内部的锁处理也更简单,不需要关心长事务,更不用关心事务里多个key是否分布在不同节点。

那在MySQL协议这边如何实现事务呢?我们是建议用户把lua脚本写到MySQL的comment里,通过接下comment的lua,来执行事务。

总结

最后,对我们的NewSQL方案做个小结。他的优点很明显,直接在现有NoSQL架构上加以迭代即可快速上线,复用程度高,稳定性高;同时在不需要事务的场景下,确实很好的解决了扩展问题、灵活问题;另外,在前面提到的hive到Fusion的打通中,让用户使用更自然,因为原先的FastLoad是把SQL结构化的数据转成非SQL结构的KV的,现在有了NewSQL之后,用户就可以从SQL到SQL。

这个方案上线一年,当前存入数据超过了400TB,总QPS超过了200W;接入的业务超过了58个,平均每个业务存储8TB以上数据,可以看到这个数据量是MySQL不太容易解决的一个量级。

第三章:分布式数据库设计

前面只提到了NewSQL方案的优点,实际上,它还是有很多不足的地方,最核心的问题是,他是一个”伪分布式“方案,虽然数据做到了无限扩展,但是:

  1. 只实现了单机事务。
  2. 只实现了单机索引。因为集群按hash分片,无法跨机scan。
  3. 只有异步索引能力。因为没有分布式事务保证,我们只实现了异步索引。
  4. Join更是不支持的。
  5. 无弹性扩容能力scale out。

很显然,在现有的NoSQL架构上,已经无法简单的解决这些需求,需要彻底大改。因此,我们有了另起炉灶的项目——分布式数据库。它首要解决的几个问题是:

  1. 分布式事务。
  2. 数据和索引的真正无限扩展。
  3. 实时索引。
  4. 弹性扩容。
  5. 多副本强一致、高可用。
  6. SQL兼容等。

架构设计

架构设计如下,事实上,这也是分布式存储的经典架构,很多的系统都长在类似架构上面,它实现了range分区、强一致、弹性扩容、全局scan等能力。细节就不多做展开了。

当前状况

我们在这套架构上,实现了一个具备raft强一致、全局scan、自动分裂等能力的分布式KV系统,下一步是做分布式事务。即先实现一个功能强大的KV系统,然后在这基础上继续做SQL的支持。

总结三部曲

最后是对整个演进过程做一个总结。

首先我们研发了NoSQL系统Fusion,锻炼了我们的基础能力:分布式、持久化、高可用、数据流动等。

第二步是我们的NewSQL探索,我们做了一个快速解决业务问题的方案,这个方案有成功的地方,因为它解决了50多个业务的需求,也有失败的地方,我们无法在这套系统上走得更远,但这提升了我们的系统认知,这很重要。

第三步是未来演进,想要在海量数据OLTP这条路走的更远,必须彻底革命,因此最后的演进是抛弃了现有系统架构,从头设计我们的分布式数据库。这个项目也是分期的,一期我们先做一个功能强大的KV系统,然后二期在他的基础上增加SQL-parser,取代我们现有的NewSQL方案(功能比较简单,很容易落地),然后三期才是高度的SQL兼容。

整个演进过程遵循了两个原则:避免过度设计和大跃进。即在现有稳定的架构上花最小的代价,解决最短板问题。整个过程做到了产品的持续交付,既快速响应业务需求,又不断丰富自己的认知,最终朝着一个成本可控、稳定迭代的目标前进。

Image placeholder
jko3002
未设置
  62人点赞

没有讨论,发表一下自己的看法吧

推荐文章
用户从0到5亿,中国移动 OneLink 架构演进之路

导语本文根据范良泽老师在2019年10月31日【第十一届中国系统架构师大会(SACC)】现场演讲内容整理而成。范良泽(中移物联网有限公司系统架构专家)2008年毕业于上海交通大学,曾供职于华为、Ope

从网络接入层到 Service Mesh,蚂蚁金服网络代理的演进之路

本文作者:肖涵(涵畅)上篇文章《 诗和远方:蚂蚁金服ServiceMesh深度实践|QCon实录》中, 介绍了ServiceMesh在蚂蚁金服的落地情况和即将来临的双十一大考,帮助大家了解Servic

淘宝从几百到千万级并发的十四次架构演进之路!

作者:huashiou来源:https://segmentfault.com/a/11900000186261631.概述本文以淘宝为例,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时

滴滴从KV存储到NewSQL实战

桔妹导读:本文讲诉滴滴在分布式Nosql存储Fusion之上构建NewSQL的实践之路。详细描述Fusion-NewSQL的特性,应用场景,设计方案。1.背景Fusion-NewSQL是由滴滴自研的在

大神讲解微服务治理的技术演进和架构实践

摘要:随着业务的发展,规模扩大,服务越来越多,需要协调线上运行的各个服务,保障服务的SLA;基于服务调用的性能KPI数据进行容量管理,合理分配各服务的资源占用;对故障业务做服务降级、流量控制、流量迁移

PB级数据实时查询,滴滴Elasticsearch多集群架构实践

Elasticsearch是基于Lucene实现的分布式搜索引擎,提供了海量数据实时检索和分析能力。Elastic 公司开源的一系列产品组成的ElasticStack,可以为日志服务、搜索引擎、系统监

HDFS3.2升级在滴滴的实践

桔妹导读:Hadoop 3的第一个稳定版本在2017年底就已经发布了,有了很多重大的改进。在HDFS方面,支持了ErasureCoding、Morethan2NameNodes、Router-Base

让AI无处不在:滴滴与蚂蚁金服开源共建SQLFlow

2018年1月,Oracle的官方博客上发表了一篇文章,标题是“It’sPervasive:AIIsEverywhere”。作为全球最著名的商业数据库系统提供商,Oracle在这篇文章里历数了AI在企

微博广告策略工程架构体系演进

概述 1.广告样式与场景 上图是微博广告目前商业场景流,“一屏四大流”。“一屏”指打开微博的Fashion,“四大流”指占据微博商业化的主体,包括关系信息流、热门流、评论流和热搜流。右图为广告投放的

深度解读当代前端架构演进与趋势(上)

软件架构的核心思想,就是推断软件系统各个组件之间数据流动的方式。软件架构的质量取决于你设法推断这些数据流的难易程度!本文要讲的内容,就是在今天的Web应用程序背后探索这些数据流和最终的体系结构。We

一个多业务、多状态、多操作的交易链路?闲鱼架构这样演进

前言双十一刚刚结束,成交额2684亿震惊全世界,每秒订单峰值达54.4W笔。在闲鱼2000万DAU,交易数额同样增长迅速的今天,我们如何保障交易链路的稳定与快速支撑业务?这篇文章从客户端开发的角度,介

数字转型 架构演进 2019中国系统架构师大会盛大召开

2019年10月31日~11月2日,由IT168旗下ChinaUnix社区主办的第十一届中国系统架构师大会(SACC2019)在北京隆重召开。自2009年举办以来,大会云集了国内CTO、研发总监、高级

来SACC2019共论“数字转型 架构演进”之道

2019已经过半,第十一届中国系统架构师大会SACC2019的脚步也越来越近了,十年来中国系统架构师大会SACC一直紧跟系统架构关键技术热点,成为架构师、CTO、CIO以及各研发人员学习交流的前沿阵地

滴滴 曾奇:谈谈我所认识的分布式锁

桔妹导读:随着计算机技术和工程架构的发展,微服务变得越来越热。如今,绝大多数服务都处于分布式环境中,其中,数据一致性是我们一直关注的重点。分布式锁到底是什么?经过了哪些发展演进?工程上有哪些实现方案?

滴滴海量离线数据的在线化 — FastLoad

桔妹导读:滴滴自成立以来,有海量的数据存储在离线平台,离线数据虽然存储便宜,压缩比高,但不适用于线上使用。为此,我们提供了一键式DTS平台——FastLoad,帮助业务往在线存储系统搬运离线数据,目前

浅谈滴滴派单算法

桔妹导读:说到滴滴的派单算法,大家可能感觉到既神秘又好奇,从出租车扬召到司机在滴滴平台抢单最后到平台派单,大家今天的出行体验已经发生了翻天覆地的变化,面对着每天数千万的呼叫,滴滴的派单算法一直在持

滴滴大数据在汽车金融风控场景中的应用

桔妹导读:滴滴独有的出行场景大数据在金融领域有着非常广泛的应用前景,未来可与银行,保险,支付和理财等机构深入合作,帮助传统金融机构提升资源配置效率,降低获客和风险管理成本。出行场景大数据在交易欺诈识别

UfqiNews有福新闻的第N+1批次更新:清晰,流畅,省电

UfqiNews有福新闻自推出以来,一直持续更新、优化升级,作为一款带来全新新闻阅读体验的资讯应用,已经日益成熟,浏览量也日渐攀升。近日针对UfqiNews有福新闻的升级改进包括如下方面。1.UI调整

从Oracle到PostgreSQL,某保险公司迁移实践

摘要:去O一直是金融保险行业永恒的话题,但去O的难度之大也只有真正经历过的人才知其中的艰辛。此次笔者结合实际去O工作,对去O过程中碰到的DBLINK、SEQUENCE最大值、空串、SQL语句中的别名等

从 Oracle 到 PostgreSQL ,某保险公司迁移实践

作者 |章晨曦编辑 | 老鱼摘要:去O一直是金融保险行业永恒的话题,但去O的难度之大也只有真正经历过的人才知其中的艰辛。此次笔者结合实际去O工作,对去O过程中碰到的DBLINK、SEQUENCE最大值

Mysql数据实时同步实践

关于小米内部使用的数据库你知道多少?背景Mysql由于自身简单、高效、可靠的特点,成为小米内部使用最广泛的数据库,但是当数据量达到千万/亿级别的时候,mysql的相关操作会变的非常迟缓;如果这时还有实

GORM 中文文档_4.5. 原生 SQL 和 SQL 生成器

运行原生SQL 执行原生SQL时不能通过链式调用其他方法 db.Exec("DROPTABLEusers;") db.Exec("UPDATEordersSETshipped_at=?WHEREidI

【Golang+MySQL】记一次 MySQL 数据库迁移(一)

【Golang+mysql】记一次mysql数据库迁移(一)文章地址:https://github.com/stayfoo/stayfoo-hub一、准备目标: 腾讯云CVM自建mysql数据迁移到腾

MySQL 性能优化:8 种常见 SQL 错误用法!

1、LIMIT语句分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如对于下面简单的语句,一般DBA想到的办法是在type,name,create_time字段上加组合索引。这样条件排序都

为什么SQL正在击败NoSQL,这对未来的数据意味着什么

导读:经过多年的沉寂之后,今天的SQL正在复出。缘由如何?这对数据社区有什么影响?看看本文的分析。以下为译文。自从可以利用计算机做事以来,我们一直在收集的数据以指数级的速度在增长,因此对于数据存储、处