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

高性能数据访问中间件 OBProxy(八):揭秘高性能转发原理

SQL学习者 2023-08-11
219

OBProxy提升 OceanBase 数据库性能

对于提升 OceanBase 数据库的性能,经过长期的性能问题分析和排查,我们总结了四个方面的影响因素,了解这四点大家就掌握了OBProxy对 OceanBase 数据库的性能影响,下面我们进行详细介绍。

链路对性能的影响

引入OBProxy后,虽然整体链路上多了一个模块,但对性能影响不大,参考下面例子:

我们比较连接OBProxy和连接OBServer1两种情况,假设数据分布在OBServer2上面,那么两种方式都需要两次网络交互。所以大部分情况下连接OBProxy和连接 OBServer的性能差距不大,并且因为OBProxy转发效率更高,有时性能更好。

访问 OceanBase 数据库时,链路长度和模块的部署方式有很大关系。我们在第二篇文章介绍了OBProxy部署方式,提到OBProxy部署到应用端时性能最好。为了大家更方便的享受这种部署的好处,我们也研发了富客户端功能。所谓富客户端功能,就是指我们把OBProxy的功能打包成一个so动态库,JDBC/C驱动等加载该so就可以使用富客户端能力,而无需部署运维OBProxy,我们以Java程序为例:

使用富客户端只需要修改下配置的URL即可,不需要修业务的代码,非常方便上手。

除了富客户端,随着云原生技术的普及,中间件产品的Mesh化也是部署的一个重要发展方向。OBProxy的Mesh产品DBMesh在蚂蚁内部也大量部署使用。因为Mesh 化对底层架构如k8s、pilot配置中心等有要求,因此有一定的使用门槛。

总结一下,大家根据真实的机房环境,按照我们第二篇文章给出的几种部署方式选择合适的就行,如果对性能有极致要求可以尝试使用OBProxy的富客户端形态。

扩展性

当排查发现分布式系统中某个模块达到单机性能瓶颈时,此时再去想提升单机性能是一件非常困难的事情,而通过增加机器进行扩容可以快速解决性能瓶颈问题,因此扩展性就是一个影响性能的重要因素。

OBProxy本身是无状态的,并且启动速度特别快,可以实现秒级提供服务,因此 OBProxy的扩展性特别好。根据真实测试数据,OBProxy可以在1~2s内完成启动提供服务。

另一方面,在双十一等高并发场景,OBServer 本身也经常做云上的弹入和弹出操作,本质就是OBServer的机器变更(上下线、扩缩容等)。OBProxy感知OBServer 的副本位置变更操作,在路由时选择正确的OBServer为用户提供服务,帮助用户有丝滑的使用体验。

数据路由

在第五篇文章我们介绍了路由影响因素,其中性能因素至关重要。为了更好的性能,我们实现了丰富的路由算法如LDC路由、Primary Zone路由、读写分离路由等,大家可以回顾前面的数据路由文章。

在OBServer的新版本,我们也将要上线事务路由功能,事务内的SQL都可以发往数据所在的节点,性能也会变得更好。我们假设事务有两条SQL:

之前版本事务路由:

新版本事务路由:

通过比较我们也可以发现新的事务路由更加的简单高效,减少TCP通信次数,并且可以更高效发挥每一台OBServer能力,性能提升有50%左右。

OBProxy单机性能提升

本节我们介绍下OBProxy单机性能提升的一些工作,方法论的东西比较多,和大家做一下交流,主要分为三个方面:

1、在OBProxy的功能设计和编码实现时考虑性能影响,面向高性能编程,降低新功能带来的性能损耗;

2、关注新的硬件、linux内核和编译器技术,使用新技术带来性能优化;

3、建立性能回归体系,对每个版本做严格性能回归,保证性能优化的成果。

下面我们将展开介绍。

OBProxy 高性能设计

