“牛板金”是浙江佐助金融信息服务有限公司旗下综合性互联网理财服务平台,总部位于杭州。牛板金致力于为投资者提供安全、专业、便捷、高效的创新性互联网理财服务,降低投资者的投资门槛,多渠道增加居民财产性收入;支持中小微企业发展,助力实体经济,实现真正意义的“普惠金融”。
截至目前,牛板金已有注册用户接近 80 万人,累计投资金额超过 200 亿元。
在牛板金中,我们的用户最喜欢的一件事就是打开 App,然后进行签到获取积分,再拿积分兑换加息券来获得更多的收益。正因为此,在整个牛板金营销平台的后台数据库中负责记录用户积分信息的表(积分流水表)增长的比我们想象的要快很多,不到一年就已经超过 5000 万,而且增速越来越快,不得不开始对其开始优化。
一开始我们我们调研了很多相关的数据库分布式中间件产品,包括 TDDL、Cobar、MyCAT、Sharding-JDBC。当时通过一定的考量后,我们选用了 MyCAT 作为分库分表方案,按照时间维度对表进行了拆分。然而实际线上运行过程中,还是遇到了很多问题,大致有以下几种:
MyCAT 运行不够稳定且高可用机制欠佳,有两次比较严重的宕机导致我们线上服务的部分不可用;
主键冲突,采用 MySQL 单表的自增主键,导致多表扫描合并结果集再排序出现不同顺序的情况;
自增主键,由于采用了 MyCAT 的自增主键方式,导致线上线下必须全部采用 MyCAT 环境,增加了运维复杂度;
按月度分表,没有解决单表热点问题,现在单表又已经突破千万,存在需要再次修改分库分表策略的问题;
另外考虑到 MyCAT 的集群扩容机制不够完善,扩容操作比较困难且会对业务可用性产生影响。
因此我们决定寻找是否有更优的解决方案,能够一劳永逸的解决这个问题,这时候 TiDB 再次进入我们的视野,当时 TiDB 刚刚发布了 RC4 版本。在经过一轮详细的测试后,我们发现 TiDB 在数据量不断增长后优势还是很明显的,不管对比单机 MySQL 还是 MyCAT,主要优势有以下几点:
高度兼容 MySQL 协议,数据分布式存取模式对业务开发透明,开发人员无需过多关注其本身;
弹性扩容,使用官方 TiDB-Ansible 工具可在线对相应节点进行扩容;
OLTP,满足数据强一致性需求;
技术支持,PingCAP 的技术支持团队响应很快,能够第一时间解答我们的问题。
我们开始测试 TiDB,并与 MySQL + MyCAT 传统分库分表中间件方式做了调研比较。
下面是我们调研比较后一些结论和心得:
TiDB 不需要像 MySQL + MyCAT 关心后台数据分片规则设计和存储,对于业务开发工作量和工作难度的降低有很大的帮助。业务代码的灵活性和可维护性也大幅提高了。
TiDB 的性能提升基本是线性的,横向扩展能力比较强;受制于 MyCAT 自身的性能限制,MySQL + MyCAT 的性能无法做到线性提升,这点对我们高速增长的业务发展趋势来说是特别看重的。
MySQL + MyCAT 的高可用虽然可以通过一些第三方组件和配置完成,但是总体的可靠性可用性不能满足我们金融企业的安全要求; TiDB 是一个没有单点的高可用架构,已经具备了完整的高可用保障机制,无需我们耗费额外的精力去规划和考虑。
我们对 TiDB 和 MySQL + MyCAT 的性能也做了评测,在大数据量(千万到亿单表记录数)的规模下,TiDB 几乎不需要太多的配置优化就能很好的完成数据处理,MySQL + MyCAT 则需要人为调整一堆参数,反复调试;性能上 TiDB 有不俗的表现,我们经过测试,在多表和上述单表大规模数据量规模下,TiDB (当时测试的是 RC4 版本) 相比 MySQL + MyCAT 在性能上至少有 1.5 倍到 2 倍的优势,如果进一步优化的话,两者的差距还有可能更大。
我们还关注了性能压力测试过程中的稳定性表现。TiDB 的吞吐量和延迟指标的变化随负载请求压力增加变化稳定,MySQL + MyCAT 的性能波动比较大,这个结果对我们的金融业务是否能够稳定在线开展服务非常重要。
在我们决定迁移 TiDB 后,一个最大的问题就来了,如何在保证数据一致性的前提下更快的将数据迁移同步到 TiDB 集群,这时候我们联系了 PingCAP 官方,他们给我们提供了一个很好的解决方案。
最终我们采用的同步方案是 Loader + Syncer,具体方案如下:
使用 Mydumper + TiDB Loader 全量导出 MySQL 库中数据,并记录 SavePoint,然后导入 TiDB。 使用 TiDB Syncer 做实时增量同步,将 MySQL 中数据同步到 TiDB。
将 MyCAT 中按月拆分的表通过 ETL 以无主键的形式导回 MySQL 单表( MyCAT 分表中存在主键重复,不能单纯直接导入 TiDB,并且当时 TiDB 对于 ETL 工具的支持还未完善,无法使用 ETL 工具导入 TiDB ),只保留当前月份数据不导入。
将重新整合后的 MySQL 单表数据通过 Mydumper + TiDB Loader 导入 TiDB。
待上线当天晚上,将当前月份数据导回 MySQL (重建主键),再通过 Mydumper + TiDB Loader 导入 TiDB。
这个方案虽然复杂但能将迁移的时间缩减到最短。
在测试的过程中我们发现,TiDB 在进行一些复杂的强 OLAP 查询时会导致整个集群处于 busy 状态,进而影响到 OLTP 业务,通过和 PingCAP 技术团队沟通,TiDB 官方的建议是,对于一个集群存在混合业务的场景:
对于不同类型的业务,可以通过不同的 TiDB-Server 作为入口,在计算层面做隔离;
另外不同的业务可以通过不同的隔离级别(比如 OLAP 业务使用 RC 隔离级别)、设置语句优先级( OLAP 请求设置为低优先级)以及控制执行并发度等方式进行资源使用优化。
我们最后决定采用主从集群模式,通过搭建一组 TiDB 从集群,采用 TiDB Binlog 对主从集群进行同步,这样 Master 集群负责 OLTP 业务,而 Slave 集群负责 OLAP 业务,两者之间就没有相互影响,而且通过实测,TiDB Binlog 的同步延迟大概在秒级,对于我们的 OLTP 业务没有影响。两套集群的配置大致一样,Slave 集群只比 Master 集群少一台 TiDB 角色。
最终,完成生产上的 TiDB 主从两套集群的部署和投产。架构如下:
数据库集群总体配置如下:2TiDB、3TiKV、3*PD。
到目前为止,TiDB 稳定运行近半年,随着牛板金业务规模的逐渐放量,数据库数据处理能力稳定提升。
该系统主要是对我们系统的所有请求流量进行存储以便后期进行分析。由于数据量将会非常大,因此从一开始我们就规划使用 TiDB,这样就可以使用传统的 SQL 来进行分析查询。我们还了解到 PingCAP 的另一个项目 TiSpark,也是很适合在我们这个场景使用,下一步就是规划部署 TiSpark 集群。
对于请求的采集形式,我们是采用在网关层增加一个 Filter 的形式,将请求的相关参数进行采集然后通过消息队列将 message 发送到 MQ,然后通过请求分析处理系统从 MQ 中拉取消息,最后落库。现在只对 App 端的流量做了处理,每天的数据量大约在 1000 万左右。
对于这些数据的分析,大致计划有以下几方面:
访问情况的统计报表;
安全分析,构建安全防范策略;
全链路压力测试,这些是天然的请求源数据。
通过 TiDB 的在混合负载方面的能力,可以接受海量采集数据的不断写入,同时能够实时的提供分析、统计及计算。在运维方面也不用担心快速膨胀的数据对容量管理和扩容操作带来的繁琐和麻烦。TiDB 提供的 ansible 方式的管理可以提供方面的一键扩容操作。目前我们计划在 2018 年春节后上线该项目。
实践中我们认识到,由于 TiDB 是一个分布式数据库,不可避免的会有网络开销,尤其是对于小表,这个影响会被成倍放大,如果 TiDB 能够对小数据量的表进行特殊优化,让其性能能够接近单机数据库,那对于 TiDB 的使用场景可能会更多,毕竟一个系统中的表不只是拥有海量数据的表,而且也不一定能够采用多数据源的方式来进行修改调整。
2018 开年后,和 TiDB 开发团队沟通此问题,他们表示正在着手解决这个问题,目前在尝试通过 TiKV 端引入 Query Cache 来加速频繁查询,对小表以及聚合类查询的响应速度会有很好的提升,对此我们非常期待。
作者介绍:沈晨波 佐助金融 资深架构师