TiDB在摩拜单车在线数据业务的应用和实践

作者 丁宬杰,胡明

责编 郭芮

【导语】摩拜每天产生的骑行数据超过30TB,在全球拥有最为全面的骑行大数据,飞速增长的业务下也面临着数据库扩展与运维的巨大挑战。中间件方案对业务过强的侵入性、不支持跨分片的分布式事务、无法保证强一致性事务的特性都使我们望而却步。2017年初,摩拜单车开始使用TiDB,从最早的RC3、RC4、PreGA、到现在的1.0正式版,一步步见证了TiDB的成熟和稳定。

背景

摩拜单车于2015年1月成立,2016年4月22日地球日当天正式推出智能共享单车服务,截至 2017年11 月中旬,已先后进入国内外超过180个城市,运营着超过700万辆摩拜单车,为全球超过2亿用户提供着智能出行服务,日订单量超过3000万,成为全球最大的智能共享单车运营平台和移动物联网平台。摩拜每天产生的骑行数据超过30TB,在全球拥有最为全面的骑行大数据,飞速增长的业务使摩拜面临数据库扩展与运维的巨大挑战。

面对飞速增长的并发数与数据量,单机数据库终将因无法支撑业务压力而罢工。在摩拜正式上线以来,我们就在不断思考数据库扩展和运维的未来,近年来业内对数据库进行扩展的常见的方案是通过中间件把数据库表进行水平拆分,将表内数据按照规则拆分到多个物理数据库中。使用这样的中间件方案,在数据库扩容时需要先停下业务,再重构代码,之后进行数据迁移,对于摩拜这样与时间赛跑的创业公司来讲代价巨大,中间件方案对业务过强的侵入性、不支持跨分片的分布式事务、无法保证强一致性事务的特性都使我们望而却步。

摩拜单车于2017年初开始使用TiDB,从最早的 RC3、RC4、PreGA、到现在的1.0正式版,一步步见证了TiDB 的成熟和稳定。目前支撑着摩拜内部的实时分析和部分线上业务,同时正在规划迁移更多的线上业务至TiDB。

目前,TiDB在摩拜部署了数套集群,近百个节点,承载着数十TB 的各类数据。

TiDB 在摩拜的角色和主要应用场景

在摩拜,TiDB是一个核心的数据交易与存储支撑平台,引入它的主要目的是用来解决海量数据的在线存储、大规模实时数据分析和处理。

在我们看来,TiDB的好处主要有:

弹性扩容。具有NoSQL类似的扩容能力,在数据量和访问流量持续增长的情况下能够通过水平扩容提高系统的业务支撑能力,并且响应延迟稳定。

简单易用。兼容MySQL协议,基本上开箱即用,完全不用担心传统分库分表方案带来的心智负担和复杂的维护成本,而且用户界面友好,常规的技术人员都可以很高效地进行维护和管理。

响应及时。因为和PingCAP团队有非常深入的合作关系,所以有任何问题都可以第一时间和PingCAP团队直接沟通交流,遇到问题都能很快地处理和解决。

下面介绍 TiDB 的应用场景。

应用场景一:开关锁日志成功率统计

开关锁成功率是摩拜业务监控的重点指标之一。

在每次开、关锁过程中,用户和锁信息会在关键业务节点产生海量日志,通过对线上日志的汇总分析,我们把用户的行为规整为人和车两个维度,通过分布式、持久化消息队列,导入并存放到TiDB里。在此过程中,通过对不同的实体添加不同的标签,我们就能方便地按照地域、应用版本、终端类型、用户、自行车等不同的维度,分别统计各个类别的开锁成功率。

按照我们的估计,这个业务一年的量在数百亿,所以使用单机的MySQL库需要频繁地进行归档,特别是遇到单机数据库瓶颈的情况下,扩容更是带来了非常大的挑战,这在我们有限的人力情况下,完全是个灾难。所以要支撑整个后端数据库,我们必须要寻找简单易用的方案,极大地减少在单个业务上的人力成本开销。其次,根据我们之前使用分库分表的经验,对于这类需要频繁更新表结构进行DDL操作的业务,一旦数据量过大,很容易出现数据库假死的情况,不仅影响服务的可用性,更严重的是很可能导致数据不一致的情况出现。最后,我们希望不管今后的业务量如何激增,业务需求如何变化,都可以保持业务逻辑可以很方便地升级支持。

在方案设计时,我们对比了MySQL分库分表和 TiDB方案。

我们先估计了可能的情况:

新业务上线,在线变动肯定是经常发生的;

尽可能存长时间的数据,以备进行统计比较;

数据要支持经常性的关联查询,支撑运营组的临时需求;

要能支撑业务的快速增长或者一些特殊活动造成的临时流量。

考虑到这些情况,MySQL分库分表的方案就出现了一些问题,首先频繁变动表结构就比较麻烦,而TiDB可以进行在线DDL。数据生命期比较长,可以设计之初做一个比较大的集群,但是弹性就比较差,针对这个问题,TiDB 可以根据需要弹性地增加或者减少节点,这样的灵活性是 MySQL 分库分表没有的。另外,数据要支持频繁的复杂关联查询,MySQL 分库分表方案完全没办法做到这一点,而这恰恰是 TiDB 的优势。通过以上的对比分析,我们选择了 TiDB 作为开关锁日志成功率统计项目的支撑数据库。