OBProxy在设计之初就考虑了高性能:

  • 采用C++语言编写,可以充分使用硬件、内核的特性,也减少一些语言的GC等机制对性能影响;
  • 设计优秀的多线程模型,可以充分发挥每一个CPU核心的能力,架构上做到尽量简单;
  • 编码时采用异步调用、内存池、减少Buffer拷贝等手段优化性能。

如果用一句话概括,OBProxy通过多线程和异步框架提供优异的性能。为了满足异步接口的使用,我们也做了一些牺牲,一个完整的流程会被切割成多段代码,对代码可读性有一定影响。

对于OBProxy的线程模型,下图描述了公有云上OBProxy在16c机器上的任务分发模型。线程主要分为两类:accept线程和work线程。accept有两个,work线程有16个(根据CPU核数确定)。work线程完全一样,accept线程完成TCP建连后,会将对应的套接字轮询的发给每个work线程。每个work线程运行epoll机制, 进行套接字的读写、异常等处理工作。

因此OBProxy可以做到CPU核心之间的负载均衡,充分发挥每一个核心的能力,不存在因为阻塞导致CPU利用率上不去的情况。

OBProxy 优化方向

虽然OBProxy有了优秀的线程模型和异步框架,但随着功能的不断丰富,对性能也会产生一定的损耗。此时为了提升性能,我们该怎么做呢?我们的做法是分为应用、编译器和内核、硬件三层去做性能优化。

应用层优化

对于应用层优化,我们不做具体工作介绍了,讲一下我们的方法步骤,常见做法分为四步:

1、确定优化场景:如数据库我们常选择sysbench中的场景或者TPCC场景;2、分析性能消耗:我们通过perf火焰图、打日志等一些手段获取性能消耗分布, 从大到小,模块、函数、代码语句层层拆分下去,明确问题点;3、提出解决方案:无论是从设计上还是C++一些优化技巧(如减少拷贝、减少锁使用等)提出优化方案;4、验证优化效果:根据方案进行编码,并重新验证优化效果。

对于大部分情况,我们发现应用层优化效果就会很显著。举个极端例子,某个客户性能不符合预期,我们调整了客户Java程序的日志级别,就发现性能有几倍的提升,都还未涉及到数据库层面优化。在Github的OBProxy项目下,文件hotfuncs.txt记录了影响OBProxy性能的重点函数。但对于OBProxy和OBServer这样经过长时间优化的项目,应用层优化的油水会越来越少。

编译器和内核新特性使用

内核和编译器技术也在不断发展,在性能方面也会提供越来越多的新特性,我们关注这些技术发展并应用到我们实践中。

我们以编译器为例子,PGO和LTO是编译器的重要发展方向,编译器可以帮助应用程序更好的利用CPU的特性,如帮助CPU更好的做指令预取等。OBProxy也在升级适配新版本的编译器,将这些技术引入到项目中,提升OBProxy性能。

软硬件结合

对于硬件影响,我们举个例子,同一份OBProxy代码,只升级Intel CPU型号,性能就会有巨大差异。因此我们也需要关注硬件技术。硬件方面,我们探索RDMA在 OceanBase 数据库的使用。

对于RDMA,除了大家知道的对延迟的影响,另一个重要作用就是Bypass Kernel,节约CPU,优化性能。

在分析OBProxy性能时,我们发现内核态进行TCP报文收发就可能占用30% ~ 50% 的CPU资源。使用Bypass Kernel设计(参考下图),可以进一步提升OBProxy性能。目前在蚂蚁内部我们也在验证 RDMA 技术。

OBProxy 优化成果保护

对于OBproxy项目,版本功能迭代是性能的一大杀手。新的功能特性意味着新代码引入,代码规模进一步变大。除了指令数增加,对Cache命中率等硬件特性影响也会导致下降。因此我们需要平衡好新功能开发对性能影响:

1、在性能设计时考虑性能影响,做评估好性能影响;2、建立完善的性能回归体系,发现每一次的性能变化,并做好记录。

