TiDB_Robot
作者TiDB_Robot·2020-06-01 14:56
数据库研发工程师·PingCAP

聊聊数据库的未来,写在 PingCAP 成立五周年之际

字数 4904阅读 708评论 0赞 0
作者:邹建伟,北京开科唯识技术有限公司 技术专家。

一、互联网理财的兴起

在经济和科技飞速发展的趋势下,相比于以前传统的线下理财模式,互联网理财的模式,因其入围门槛相对较低,选择范围广,加上随时随地用电脑或者手机就能够进行理财,导致便捷性和灵活性的提升,从而让越来越的人们开始接受理财、乐于理财,理财的意识和投入的形态也越来越多。但随着监管制度的管控、用户规模、渠道规模、业务形态、高并发业务请求的不断增长和变化,传统的理财 IT 基础设施建设已经无法满足用户的使用体验,基于分布式系统建设新的业务系统必将破浪前行。

这次我们在中国某大型股份制银行—— G 行的互联网理财系统建设中,也是采用了分布式的数据库系统来取代传统 Oracle 数据库系统,在使用分布式数据库 TiDB 时,遇到了新技术适配的一些问题,通过迁移、开发改造和联调优化,积累了互联网理财场景中的一些分布式数据库 TiDB 的经验。本篇文章分享下在建设中遇到的问题和最终的解决方案,希望对所有准备建设和正在建设互联网理财系统的的用户有所帮助。

二、互联网理财业务简介

互联网理财最早于 2003 年就已经开展业务,主要承载基金代销、理财销售等线上业务,2018 年 4 月随着“资管新规”的发布,银行理财产品起售点由 5 万下调至 1 万,大大促进了银行资管理财业务的发展,更加激发了客户购买理财产品的热情,部分明星热销产品,更是吸引了大量客户集中抢购。G 行互联网理财系统主要涉及两大类业务场景:

  • 联机交易场景 :处理开户申请请求,对单笔交易的响应时间有较高的要求;
  • 批量任务场景 :处理理财批量业务,属于计算密集型的工作,对数据库大数据量下的吞吐能力要求较高。

2.1 业务功能拓扑

互联网理财系统主要包含文件传输、实时开户、交易确认、份额登记、收益结转、产品管理、产品运营等功能,拓扑图如下:

业务对数据库处理能力提出了明确的技术指标要求:

  • 批量任务:要求数据库提供在 2h 内对 5000w 笔交易记录,能够跑完夜间批量任务的能力。
  • 联机任务:要求数据库提供事务平均响应延时不超过 100ms 的能力。

2.2 数据存储拓扑

TiDB 同城两中心

TiDB 同城两中心

<center>同城两中心<center>

整套集群服务器使用接近 30 台物理服务器,每台物理服务器均配置 4 块 NVMe 盘、2 个万兆网卡、2 个千兆网卡、72vcore、512G 内存,预期可以保留 3 个月的在线数据。

三、选型之路

3.1 背景与依据

在传统理财业务系统使用集中式的 IOE 架构,原有传统数据库 Oracle 数据库遇到支撑的瓶颈,已无法适应互联网+理财业务模式的发展需求, 取而代之的是通过开源自主可控、分布式数据库的技术方案来支撑当下的互联网技术模式的系统建设,现有 Oracle 主要遇到亟待解决的的问题如下:

  1. 容量上限不能扩展 (存不下、查不出来,索引优化已没有用)。
  2. 分布式改造和适配如何取舍。

在当前分布式数据库解决方案领域内,可以聚焦的数据库选择范围就剩下分库分表方案 和 NewSQL 原生分布式方案(顺带的说明下,这里我们不争论分库分表究竟算不算分布式架构,我们相信技术是为场景存在的)。选型我们主要考虑三点:首先是数据库功能,例如括高可用性、SQL 兼容、横向扩展、扩容等等;其次是技术架构的前瞻性、发展潜力、社区活跃度;最后是大数据量下的数据库性能最为看重。前期我们与候选的数据库厂家的工程师合作模拟了 daemon 业务程序,来验证数据库的性能,主要两个部分内容:

  1. 数据初始化能力