图1 Mobike选择 TiDB 支撑开关锁日志成功率统计项目

目前,大致可以将到端到端的延时控制在分钟级,若有开锁成功率下降,监控端可即时感知。此外,还能通过后台按用户和车查询单次故障骑行事件,帮助运维人员快速定位出故障的具体位置。

应用场景二:实时数据分析

数据分析场景中,TiDB可以从线上所有的MySQL 实例中实时同步各类数据,通过TiDB周边工具 Syncer导入到TiDB进行存储。

这个业务的需求很简单,我们线上有数十个 MySQL集群,有的是分库分表的,有的是独立的实例。这些孤立的数据要进行归集以便业务方进行数据分析。我们一开始计划把这些库同步到 Hive 中,考察了两种方式:一种是每日全量同步,这么做对线上的库压力以及Hive的资源开销都会越来越大;另一种是增量同步,这种方式非常复杂,因为HDFS不支持update,需要把每日增量的部分和之前的部分做merge计算,这种方法的优点是在数据量比较大的情况下,增量同步对比全量同步要更快、更节省空间,缺点是占用相当一部分Hadoop平台的计算资源,影响系统稳定性。

TiDB本身有很多不错的工具,可以和MySQL的生态方便地连接到一起。这里我们主要使用了Syncer,这个工具可以方便地把 MySQL 实例或者MySQL分库分表的集群都同步到 TiDB 集群。因为TiDB本身可以update,所以不存在Hive里的那些问题。同时有TiSpark项目,数据进TiDB以后,可以直接通过Spark进行非常复杂的OLAP查询。有了这套系统,运营部门提出的一些复杂在线需求,都能够快速简洁地完成交付,在Hadoop平台上是无法提供这样的实时性的。

目前,该集群拥有数十个节点,存储容量数十TB,受益于TiDB天然的高可用构架,该系统运行稳定,日后集群规模日益变大也仅需简单增加x86 服务器即可扩展。后台开发、运维、业务方等都可以利用TiDB的数据聚合能力汇总数据,进行数据的汇总和分析。

应用场景三:实时在线 OLTP 业务

如前所述,对比传统的分库分表方案,TiDB的灵活性和可扩展性在实时在线业务上优势更加明显。

根据我们的测试,TiDB在数据量超过5千万时,对比MySQL优势较大,同时协议层高度兼容 MySQL,几乎不用修改业务代码就能直接使用,所以TiDB集群对于数据量大的实时在线业务非常适合。

图2 场景应用之实时数据分析

目前,摩拜主要上线了两套在线OLTP业务,分别是摩豆信用分业务和摩豆商城业务。

摩豆信用分业务

图3 摩豆信用分业务

摩拜单车信用分业务与用户骑行相关,用户扫码开锁时先行查询用户信用积分判断是否符合骑行条件,待骑行完成后,系统会根据用户行为进行信用分评估并进行修改。当单车无法骑行,上报故障核实有效后增加信用分、举报违停核实有效后降低信用分;但是如果不遵守使用规范,则会扣除相应的信用分;例如用户将自行车停在禁停区域内,系统就会扣除该用户的部分信用分作为惩罚,并存档该违停记录。当用户的信用分低于 80分时,骑行费用将会大幅上升。

摩豆商城业务(App 中的摩拜成就馆)

魔豆商城业务即摩拜成就馆,用户的每一次骑行结束后,系统会根据骑行信息赠送数量不等的省时币、环保币、健康币作为积分,通过积累这些积分可以在摩拜成就馆内兑换相应积分的实物礼品。

这些业务的共同特点:

7*24*365 在线,需要系统非常健壮,在任何状况下保证稳定运行;

数据不希望删除,希望能一直保存全量数据;

平时高峰期并发就非常大,搞活动的时候并发会有几倍的增长;

即便有业务变更,业务也不能暂停。

由于是典型OLTP场景,可选项并不多,而且数据量增长极快,这些数据库的数据在一年内轻松达到数百亿量级。这些场景在我们有了TiDB的使用经验以后,发现TiDB的所有特性都非常契合这种海量高并发的OLTP场景。TiDB的容量/并发可随意扩展的特性不再赘述,支持在线DDL这个特性特别适合这些业务,有需要业务更改不会阻塞业务,这是我们业务快速迭代比较需要的特性。

目前,这两个在线OLTP集群拥有数十个节点、百亿级数据,上线以后非常稳定,PingCAP客户支持团队也协助我们进行该集群的日常运维工作。

应用场景四:违章停车记录/开锁短信库等日志归集库

相对于传统的针对不同的业务分别部署MySQL 集群的方案,TiDB在可扩展性和在线跨库分析方面有较大优势。

在部署TiDB之前,摩拜面对新增的业务需要对其进行单独的规划和设计,并根据业务的数据量,增速以及并发量设计MySQL的分库分表方案,这些重复的预先设计工作在所难免。另一方面,不同业务之间往往是有关联的,当运营部门需要不同业务的汇总数据时就变得异常麻烦,需要新建一个临时的数据汇总中心,例如新建一套MySQL 分库分表的集群,或者临时向大数据组申请Hive 的空间,这都让数据提供的工作变得麻烦。