根据我们的工程实践,每个迭代性能损耗可以控制很好,在我们的预期范围内。

常见问题总结

问题分析方法论

下面我们分享总结我们一些性能优化方法论。

性能优化目的:

性能调优的目的旨在充分发挥软件和硬件的能力,在真实环境中实现系统的最佳性能,提高软硬件的性价比,降低客户的成本。

性能优化步骤:

1、确定优化目标:两个重要指标是吞吐量/延迟,如金融业务中延迟变大导致交易失败更加需要关注;2、压力测试及信息采集:因为性能压测往往伴随高并发等场景,所以需要尽量简化场景,更有利于问题分析;3、分析压力确定性能瓶颈:遵循从大到小原则,从整个系统拆分到某个模块,有模块进一步拆分,逐步攻克;4、实施优化:根据问题分析结果确定优化手段;5、确认优化效果:通过验证确定优化手段是否有效,如果无效需要重新分析。

通用优化手段:

1、优化部署:我们做了很多介绍,大家参考我们的部署内容介绍;2、调整配置参数:了解常用参数参数对性能的影响,OBProxy将大部分优化参数调整成默认值;3、分析及优化客户应用:性能优化方法论非常通用,也可以和客户交流,推动应用侧优化;4、负载均衡:OBProxy有一些路由配置项,可以通过调整路由配置观察不同路由算法对性能影响。

延迟问题排查

延迟问题分析的一个重要思路就是确定时间都去哪了。我们以一次云上延迟问题分析为例。

首先我们需要了解业务模型,以sysbench的write_only场景为例,客户端会发送如下 SQL:

BEGINUPDATE sbtest14 SET k=k+1 WHERE id=299UPDATE sbtest25 SET c='44447767919-12274780880-99082970721-80233057876-56657929970-31232803895-99831366925-10847903674-03281233116-67159541952' WHERE id=253DELETE FROM sbtest10 WHERE id=250INSERT INTO sbtest10 (id, k, c, pad) VALUES (250, 252, '40759328906-38274427176-96674981047-99836330693-36612343492-26708648085-72288836314-84636340651-06191567091-70833666298', '76795660930-60533928600-47111820801-73921545159-04547938600')COMMIT

第二步确定整体网络拓扑和ping延迟:

第三步我们根据OBProxy的审计日志、慢日志、统计日志分析OBProxy行为(参考第三篇文章)。根据OBServer 的 sql_audit分析OBServer行为。

最后根据分析出来的结论,整体梳理整个性能问题,进行总结归纳。

并发问题排查

并发问题表现就是QPS上不去,对于OBProxy,主要关注三点:

1、打印日志是否频繁:观察OBProxy打印日志的速度,如果2~3s就生成一个日志文件,那么性能肯定不好,正常应该几个小时或者一天生成一个,此时需要观察打印日志内容分析OBProxy行为;另一方面打印日志会导致SQL变慢,SQL变慢又会触发打印慢日志,导致恶性循环;

2、是否有远程计划:如果OBServer的sql_audit有大量远程计划,那么性能一般不会太好,此时需要分析问题原因,不同的原因有不同的处理办法;

3、使用perf top:可以通过perf top看OBProxy的函数CPU使用,如果有函数的 CPU使用超过5% (显示红色),就可以找专家协助看一下。

上面三点基本就可以解决大部分的OBProxy问题。

OBProxy 性能指标

对于OBProxy,大家也可以记录一些常用性能数据。OBProxy单核性能在2~4w之间,云上16c测试约有40w QPS。

OBProxy没有明显性能热点函数,使用perf top观察每个函数CPU消耗都在5%以下。

OBProxy工作线程建议配置和CPU核数一样,更多的线程数不会再带来性能提升。

对于OBProxy使用的协议,性能数据如下:MySQL协议>2.0协议>压缩协议。将压缩协议改为MySQL协议后性能会带来明显提升。

