TiDB 在某餐饮 SaaS 服务商的实践及海外机房构建

作者:火烧,TUG 杭州区 leader。本文系 2019 年 Techday 杭州站演讲实录。

公司从 2017 年 9 月开始上线 TiDB,目前有 2 套 TiDB 集群。最开始使用是在集群 2 上使用,该集群目前有 1W+ QPS,主要是批量写入的场景,复杂读取,主要是给数据中心使用的。另一个集群有 100亿+ 条记录,集群上有十几个业务,是实时写入的场景。这套集群数据库量比较大,但是读取量和写入量并不是很大。两套集群一共有 20+ 台服务器。

公司首先在数据大屏及报表的场景上线了 TiDB。下面是没有使用 TiDB 之前的架构。

首先 MQ 从 Binlog 里读取数据,然后写入到报表业务应用和的 MySQL 和 Solr 里。业务从数据中心进,读取 MySQL 和 Solr 的数据。因为报表的维度非常多,有成百上千张报表。业务要读取的话,可能从 MySQL 里读,有可能从 Solr 里面读,也有的是从分库之后报表业务应用使用的的 100 多个实例里面读取,也会从 MySQL 的备库和 MySQL 的 库里面分别做一定的查询和读取。也会在,Solr 内部有好几套集群,有订单的,有商品的,从各个维度进行读取,然后进行合并。

这么多工作信息放在那边,新的开发人员过来的时候,不知道某一个报表需要从哪里进行读取;就算他知道,有的数据从 Solr 里读取,可能带有嵌套、循环。这样多数据合并计算的时候,代码会非常冗长,嵌套很多,很容易出错。

我们是 ToB 的业务,ToB 业务有连锁和非连锁的。一个连锁大店之下有很多小的店铺,查询某一个店铺的数据时,查询性能非常低下。不进行处理的话,要过十几秒才能返回报表数据。店家非常关注实时报表的数据,需要查询的返回时间要达到秒级。这个时候,我们的架构,提供给商家的业务会出现一些问题。如果某个店铺的连锁关系进行了调整,相当于数据要进行迁移。数据进行迁移就属于 T+1。这个时候就无法提供实时报表。分库分表是按照店铺的 ID 来分的,不能按照连锁的 ID 分库。不管是如何分库,有些店的数据量特别大,这样它在某一个库的实例之下, IO 特别高,会造资源使用不均衡。特别是有些店要在下午两点做账,晚上 9 点做账,可能会出现报表瘫痪的情况。

在 2017 年的时候我们接触到了 TiDB。经过功能测试、多数据写、MySQL 和 TiDB 两套集群同时进行使用、以及一些推广后,我们正式使用了 TiDB。这是我们目前的架构。

业务提供 Binlog 数据,通过 Otter 发送 App 消息。App 消息我们做了策略:将商家 ID 进行哈希,一个商家的 ID 只会发送到一个 MQ 的队列里去。这样后面订阅消息的时候可以对一些数据进行 merge。为什么要进行 merge 呢?因为数据大屏的数据写入量太大,负载非常高。而且数据大屏的业务,不需要秒级展现,只要数据 5s 之内可以进行变更就是可接受的。如果不按照商家的 ID 来进行队列,merge 操作会在不同的机器上处理,这样无法对数据进行合并处理。

数据合并处理完之后存放在 TiDB,有的是通过 TiDB 进行访问,有的是通过 Redis 进行访问。在 2017 年之前,我们的实时报表做到了十几张,TiDB 上线以后已经做到了所有报表的实时化。这些是 TiDB 在我们的数据大屏场景下的应用。

TiDB 集群 1 是在我们的常规业务下使用的。这个集群当时是为了上交易生产线的 TiDB 集群做准备的。所以我们抽取了一些数据量比较大的业务和一些无法分库的业务。有些业务经常需要更改 DDL,之前我们的数据库中间件是用的 Cobar,对 Cobar 更改,比如加一张表,需要更改配置文件,再进行 reload。这样加一张表相当于数据库中间件也要动,数据库也要动,给 DBA 带来很多繁琐的工作。

