暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

PingCAP 2021-01-09
812

作者介绍

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

他们的队伍稳如狗的 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 圆点蓝牙机械键盘等实物奖励。
    🏅 一等奖(1 支队伍):¥ 100,000
    🥈 二等奖(2 支队伍):¥ 60,000 
    🥉 三等奖(2 支队伍):¥ 20,000
    🌟  投资机构特别奖 —— 「最具市场潜力奖」(3 支队伍):万元精彩大礼 
    🌟  PingCAP CTO 特别奖 (1 支队伍):Switch + 健身环
    ✨ 赞助商特别奖项:CNCF Special Award —— Scholarships to KubeCon 2021
    ✨ 最佳人气奖(1 支队伍,由现场观众投票):LOFREE 洛斐 DOT 圆点蓝牙机械键盘
    ✨ 最终 20 强:Divoom 点音 Evo 蓝牙音箱、CNCF 商店 50 美元礼券等

    目前,Hackathon 已经面向全球的数据库爱好者、 TiDB 用户、TiDB 生态合作伙伴及个人开发者开放报名,快来加入 TiDB Hackathon 2020,开启一段精彩的代码旅程!

    扫码下方二维码填写报名信息,立即组队报名!

    点击【阅读原文】了解更多 Hackathon 赛事详情

    文章转载自PingCAP,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论