OBProxy提升 OceanBase 数据库性能

对于提升 OceanBase 数据库的性能,经过长期的性能问题分析和排查,我们总结了四个方面的影响因素,了解这四点大家就掌握了OBProxy对 OceanBase 数据库的性能影响,下面我们进行详细介绍。

链路对性能的影响

引入OBProxy后,虽然整体链路上多了一个模块,但对性能影响不大,参考下面例子:

我们比较连接OBProxy和连接OBServer1两种情况,假设数据分布在OBServer2上面,那么两种方式都需要两次网络交互。所以大部分情况下连接OBProxy和连接 OBServer的性能差距不大,并且因为OBProxy转发效率更高,有时性能更好。

访问 OceanBase 数据库时,链路长度和模块的部署方式有很大关系。我们在第二篇文章介绍了OBProxy部署方式,提到OBProxy部署到应用端时性能最好。为了大家更方便的享受这种部署的好处,我们也研发了富客户端功能。所谓富客户端功能,就是指我们把OBProxy的功能打包成一个so动态库,JDBC/C驱动等加载该so就可以使用富客户端能力,而无需部署运维OBProxy,我们以Java程序为例:

使用富客户端只需要修改下配置的URL即可,不需要修业务的代码,非常方便上手。

除了富客户端,随着云原生技术的普及,中间件产品的Mesh化也是部署的一个重要发展方向。OBProxy的Mesh产品DBMesh在蚂蚁内部也大量部署使用。因为Mesh 化对底层架构如k8s、pilot配置中心等有要求,因此有一定的使用门槛。

总结一下,大家根据真实的机房环境,按照我们第二篇文章给出的几种部署方式选择合适的就行,如果对性能有极致要求可以尝试使用OBProxy的富客户端形态。

扩展性

当排查发现分布式系统中某个模块达到单机性能瓶颈时,此时再去想提升单机性能是一件非常困难的事情,而通过增加机器进行扩容可以快速解决性能瓶颈问题,因此扩展性就是一个影响性能的重要因素。

OBProxy本身是无状态的,并且启动速度特别快,可以实现秒级提供服务,因此 OBProxy的扩展性特别好。根据真实测试数据,OBProxy可以在1~2s内完成启动提供服务。

另一方面,在双十一等高并发场景,OBServer 本身也经常做云上的弹入和弹出操作,本质就是OBServer的机器变更(上下线、扩缩容等)。OBProxy感知OBServer 的副本位置变更操作,在路由时选择正确的OBServer为用户提供服务,帮助用户有丝滑的使用体验。

数据路由

在第五篇文章我们介绍了路由影响因素,其中性能因素至关重要。为了更好的性能,我们实现了丰富的路由算法如LDC路由、Primary Zone路由、读写分离路由等,大家可以回顾前面的数据路由文章。

在OBServer的新版本,我们也将要上线事务路由功能,事务内的SQL都可以发往数据所在的节点,性能也会变得更好。我们假设事务有两条SQL:

之前版本事务路由:

新版本事务路由:

通过比较我们也可以发现新的事务路由更加的简单高效,减少TCP通信次数,并且可以更高效发挥每一台OBServer能力,性能提升有50%左右。

OBProxy单机性能提升

本节我们介绍下OBProxy单机性能提升的一些工作,方法论的东西比较多,和大家做一下交流,主要分为三个方面:

1、在OBProxy的功能设计和编码实现时考虑性能影响,面向高性能编程,降低新功能带来的性能损耗;

2、关注新的硬件、linux内核和编译器技术,使用新技术带来性能优化;

3、建立性能回归体系,对每个版本做严格性能回归,保证性能优化的成果。

下面我们将展开介绍。

OBProxy 高性能设计