所以我们抽取了这些场景打算放到 TiDB 上面去做一些处理。这一套集群从 2017 年 10 月开始用,现在已经稳定运行 500 天以上,也发生过节点增加,因为我们是云上环境,也发生过某个节点挂掉。虽然发生过意外,但是整个系统稳定运行没有任何问题。

海外机房构建

下面是最近半年来我们海外机房构建的一些心得。

我们很多业务是在海外的,GDPR 绕不过去。GDPR 规定数据不能出国外,所以国外的数据只能在国外建机房,没有别的方式。就算在海外建了机房,也会出现响应延迟的问题。海外部署我们都是全量构建,公司的运维技术人员比较少,基础运维只有一个半人,投入到这上面来的只有 0.5+ 个人的运维把海外机房全部部署起来,而且交付时间很快。不是说把这些搭建起来就可以交付,而是可以正式给商家投入使用的。200+ DB 实例,300+ 应用,2000+ 阿里云上的 VM,6000+ service。这些全部要 all in 机房。这样 all in 的话,比如在国外,我们在东亚、东南亚、北美都有机房,如果都是在 VM 上,运维是受不了的。所以我们全部放到了 Openshift 上。之前上 TiDB 集群 1 的时候我们已经做了很多业务类的场景了,本来海外机房构建的时候,我们是准备数据库结构 all in TiDB 的,但是后来某个云厂商,在那个节点我们没有选择,他们没有本地X硬盘,我们方案、测试已经做好了,发现它本地硬盘到不了,我们就又回到了 MySQL。

下图是我们海外机房的网络情况。开始的网络情况很差,响应非常慢,对我们来说一个月就要交付根本不可能实现。但是网络模式又是图中的模式,所以我们对网络进行了优化。我们运用了云企业网。图中大轴之内的 VPC 全部用光纤的方式打通,海外机房通过 VPN 的方式出去,VPN 是利用了云厂商的 VPN 隧道。做完这些以后,费用降低了,稳定性提升了 3 倍以上,延迟,或者说丢包率,降低了 100% 以上。

发布是一个很大的挑战。下图中显示的环境迭代、国内预发布、国内生产发布是最基本的,但是到海外发布的时候,海外成本降下来了,所以海外没有预发布,也没有测试环境,相当于海外只有生产环境。海外的发布这里写的是“以周为单位同步”,但是现在还没有做到这么理想。All In 的发布模式会有什么问题呢?我们 6000+ 个 service 一次 all in 发布过去以后,回归时间需要多长?基本上一个晚上我们做一次 all in 发布,从晚上 10 点到凌晨 6 点都还在测试。

基于这些问题,我们做了一个增量发布的流程。增量发布的流程中,有一部分是可以手动更换的。比如下图中域名配置的步骤。在域名申请的时候,我们就提前把各大机房的域名配好,这一步提前做。在域名指向的时候,海外很方便,国内的域名指向做好了,国外是一样的。在变更的环节,我们要确定好发布范围,把周边配套做好,然后有一个 CI 的操作,包括一些合法性,用户密码的一些问题做好以后直接上国内的预发。上预发之后,网关配置,中间件、配置中心配置,数据库/缓存同时把生产和海外机房做好。这里有很多问题,比如数据库,数据库删字段就不行,我们不允许删字段。如果对数据库有删字段操作,是没法做到自动化的。这个时候海外提前发上去,是不一样的。

然后来到生产环境,搜索和数据中心业务配置这个地方是需要手动的,因为搜索是非常耗费时间的,所以先把这些事情做好。做好以后,我们通过测试,测试通过以后发到生产环境。完成以后进行规则替换。之前碰到的问题我们汇总了一些规则,把这些规则替换了以后,进行 image,海外发布。海外发布完以后有一个自动化测试。我们做了一个拨测系统,把一些核心业务进行拨测,看业务是否正常。不是一个严格意义上的自动化测试,但是这样差不多可以做到增量发布的情况了。

火烧兄大作,必属精品。餐饮 SaaS 通用解决方案。