来自互联网渠道的理财数据,预估每小时至少千万级别,在 1 个小时内我们有一系列的批量任务,留给数据库入库的时间最多 10 分钟。

  1. 业务性能测试

理财业务具有多任务并存的特点,大方向说包括联机交易任务和跑批任务两部分,跑批任务包括日间任务和夜间任务以及数仓 edw 任务。联机任务要求事务平均响应延时不超过 100ms,批量任务即使并存时也不可以超过总体执行时间。

经过多轮的测试、评审,分库分表对业务设计上的不解决够优雅,由于拆分字段的规则限制了业务实现的一些方式,不能灵活进行业务处理,并且在批量的复杂逻辑SQL 处理上性能无法满足业务要求,最终我们选择 TiDB 来进行分布式数据库的建设。验证下来,完全满足业务数据初始化效率、提升联机交易和批量处理响应能力、缩短批量处理时间周期,而且也无需限制业务场景的处理逻辑,根据压力需求灵活的进行在线扩展和在线收缩。上线前的非功能测试中,联机交易部分:在并发用户 30 下,数据库处理能力为 536 笔/s,响应时间为 0.0558s,满足预期 200TPS。批量入库:64 并发下,5kw 数据入库 9.7min,当然这并非极限值。

3.2 TiDB 的特性优势

水平弹性扩展

这里说的水平扩展包括两方面:计算能力和存储能力。TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐。TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据 Scale 的问题。

高可用

TiDB 集群核心三大组件:TiDB/TiKV/PD 都能容忍部分实例失效,不影响整个集群的可用性。TiDB 本身是无状态的,支持动态的增加删除。TiKV/PD 采用 Raft 协议,在大多数存活的前提集群便是可用的。

数据强一致

TiDB 的分布式算法使用 Raft,其事务可以跨分片、跨节点执行,并且强一致。

生态强大

这个特点应该毋庸置疑,说是“风口的猪”也不过分。TiDB 分布式数据库从 2015 年 4 月份开源以来,有来自社区的开发者、用户、布道师、设计师等不同角色的贡献者们的细心呵护,也有来自 PingCAP 持续不断的资源投入,截止到 2020 年 3 月,TiDB 社区项目已经聚集了来自全球的 760 多位 Contributor,100 多位核心用户,30000+ GitHub Stars 支持,TiDB 现已被近 1000 家不同行业的领先企业应用在实际生产环境。TiDB 详细的架构和原理可以参照官网(不再赘述)

四、开发改造中的思考&问题

G 行采用的 TiDB 版本是 3.0 早期版本,仅提供乐观锁机制, 这个问题在 TiDB 3.0.8 后引入了悲观锁后得到了解决。作为一名“重度”悲观锁使用者,TiDB的乐观锁是我刚开始接触 TiDB,所认为的开发改造过程中最大“阻碍”。但实际开发过程中,这里的碰到的问题其实很少,更多是认知理解的过程。整个改造过程中主要遇到了以下几个方面的问题,也都通过 TiDB 提供的最佳开发实践获得了很好的处理效果。

问题 1:热点账户更新

select for update 语句是悲观锁机制下热点账户更新场景常被利用的机制,Oracle 数据库中,这个语句的作用是:

The FOR UPDATE clause lets you lock the selected rows so that other users cannot lock or update the rows until you end your transaction.

也就是说利用它可以实现数据行的锁定,阻塞其它事务对该行数据的 DML 操作。TiDB 也支持这个语句,不过在乐观锁机制下,这个语句不会在事务开启就锁住数据,而是其他事务在提交的时候进行冲突检查,如有冲突,会进行回滚。

问题 2:Rows Affected 不可信

