TiDB 在平安核心系统的引入及应用

做者:何志勇
本文转载自公众号「平安科技数据库产品团队」。mysql

2019 年 5 月 9 日,平安科技数据库产品资深工程师何志勇在第十届数据库技术大会 DTCC 上分享了《TiDB 在平安核心系统的引入及应用》,经过对 TiDB 进行 POC 测试,详细解析如何选择适用于金融行业级别的开源分布式数据库,以及平安“财神节”活动中引入 TiDB 的全流程应用实践案例分享。本文根据演讲内容整理。

<center>何志勇 平安科技数据库产品团队 资深工程师</center>redis

1、TiDB 引入的 POC 测试

做为一名运维人员,引入一个新的数据库产品前必需要明确几点:spring

  • 从业务的角度,引入的产品可否知足业务基本需求和使用场景。
  • 从运维管理角度看,这产品必须是可运维、可管理的,而且咱们须要对其相应的功能与特性,要有一个很好的了解。
  • 产品性能稳定。

因此在咱们引入前从如下六个方面分别对 TiDB 进行测试验证,其中功能与架构、配置与管理、备份与恢复都是针对咱们运维管理,SQL 特性、基准测试、应用场景测试则是应对业务需求和业务场景的。sql

1. 功能与架构

TiDB 事务隔级别为 SI,支持 Spark 生态,支持动态扩容,跨数据中心部署。数据库

这是 TiDB 官网最新的架构图:编程

从左至右看,能够经过 MySQL 或 MySQL 客户端接入 TiDB,TiDB 有 TiDB、PD、TiKV 三个组件,组件之间功能相互独立,需独立部署,分别负责计算、调度、存储功能;同时又相互协做,共同完成用户请求处理。在 TiKV 层各节点是使用 Raft 协议保证节点间数据的一致性,同时它还提供 Spark 接口供大数据分析。 服务器

从上往下看,可经过 Data Miaration 工具从 MySQL 迁移到 TiDB,同时提供备份恢复功能、内部性能监控监测及诊断、支持容器化部署。多线程

TiDB 从架构及生态上基本上具有了传统数据库应有的功能。架构

2. SQL 特性

兼容 mysql 语法,2.0 版本不支持窗口函数、分区表、视图、trigger 等。并发

3. 配置与管理

支持在线 DDL,2.0 只支持串行的 DDL、不支持并发,在优化器上支持 RBO 与 CBO,能对单会话进行管理,能够支持复杂的 SQL。

4. 备份与恢复

备份恢复工具均为开源,支持多线程备份恢复,当前版本不支持物理备份,loader 恢复时间偏长。

5. 基准测试

TiDB 在单条 SQL 的性能较好,高并发场景下性能较稳定,但 DML 事务大小有限制。

6. 应用场景测试

支持标量子查询,能支持很是复杂的查询,查询引擎可朔性强。

这个应用场景是咱们的产险的实际分析场景,表数据量不大可是 SQL 较为复杂,是典型的星型查询。在 Oracle 用了 134 秒,可是 TiDB 用了 50 分钟,咱们以为很诧异,与 TiDB 的同事咨询后,他们经过现场支持咱们优化底层代码后 34 秒能够跑出来。

2、“财神节”活动中 TiDB 的应用实战

“财神节”是中国平安综合性年度线上金融狂欢节。2019 年平安集团“财神节”活动于 1 月 8 日正式启动,涉及寿险、产险、银行、养老险、健康险、普惠、证券、基金、健康互联、陆金所、壹钱包、互娱、不动产等多个领域,活动参与的 BU 数量与推广的力度是历年之最。单日成交额超过 1000 亿,在单日交易额破千亿背后是几百个后台数据库实例的运维保障。

咱们看下活动业务场景的特色:

  • 参与门槛低:暖宝保这个业务保费价格低至 19.9,因此人人均可以参与。
  • 咱们的推广力度很大:以微服务的方式对接如平安健康、好福利、平安银行、陆金所等全部 APP 端,同时配合各类合做伙伴的宣传。
  • 典型的互联网活动形式如秒杀、红包雨,因此对数据库的要求是高并发、低延迟、高响应、高可用,2-5 年在线数据存储量预计达到 20~50TB,而这些只是预估,有可能远远大于以上评估值。

平安在用的开源数据库有不少,那在这么多数据库中,咱们选择什么数据库呢?

综合对比考量最终咱们选择 TiDB,在选择的同时也面临着挑战:

  • 时间紧迫

    2018 年 12 月 17 日~2019 年 1 月 7 日,20 天时间内完成开发测试到生产上线,时间短,风险大

  • 开发零使用经验

    现有开发大都是基于传统 Oracle 保险业务,对于 TiDB 没有使用经验

  • 并发量与扩容

    互联网业务并发需求前期不可彻底需求,前期不能很好的以实际压力进行测试,与资源准备

  • DB 运维管理

