---
title: 'TiDB in SaaS丨TiDB 在 Moka BI 场景下的应用'
date: '2023-03-21T00:00:00+08:00'
status: publish
permalink: /blog/user-case-moka
author:
    - 陈霜
    - 陈霜
    - 张晓辉
excerpt: '在综合考虑兼容性、稳定性、简介性、高可用、易用性等因素后，Moka BI 选择了 TiDB 作为支撑新架构的数据库，解决了数据壁垒，降低业务复杂度，实现了全面的性能提升。'
type: post
id: 3218
category:
    - 案例实践
tag:
    - SaaS
    - TiDB
post_format: []
profile:
    - 张晓辉
algolia_posts_post_records_count:
    - '6'
---
> 本文作者为 Moka 数据架构师张晓辉

导读
--

Moka 是一家 HR SaaS 服务提供商，致力于通过一流技术和服务赋能企业的人才战略。Moka 的 BI 系统通过数据统计和实时报表等方式，实现了企业招聘和人力资源管理系统的智能化。文章重点介绍了 Moka BI 对其数据库架构的革新，分享了其系统现状及对选型的思考。在综合考虑兼容性、稳定性、简洁性、易用性、高可用等因素后，Moka BI 选择了 TiDB 作为支撑新架构的数据库，解决了数据壁垒，降低业务复杂度，实现了全面的性能提升。

Moka BI 介绍
----------

Moka 是一家致力于为全员带来更好体验的 HR SaaS 服务商，从 2015 年成立到现在已累计获得数十亿元的融资，先后服务小米、万科、太平洋保险等各领域的头部企业，累计服务超 2000 家客户，核心产品智能化招聘管理系统和人力资源管理系统，为中大型企业提供从招聘、入职、薪酬、假勤、绩效等人力资源全模块管理，为企业提供极致体验、数据驱动的 HR SaaS 产品，致力于通过一流技术和服务赋能企业的人才战略。

Moka BI 则通过全方位的数据统计和可灵活配置的实时报表，赋能智能化招聘管理系统和人力资源管理系统，通过 PC 端和移动端的多样报表展示，从而改善招聘业务、提供数据支持、提升招聘竞争力，从而助力科学决策。