悲观锁机制下,显式事务每条 DML 语句执行完成后数据库会返回影响行数:affect rows,业务会利用 affect rows 实际值不同进行不同的逻辑处理,这个是没问题的。不过 TiDB 乐观锁机制,显示事务每条 SQL 执行完成后返回的 affect rows 是不可信,究其根本原因,悲观锁是先加锁再更新,而乐观锁机制下,行冲突检测和数据上锁是放在事务提交时检测的,这里举一个例子:

对于事务 B 来说,update 语句执行后数据库返回 1 row affected,不过显而易见,这个语句提交时并没有发生更新,也即此时的 Affected rows 是不可信的。如果业务还希望使用 affected rows 来做程序执行逻辑的判断条件,可行的方式是:显示事务下,先判断事务成功的条件,然后再根据 affected rows 进行逻辑处理。而隐示事务下,可以直接使用 affected rows 进行逻辑处理。

问题 3:大事务

熟悉 MySQL 的同学会对事务大小设计比较熟悉,开发规范中会尽可能拆分大事务为多个小事务。TiDB 对大事务也有类似的要求,并给出了限定具体限定标准:

  • 每个事务内的 SQL 数量不超过 5000 条(可配置)。
  • 每个键值对不超过 6MB。
  • 键值对的总大小不超过 100MB。
  • 键值对的总数不超过 300,000。

开发使用过程中,体会最多的限制是键值对的总数不超过 300,000,老系统稍不注意就超出了这个限制,造成处理失败。这里要着重说明,键值对数与行数不等价。举例说明:一行数据是一个键值对,一行索引也是一个键值对,当一张表只有 9 个索引时,每 insert 一行数据会写入 10 个键值对。这里的原因涉及到 TiKV 使用的存储格式,感兴趣的同学可以搜索 TiDB 相关文章进一步阅读。

问题 4:WRITE CONFLICT

WRITE CONFLICT 是开发中碰到的频率最多的问题之一,报错示例信息:


Err:[kv:9007]Write conflict, txnStartTS=411771139330670593, conflictStartTS=411754809751764993, conflictCommitTS=0, key={tableID=698, handle=391317290} primary={tableID=698, indexID=5, indexValues={0, 391317246, }} [try again later], ErrCount:313, SnapshotVersion:411752587989614594

问题的成因这里不赘述,感兴趣的同学可以搜索相关文档查看。TiDB 默认针对这个错误不会进行事务重试,由参数 tidb_disable_txn_auto_retry 控制,3.0 版本默认值是 1,而在更早的 2.1 版本里没有这个参数,默认行为是会自动重试,默认值更改的原因是优化事务处理逻辑,适应更多场景。

五、总结

目前互联网理财业务系统稳定的运行在 TiDB 3.0 版本乐观锁下,TiDB 4.0 马上要 GA 了,我们当初能赶上基于 4.0 的改造该有多好啊,据说 4.0 版本有了更多的新特性

,让后续迁移到 TiDB 数据库的同学会更加的通用、易用。比如:

4.0 有了大事务

对于开发人员说,TiDB 4.0 以前事务的限制始终有点「达摩克利斯之剑」的意味,总是担心一个不留心就撞墙。4.0 版本开始,对事务的限制松绑很多,键值对的总大小允许 10GB 以内。

有了悲观锁

相比大事务带来的别扭,悲观锁个人觉得是最期待的特性。最早在 TiDB 3.0.8 版本引入,4.0 版本开始默认开启悲观锁。悲观事务模型是对于金融场景非常重要的一个特性,有了悲观锁我相信 TiDB 才会走的更高更远。

新特性很期待

TiDB 4.0 GA 版本即将发布,除了本文涉及的大事务、悲观锁等等还有很多新特性,例如 Sequence、Key VisualizerFollower Read等等,有兴趣的同学可以官网查看相关文章。

本文内容以 PingCAP 官网博客栏为准,欢迎点击【这里】查看原文。

若对 TiDB 的使用有所疑问,也可以登录 Asktug.com 搜索或发帖交流~

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广