有了TiDB以后,此类业务的开发和数据提供都变得非常简单,每次新需求下来,只需要按照新增数据量增加TiKV节点的数量即可,因为整个集群变得比较大,并发承载能力非常强,基本不需要考虑并发承载能力。特别的好处是,因为这些业务有相关性的业务,放在一个独立的数据库中,运营需要提供某几类某段时间的数据时就变得极为方便。

基于TiSpark项目,Spark集群可以直接读取TiDB 集群的数据,在一些运营需要实时数据提供的场景,不再需要按照原有的提供数据到大数据平台,设计ETL方案,运营再去大数据部门沟通运算逻辑。而是直接在TiDB现有数据的基础上,直接提出复杂的分析需求,设计Spark程序进行在线的直接分析即可。这样做,我们非常容易就可以实现一些实时状态的分析需求,让数据除了完成自己的工作,还能更好的辅助运营团队。

图5 基于 TiSpark 项目直接读取 TiDB 集群的数据

使用过程中遇到的问题和优化

在说优化问题之前,先看TiDB的架构图,如图6所示。其中:

图6 TiDB 架构图

PD是整个集群的管理模块,负责元信息管理、集群调度和分配全局递增非连续ID;

TiDB 是客户端接入层,负责SQL解析、执行计划优化,通过PD定位存储计算所需数据的TiKV 地址;

TiKV是数据的存储层,底层是基于RocksDB的KV引擎,并在其上分别封装MVCC和Raft 协议,保证数据的安全、一致;

TiSpark是Spark接入层,负责把Spark和TiKV 连接到一起,在执行非常重的OLAP业务时可以利用到Spark集群的优势。

在使用过程中,遇到过不少问题,但是在我方和 PingCAP技术团队的充分交流和协作下,都得到了比较完善的解决,下面挑选最为重要的资源隔离与优化展开。

TiKV中数据存储的基本单位是Region,每个 Region都会按顺序存储一部分信息。当一个 Region包含多个表的数据,或一台机器上有多个Region同时为热点数据时,就容易产生资源瓶颈。

PD 在设计之初考虑了这方面的问题(专门设计了 HotRegionBalance),但是它的调度粒度是单个 Region,并且整个调度基于这样的假设:即每个 Region的资源消耗对等,不同Region之间没有关联,同时尽量保持Region均摊在所有Store。

但当一个集群同时承载多个库,或一个库中包含多个表时,发生资源瓶颈的概率会明显提升。

针对这个问题,我们和PingCAP技术团队合作,对 TiDB做了以下优化。

优化1:基于Table的分裂

这个修改的目的是解决小表数据的相互影响的问题。

当有新表数据插入某一 Region 时,TiKV会根据当前Region的Key Range计算出tableID,如果发现插入的Key不在这 KeyRange中,会对这个 Region提前分裂,这就保证了每个Region只包含一个表的数据。

优化2:表级别的资源隔离

与此同时,我们在PD增加了TableID和 NameSpace 之间的映射关系以及NameSpace和 TiKV Store 的映射关系,通过把上述关系持久化到 eEtcd 里,保证该映射关系的安全。

当数据插入时,可以在TiDB层面拿到TableID,进而从PD找出目标Region所在的 TiKV,保证新插入的数据不会放到其他 TiKV。

另外,我们还与PingCAP团队共同开发实现了一个NameSpace调度器,把未规整的Region调度回应在它的TiKV里,进而在表级别保证数据不会相互干扰。

优化3:管理工具

最后是管理NameSpace的问题。

TiDB在早期设计时保留了足够的灵活性,通过 TiDB原有接口,我们只需要调用相关API即能通过表名拿到TableID。

同时我们在PD的命令行管理台pc-ctl中增加了 HTTP接口,管理确认Table Name和Table ID之间的对应关系。

后记

部署TiDB近一年来,摩拜单车经历了用户数量近十倍、日骑行数据数十倍的增长,依靠其线扩容的能力,我们完成了多次数据库扩容与服务器更换,而且这些操作对业务是完全透明的,我们可以更专注于业务程序的开发与优化,而无须了解数据库的分片规则,对于快速成长的初创公司,这有着很强的借鉴意义。另外深度参与TiDB的开发并和开源社区紧密的互动,也使我们获得了很多有益的反馈,极大降低了代码维护成本。

未来,我们会联合PingCAP进一步丰富多集群的管理工具,进行更深入的研究和开发,持续提升 TiDB的性能,将它应用到更多的业务中。

作者简介:丁宬杰,摩拜基础平台工程师,2017年初加入摩拜,主要参与了系统稳定性改造、数据库分库分表等项目,现在专注于跟团队一起为摩拜提供稳定高效安全的数据存储服务。

胡明,摩拜单车工程师,十年软件开发经验,现在专注于数据库、分布式系统方向。

本文为《程序员》原创文章,未经允许不得转载。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171219B08R7C00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券