OBProxy在设计之初就考虑了高性能:

  • 采用C++语言编写,可以充分使用硬件、内核的特性,也减少一些语言的GC等机制对性能影响;
  • 设计优秀的多线程模型,可以充分发挥每一个CPU核心的能力,架构上做到尽量简单;
  • 编码时采用异步调用、内存池、减少Buffer拷贝等手段优化性能。

如果用一句话概括,OBProxy通过多线程和异步框架提供优异的性能。为了满足异步接口的使用,我们也做了一些牺牲,一个完整的流程会被切割成多段代码,对代码可读性有一定影响。

对于OBProxy的线程模型,下图描述了公有云上OBProxy在16c机器上的任务分发模型。线程主要分为两类:accept线程和work线程。accept有两个,work线程有16个(根据CPU核数确定)。work线程完全一样,accept线程完成TCP建连后,会将对应的套接字轮询的发给每个work线程。每个work线程运行epoll机制, 进行套接字的读写、异常等处理工作。

因此OBProxy可以做到CPU核心之间的负载均衡,充分发挥每一个核心的能力,不存在因为阻塞导致CPU利用率上不去的情况。

OBProxy 优化方向

虽然OBProxy有了优秀的线程模型和异步框架,但随着功能的不断丰富,对性能也会产生一定的损耗。此时为了提升性能,我们该怎么做呢?我们的做法是分为应用、编译器和内核、硬件三层去做性能优化。

应用层优化

对于应用层优化,我们不做具体工作介绍了,讲一下我们的方法步骤,常见做法分为四步:

1、确定优化场景:如数据库我们常选择sysbench中的场景或者TPCC场景;2、分析性能消耗:我们通过perf火焰图、打日志等一些手段获取性能消耗分布, 从大到小,模块、函数、代码语句层层拆分下去,明确问题点;3、提出解决方案:无论是从设计上还是C++一些优化技巧(如减少拷贝、减少锁使用等)提出优化方案;4、验证优化效果:根据方案进行编码,并重新验证优化效果。

对于大部分情况,我们发现应用层优化效果就会很显著。举个极端例子,某个客户性能不符合预期,我们调整了客户Java程序的日志级别,就发现性能有几倍的提升,都还未涉及到数据库层面优化。在Github的OBProxy项目下,文件hotfuncs.txt记录了影响OBProxy性能的重点函数。但对于OBProxy和OBServer这样经过长时间优化的项目,应用层优化的油水会越来越少。

编译器和内核新特性使用

内核和编译器技术也在不断发展,在性能方面也会提供越来越多的新特性,我们关注这些技术发展并应用到我们实践中。

我们以编译器为例子,PGO和LTO是编译器的重要发展方向,编译器可以帮助应用程序更好的利用CPU的特性,如帮助CPU更好的做指令预取等。OBProxy也在升级适配新版本的编译器,将这些技术引入到项目中,提升OBProxy性能。

软硬件结合

对于硬件影响,我们举个例子,同一份OBProxy代码,只升级Intel CPU型号,性能就会有巨大差异。因此我们也需要关注硬件技术。硬件方面,我们探索RDMA在 OceanBase 数据库的使用。

对于RDMA,除了大家知道的对延迟的影响,另一个重要作用就是Bypass Kernel,节约CPU,优化性能。

在分析OBProxy性能时,我们发现内核态进行TCP报文收发就可能占用30% ~ 50% 的CPU资源。使用Bypass Kernel设计(参考下图),可以进一步提升OBProxy性能。目前在蚂蚁内部我们也在验证 RDMA 技术。

OBProxy 优化成果保护

对于OBproxy项目,版本功能迭代是性能的一大杀手。新的功能特性意味着新代码引入,代码规模进一步变大。除了指令数增加,对Cache命中率等硬件特性影响也会导致下降。因此我们需要平衡好新功能开发对性能影响:

1、在性能设计时考虑性能影响,做评估好性能影响;2、建立完善的性能回归体系,发现每一次的性能变化,并做好记录。

