性能竞赛优秀项目 | 以「点」窥面,PointGet 性能优化分享

百家 作者:PingCAP 2021-01-08 18:46:44

作者介绍

彭笳鑫,杭州帷幄匠心研发工程师。

他们的队伍稳如狗的 HelloKitty 在性能竞赛中斩获二等奖,本文将通过他们的参赛项目,介绍如何用 PointGet 作为突破口,来提升查询的吞吐量与查询的性能。


在分布式数据库 TiDB 中如何更好的提高查询的吞吐量和提升查询的性能一直是一个难题。PointGet 虽小,但我们可以从 PointGet 中窥探出 TiDB 的特性变迁。PointGet 由于查询方式固定,所以就被剥离出来抽象成了一条特殊的 Plan,这样可以更准确的去做相应的优化。为了更好的从整体流程和针对优化方面学习 TiDB,我们特意挑选了 PointGet 来作为突破口来优化上述提到的性能,这样就可以站在巨人的肩膀上专门去优化 TiDB 抽象出来的 PointGet 相关逻辑,更加 Focus 在有意义和创造力的地方。

我们团队有三位队友和一位顾问,从比赛一开始顾问就和我们沟通了各自对于这个赛题的想法和观点。我们提出了很多没有基于现实情况的假设,顾问指出了很多我这边臆测的问题点,也为后面定位问题和解决问题提供了非常良好的帮助。同时,我们也参加了 TiDB 在 B 站的 Talent 计划,根据视频的内容对现有的 TiDB 有了更加深入的理解,更好的支撑了我们对于完成这个赛题的信心。


 什么是 PointGet?


PointGet 是一个简单的点查,展示 SQL 如下

SELECT * FROM user WHERE id = 1;


PointGet 的执行流程 


本文先把 TiDB 官方的流程图贴在下方,这样更好的能让大家对整体的 SQL 流程有个感知。图中客户端发起请求,TiDB 的服务端接收到对应的数据包,服务端 Parse、Valid 等步骤生成 AST,接着通过逻辑优化和物理优化生产对应的执行计划,并通过对应的执行算子去执行对应的 Plan,然后通过 RPC 去访问 TiKV 获取对应的数据。

SQL 查询流程

从上图的流程图我们可以看出来,PointGet 有自己的 PointGet Plan 和 PointGet Executor。

根据上面的情况我们可以发现以下几个优化点:

  • PointGet 是一个非常简单的点查,基本可以理解为一个查询一个结果;

  • PointGet 是一个点查操作,配合 Lock 的特性可以大大增加可靠性和稳定性;

  • 无论几次 Query 都会访问 TiKV,第一次查询可以访问 TiKV,后面的查询可以直接复用以前查询的结果。


设计优化 PointGet 问题点的解决方案 


面对以上优化点,我们设计一个方案来解决上面提到的问题,这个方案涉及到了 DDL 和 DML 相关模块,DML 流程图展示如下:

上图简化了很多流程,最直接的就是在 Executor 和 TiKV 中增加了一层 Cache,这个做法的直接效益是将数据从 TiKV 层返回移到 TiDB 层返回,减少一层网络开销。同时,数据从 Cache 里面返回比从磁盘返回的速度更快。

我们接下来将讨论如何保障出现 DDL 的时候,Cache 数据更新的及时性以及 Cache 的内存管理问题。


TiDB 中 Cache 更新的及时性和内存管理问题 


Cache 需要通过 TiDB 中的 Lock 特性来保证数据的一致性,Lock 非常贴合 PointGet 的 Query 要求,加锁的时候,数可以直接 Store 到 Memory 当中,Release 的时候可以直接删除对应的 Cache。完成上述设计后,我们发现添加对 Cache 管理这个特性会引来如下问题:
  • 如果有多个 TiDB,DDL 的时候如何保证查询结果的一致性?
  • 如果查询的表数据过大,缓存的 Cache 会不会直接造成 TiDB 的 OOM?
  • 引入新的代码是否符合社区的发展方向?
其中比较麻烦的是第一个问题,我们通过调研发现,TiDB 是实现了 Google 的一篇论文来管理 Schema 变更的状态。基于这个特性,在某个 TiDB(TiDB Owner)做 DDL 操作后,其他 TiDB(TiDB worker)也会做相同的 DLL 操作,所以我们在解锁表的时候就可以清空所有 TiDB 里面的缓存,这样就不会出现不同 TiDB 里面的数据不一致的情况,比较优雅地解决了数据一致性的问题。
针对第二个 OOM 问题,原本打算实现一套 LRU 来做内存的管理和淘汰,但是根据 Mentor 的提醒,我们调研了 MemDB 的底层逻辑代码。MemDB 是基于红黑树实现的,有优异的写入和读取特性。同时,MemDB 有专人维护同时也有着内存限制,不会由于用户的乱查询导致内存的飙升,规避了把服务器搞挂的风险,所以 Cache 以 MemDB 为底层的内存存储结构是一个符合社区未来发展方向的方案。


性能测试


可以很明显地发现,有 Cache 的 QPS 比没有 Cache 的 QPS 高了好几个档次。

在最后,我们发现有 Cache 的 QPS 有些许的下降,定位下来发现原因是缓存的数据过多导致机器处理能力的下降,后期增加 LRU 后就可以比较优雅地解决这个问题。

同时,有 Cache 的 p95 lantency 比没有 Cache 的 p95 lantency 响应能力也更加优秀。


额外发现


在我们做 Benchmark 的时候,发现表即使是在 Lock 状态时,Update 等语句也可以正常执行,这并不符合 Lock 的语义。

我们当天整理了一下问题并且提出了 Issue,PingCAP 的官方很及时的做出了响应,并且在接下来的几天内就解决了问题并且增加了对应的测试用例,非常具有及时性,值得点赞。


总结


在本次性能挑战大赛中,我们了解了 SQL 的一生和如何保证多个 TiDB 内数据一致,这非常有助于我们深入了解分布式数据库的内在。

同时,我们在为 TiDB 这样的大型开源项目贡献力量的时候,并不希望给 TiDB 引入有问题的代码,对于提交的代码会通过各种用例去测试他的健壮性,这也有助于提升我们编写可靠代码的能力。


特别感谢:

本抱着学习 TiDB 的心态参加了 B 站的学习视频,跟着课程提交了几次 PR,忽然发现PingCAP 还提供了竞赛并且每个赛题都会配置相应的 Mentor,这是学习并且熟悉 TiDB 的好机会,衷心感谢 PingCAP 给大家提供了这么有价值的机会。在这次 2 个月的长跑中也要感谢 Reviewers(crazycs520,breeswish,jackysp,coocood 等)不遗余力的意见和建议,还有帅鹏(jackysp)的悉心指导,帮助我们把控方向。也感谢金泽和卓群提供了一些难点的建议。非常感谢各位运营小伙伴(汽水等)的提醒和帮助让我们这次顺利的"享受"了这次竞赛,体验很赞。


还不过瘾怎么办?


一年一度的 TiDB Hackathon 报名截止正式进入倒计时!赶快上车啦!

本届大赛 Hackathon 的主题为「∞」,参赛项目可围绕 TiDB 组件或结合 TiDB 生态周边(TiKV、ChaosMesh® 等)进行创作,用最硬核的技术和最炸裂的创意去创造无限可能。共计设立高达 30 万元的现金大奖,以及 Switch、LOFREE 洛斐 DOT 圆点蓝牙机械键盘等实物奖励。

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接