TiDB 还处于生产落地阶段,一类系统还没有使用过 TiDB,没有大规模应用运维经验

基于以上挑战,咱们在 9 台 PC 服务器上作了验证测试,测试工具是 jmeter,TiKV 节点数咱们是逐步增长的,具体的测试过程以下:

总结一下,就是:

  • TiDB 吞吐:在 select 中即 point select,TiDB 的吞吐比较好。
  • 弹性扩容:在 insert 场景下随着节点数的增长,TPS 也会相应的增长,每增长 3 个节点 TPS 可提高 12%~20% 左右,同时在相同 TiKV 节点数下,TPS 与响应时间,此消彼长。
  • 批量提交性能尤佳:业务中一个保单须要同时写 7 个表,7 个表同时 commit 比单表 commit TPS 高,相同 TPS 场景下延迟更小。
  • 初始化 region 分裂耗时长:因在测试时没有预热数据(表为空表),对空表写入前几分钟,响应时间会比较大,约 5~8 分钟后响应时间趋于稳定。在前几分钟内响应时间大,是由于每一个表初始化完都是一个 region,大量 insert 进来后须要进行分裂,消耗时间比较大。
  • Raftstore cpu 高问题:因为 Raftstore 仍是单线程,测试中从监控指标看到 CPU 达到瓶颈是raftrestore 线程。
  • TiKV 性能中的“木桶原理”:TiKV 中一个节点的写入性能变慢会影响到整个集群的 TPS 与响应时间。

上线时咱们作了如下两方面改善:

1. 优化表的定义与索引

表定义:不使用自增加列(自增加的 rowid)做为主键,避免大量 INSERT 时把数据集中写入单个 Region,形成写入热点。

索引:使用有实际含义的列做为主键,同时减小表没必要要的索引,以加快写入的速度。

2. 对表的 region 进行强制分裂

查找表对应的 region:curl http://$tidb_ip:$status_port /tables/$schema/$table_name/regions

使用 pd-ctl 工具 split 对应表的 region:operator add split-region $region_id

打散表的隐式 id,打散表的数据分布:alter table $table_name shard_row_id_bits=6;

咱们使用了 25 台机器,后面还临时准备了 10 台机器去应对高并发的不时之需。

在使用过程当中遇到以下问题:

(1) 2.0.10 版本下 in 不能下推到表过渡问题

你们看到咱们两个相同的表结构,同时写入一些数据,在两个表进行关联的时候,发现过滤条件 t1.id=1 时,上面那个执行计划能够下推到两个表进行过滤,两个表能够彻底精准的把数据取出来,可是下面把等号后改为 in 的时候,对 t2 表进行全表扫描,若是 t2 表数据量很大时就会很慢,这是 TiDB 的一个 bug,解决方案就是不要用 in,在 2.1 版本修复了这个 bug。

(2) 2.0.10 下时区设置致使客户端不能连

咱们在跑命令的时候没有问题,而且结果是能够的,可是跑完后就断掉了,从后台看也是有问题的,重启 TiDB 组件也不行,后来找到代码咱们发现这是一个 bug。

缘由:这个 bug 会在你链接时 check 这个时区,致使用户不能链接。

解决办法:咱们找研发同事从新编译一个 tidb-server 登入服务器,把时区设置为正确的,而后使用最初的 TiDB 组件登陆,2.1 版本后这个 bug 修复。

(3) Spring 框架下 TiDB 事务

image

这个问题是比较重要的问题,有个产品须要生成一个惟一的保单号,业务是批量生成的,当时在 TiDB 中咱们建了一个表,表中只有一条数据,可是咱们发现会有重复保单号出来。

缘由:TiDB 使用乐观事务模型,在高并发执行 Update 语句对同一条记录更新时,不一样事务拿的版本值多是相同的,因为不一样事务只有在提交时,才会检查冲突,而不是像 Oracle、MySQL、PG 那样,使用锁机制来实现对一记录的串行化更改。

解决办法:Spring 开发框架下,对事务的管理是使用注解式的,没法捕获到 TiDB commit 时的返回状态。所以须要将 spring 注解式事务改为编程式事务,并对 commit 状态进行捕获,根据状态来决定是重试机制,具体步骤:

  • 利用 redis 实现分布式锁,执行 SQL。
  • 捕获事务 commit 状态,并判断更新成功仍是失败:

    • 失败:影响行数为 0 || 影响行数为 1 && commit 时出现异常。
    • 成功:影响行数为 1 && commit 时无异常。

相关文章
相关标签/搜索