![Moka BI.png](https://img1.pingcap.com/prod/Moka_BI_eb503bf078.png)<center>Moka BI</center>Moka BI 的架构主要是类似于 Lambda 架构，实时处理和离线处理并存，实时数据主要来源为结构化的数据，Canal 采集 MySQL 或者 DBLE（基于 MySQL 的分布式中间件） 的 binlog，输出是 Kafka，未建模的数据按照公司进行分片，存储在业务的 DBLE 中，通过 Flink 进行实时建模，将计算后的数据写入 BI DBLE。Doris 定时同步 BI DBLE 的数据，支持数据大屏和实时报表统计，离线部分则涵盖了实时部分的数据，其结构化的数据来源于建模后的 BI DBLE 数据，明细数据存储在 HBase 中，并进行实时更新，映射成 Hive 表，非结构化的数据通过 ETL 流程存储至 Hive 中，并通过 Spark 进行计算、建模，离线数仓 ADS 层的数据，最终输出至 MySQL Redis 中，支撑离线报表统计，明细数据又支持招聘预测和搜索等外部应用。

![Moka BI 系统架构.png](https://img1.pingcap.com/prod/Moka_BI_170deb8bfd.png)<center>BI 系统架构</center>基于 BI 整体架构，接下来看实时数据的走向和现状。首先实时数仓都是基于模型配置在 BI DBLE 中进行实时建模，BI DBLE 中的数据也是按照公司 ID 进行分库，建模后的数据通过 Canal 再次写入 Kafka，此时会有两个 Flink 程序消费该 Kafka 的数据，考虑到 Doris 的实时写入性能，Flink 会进行窗口数据合并，然后 VP 将数据写入到 Doris 中，同时另一个 Flink 程序也会将数据合并，微批写入到 HBase 中。

现状与问题
-----

当前架构的问题也很明显，首先就是在实时建模的过程中，因为单一公司都在一个 shard 上，在大流量下会触发单点瓶颈，从而导致消费延迟。其次在 DBLE、Doris、Hive 数据是大量冗余存储的，造成了数据壁垒。此外，整个数据链路很长，要保证 DBLE、Doris、Hive 的数据都是一致的，数据治理难度非常大，针对上述问题，我们进行了数据库的调研选型。

![Moka 使用 TiDB 前的问题.png](https://img1.pingcap.com/prod/Moka_Ti_DB_72e827202f.png)调研目标
----

我们制定了五个方向的调研目标，一期需要满足一到三项。第一个目标是兼容性，数据库要兼容 MySQL 的协议和生态，其次要兼容 Canal 格式的数据变更，还要兼容不同的云环境。第二是离散性，数据库要尽可能避免单点性能瓶颈。第三是服务的稳定性，首先是集群稳定性要高，并且支持多种容灾级别，在发生灾难时，故障响应时间要小于 30 秒，且在故障恢复后不能有数据延迟或者数据丢失。第四是易用性，我们希望数据库集群的维护成本低，并且便于扩缩容。最后的目标是简洁性，首先要简化数据存储，更进一步是最好能简化整个数据架构。

![Moka 数据库调研目标.png](https://img1.pingcap.com/prod/Moka_3ef4f094f6.png)选型对比
----

针对上述目标我们进行了一系列的调研选型，首先想到的就是 Phoenix on HBase，它的优势很明确，不需要引入额外的存储引擎，所以不涉及到数据的导入导出。它的劣势是在实时领域下，复杂的查询要基于大量的二级索引，索引维护成本比较大，且数据变更要基于协处理器，成本很高。接着，我们又调研了比较流行的 Hudi，它的优势就是整体的架构不需要大的变化，并且实时的数据能够实时入仓入湖，但是在实时存查的情况下会存在写延迟或者读延迟，且数据变更没有办法捕获到下游。

紧接着我们又调研了 PolarDB，它的优势就是对 MySQL 的兼容性比较好，完美兼容 MySQL 的生态和协议，且迁移成本很低，支持一体化的 HTAP，且没有单点性能，看似很满足我们的调研需求，实际上它有一个很大的劣势就是没办法满足不同的云环境运行，因此也不符合本次的调研目标。

![Moka 数据库选型对比.png](https://img1.pingcap.com/prod/Moka_ca61e3912e.png)为什么选择 TiDB
----------

我们最终把目光瞄准了 TiDB，并进行了深度测试，为什么选择 TiDB ？TiDB 完美兼容 MySQL 协议和生态，并且 TiCDC 支持 Canal、Maxwell 等协议，无缝衔接了数据下游，并且支持在多云环境部署。其次，TiDB 带来了性能的提升，TiDB 是 Shared Nothing 架构设计，避免了数据热点，不会形成单点瓶颈，理论上性能会随着节点的无限扩展而没有上限。第三，TiDB 满足金融级高可用，多副本存储和 Multi-Raft 协议同步事务日志，支持多种容灾级别。第四，TiDB 的维护简单，基于 TiUP 一键扩缩容，且扩缩容的过程业务无感知，并且支持实时在线的 DDL。最后，TiDB 具备实时 HTAP 的能力，TiKV 行存支持 OLTP 场景的负载，TiFlash 列存与行存强一致，使用 TiFlash 和 TiSpark 可以满足大部分的 OLAP 场景需求。

![Moka 选择 TiDB 的原因.png](https://img1.pingcap.com/prod/Moka_Ti_DB_58ec6a01b0.png)系统可行性测试
-------

在理论上都满足之后我们进行了系统的可行性测试，安装部署了 5.4.0 版本的 TiDB 集群，集群安装部署完毕之后进行了数据导入。为了真实模拟线上的业务场景，我们同步了一个业务线的全部数据，大概有 200 多张表，有 50 张表数据超过一亿，单表最大数据量为 30 亿行。实时数据则根据 Flink 同步 binlog 实时读写 TiDB 进行建模。我们的测试主要分为三个用例，第一个用例是单 SQL 串行看平均的响应 RT。同样是用 100 万的 SQL，左边绿色的是 DBLE 的响应时间，右边蓝色的是 TiDB 的响应时间，在简单查询的用例下，DBLE 的平均响应时间为 1.2 毫秒，而 TiDB 为 2.4 毫秒，复杂查询场景下 DBLE 的平均响应时间为 8.7 毫秒，TiDB 为 5.2 毫秒。关联查询下 DBLE 的平均响应时间为 20 毫秒，而 TiDB 为 8.7 毫秒。

![Moka 对 TiDB 的可行性测试.png](https://img1.pingcap.com/prod/Moka_Ti_DB_6caedf9a53.png)第二个用例是并发查询，我们用了 200 个并行度，同样是 100 万的 SQL，简单查询下 DBLE 的平均响应时间为 2.5 毫秒，TiDB 为 3.2 毫秒。复杂查询下 DBLE 的平均响应时间为 12.7 毫秒，TiDB 为 7.8 毫秒，关联查询下 DBLE 的平均响应时间为 30 毫秒，TiDB 则在 13.6 毫秒。可以看到单 SQL 串行和并发查询两个用例，在复杂查询和关联查询场景下 TiDB 的平均相应时间明显优于 DBLE。

第三个用例就是在 200 个并行度下看 QPS 的峰值，首先是单公司场景下，DBLE 的 QPS 峰值在 4K 左右，而 TiDB 达到了 24K，是 DBLE 的六倍之多。多公司场景下，DBLE 峰值为 20K，TiDB 为 80K，是 DBLE 的四倍之多。并且在以上两个场景中，TiDB 的负载未出现过高的现象，理论上未达到 QPS 峰值。在以上测试验证中，TiDB 的表现是完全符合预期的，因此我们决定使用 TiDB 替换 DBLE。

实践调优
----

我们在迁移过程中也进行了一些适配性的调优，首先是主键表，我们把主键表改为公司 ID+ID 联合主键，并增加了 SHARD ROW ID BITS 和 PRE SPLIT REGIONS 配置，避免了数据写热点的问题。其次 Flink 实时程序会增加雪花 ID 算法，兼容历史数据。为了和 TiCDC 适配，我们也升级了不同云环境下的 Kafka 版本。循环读写的场景在未关闭异步提交配置时，会频繁出现锁冲突的问题，在关闭后虽然会有 7% 的性能损失，但是能有效避免锁冲突的问题，所以我们把异步提交的配置关闭了。此外，TiDB 对大小写敏感，该配置只支持在集群初始化时配置，大家留意一下。

在适配以外，我们针对 TiDB 还做了一些优化工作，我们把 TiDB 的版本从 5.4.0 升级到 5.4.2，解决了 CDC 捕获特殊符号频繁重启的问题。我们把新增表的 ID 都改为 AUTO RANDOM，这样避免产生热点 ID。TiCDC 我们增加了对应 Kafka 的相关配置，保证了更新顺序及数据可靠性。在索引优化方面，所有的索引都添加了联合的索引，就是公司 ID 加原来的主键 ID。

实践成果
----

![Moka 应用 TiDB 的实践成果.png](https://img1.pingcap.com/prod/Moka_Ti_DB_5dacca4bb8.png)在做了上述适配性调优后，目前 TiDB 的性能得到一定的提升，真实日均 QPS 5K+，高峰稳定在 3w，读写比接近 1:1，性能的提升保证了无延迟的进行实时建模，并且强一致性的多副本提供了服务的稳定性。在 TiDB 线上运行期间有一个节点出现了特殊问题导致宕机，TiDB 在 10 秒内会自动进行恢复，没有影响到线上业务。TiDB 的升级运维也是业务无感知的，我们在迁移人力资源管理系统时，扩容了三个 TiKV 存储节点，在扩容期间对线上业务没有任何影响的。其次，TiDB 还解决了数据壁垒问题，之前两个系统存储的数据是独立的，没办法做一体化的数据访问，目前我们基于 TiDB 的统一存储形成了初级数据湖的使用模式。

总结与展望
-----

![Moka 应用 TiDB 的总结与展望.png](https://img1.pingcap.com/prod/Moka_Ti_DB_1b4287f8f2.png)最后谈谈我们对 TiDB 的总结和展望，从 2022 年 7 月开始进行开发和测试，目前 TiDB 的 OLTP 部分已经完成了 Moka BI 全业务线的投产，在多云环境下替换了 DBLE，目前服务稳定可靠，未出现性能瓶颈，圆满达成了 2022 年下半年的目标。

随着对 TiDB 的使用深入，我们越发地认识到 TiDB 和我们的业务场景是高度匹配的，面向后续 TiDB 的使用我们制定了以下的计划：首先在 2023 年要做到两个统一，第一个统一就是统一数据存储，使用 TiSpark+TiKV 替换现有的 Hive、HBase 和离线数仓；其次我们要深度调研 TiFlash，争取使用 TiDB HTAP 能力支撑 OLTP+OLAP 的统一查询场景，减少数据架构的复杂性，从而降低数据治理的困难性。在两个统一的基础上，我们要建立公司级统一的查询平台，支撑业务部门进行复杂查询，持续提供数据输出能力。