根据我们的工程实践,每个迭代性能损耗可以控制很好,在我们的预期范围内。

常见问题总结

问题分析方法论

下面我们分享总结我们一些性能优化方法论。

性能优化目的:

性能调优的目的旨在充分发挥软件和硬件的能力,在真实环境中实现系统的最佳性能,提高软硬件的性价比,降低客户的成本。

性能优化步骤:

1、确定优化目标:两个重要指标是吞吐量/延迟,如金融业务中延迟变大导致交易失败更加需要关注;2、压力测试及信息采集:因为性能压测往往伴随高并发等场景,所以需要尽量简化场景,更有利于问题分析;3、分析压力确定性能瓶颈:遵循从大到小原则,从整个系统拆分到某个模块,有模块进一步拆分,逐步攻克;4、实施优化:根据问题分析结果确定优化手段;5、确认优化效果:通过验证确定优化手段是否有效,如果无效需要重新分析。

通用优化手段:

1、优化部署:我们做了很多介绍,大家参考我们的部署内容介绍;2、调整配置参数:了解常用参数参数对性能的影响,OBProxy将大部分优化参数调整成默认值;3、分析及优化客户应用:性能优化方法论非常通用,也可以和客户交流,推动应用侧优化;4、负载均衡:OBProxy有一些路由配置项,可以通过调整路由配置观察不同路由算法对性能影响。

延迟问题排查

延迟问题分析的一个重要思路就是确定时间都去哪了。我们以一次云上延迟问题分析为例。

首先我们需要了解业务模型,以sysbench的write_only场景为例,客户端会发送如下 SQL:

BEGINUPDATE sbtest14 SET k=k+1 WHERE id=299UPDATE sbtest25 SET c='44447767919-12274780880-99082970721-80233057876-56657929970-31232803895-99831366925-10847903674-03281233116-67159541952' WHERE id=253DELETE FROM sbtest10 WHERE id=250INSERT INTO sbtest10 (id, k, c, pad) VALUES (250, 252, '40759328906-38274427176-96674981047-99836330693-36612343492-26708648085-72288836314-84636340651-06191567091-70833666298', '76795660930-60533928600-47111820801-73921545159-04547938600')COMMIT

第二步确定整体网络拓扑和ping延迟:

第三步我们根据OBProxy的审计日志、慢日志、统计日志分析OBProxy行为(参考第三篇文章)。根据OBServer 的 sql_audit分析OBServer行为。

最后根据分析出来的结论,整体梳理整个性能问题,进行总结归纳。

并发问题排查

并发问题表现就是QPS上不去,对于OBProxy,主要关注三点:

1、打印日志是否频繁:观察OBProxy打印日志的速度,如果2~3s就生成一个日志文件,那么性能肯定不好,正常应该几个小时或者一天生成一个,此时需要观察打印日志内容分析OBProxy行为;另一方面打印日志会导致SQL变慢,SQL变慢又会触发打印慢日志,导致恶性循环;

2、是否有远程计划:如果OBServer的sql_audit有大量远程计划,那么性能一般不会太好,此时需要分析问题原因,不同的原因有不同的处理办法;

3、使用perf top:可以通过perf top看OBProxy的函数CPU使用,如果有函数的 CPU使用超过5% (显示红色),就可以找专家协助看一下。

上面三点基本就可以解决大部分的OBProxy问题。

OBProxy 性能指标

对于OBProxy,大家也可以记录一些常用性能数据。OBProxy单核性能在2~4w之间,云上16c测试约有40w QPS。

OBProxy没有明显性能热点函数,使用perf top观察每个函数CPU消耗都在5%以下。

OBProxy工作线程建议配置和CPU核数一样,更多的线程数不会再带来性能提升。

对于OBProxy使用的协议,性能数据如下:MySQL协议>2.0协议>压缩协议。将压缩协议改为MySQL协议后性能会带来明显提升。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论