背景
在信创和国产化的背景下,政企银行国企等会在不久的将来全面实现国产化。就银行业底层使用的数据库而言,会逐步从小oracle小机、DB2大机等国外产品逐步替换为使用国产数据库,从边缘系统开始替换积累使用经验,后逐渐全面覆盖到核心系统。
在核心系统迁移到国产数据库前,需要做很多测试工作,其中很关键的一项的测试就是应用压测,应用压测可以模拟真实业务场景中用户使用,得到系统最真实的性能表现。作者在最近在某银行进行一次核心系统poc测试之后,将测试中的一些想法和调优手段进行整理之后编写这篇文章。
文章内容导读
应用压测架构
在通常的应用压测架构中,会在在压测端配置好压测任务项。
主要配置信息有:1、应用请求接口;2、模拟请求数据集;3、压测任务用户数(请求并发数)。
开始压测后,压测机根据配置的用户并发数,向应用集群发送一个或多个请求,通常在一个请求中,应用会向数据库发送多次请求,数据库也会多次向应用返回结果集,即一次压测请求,应用和数据库可能会有多次交互。
应用压测方式与目标
对于应用压测结果的考察有如下通常两种模式:
- 在同等机器资源下,固定压测用户并发下,测试得到TPS。
- 在同等机器资源下,可调整加大压测用户并发,直至测出性能拐点,取最高的TPS作为成绩。
在进行应用压测前还需要知道一些概念:
- 应用压测TPS不等于数据库事务TPS。应用压测TPS概括的生命周期是压测机向应用发起请求到请求回复结束,数据库事务TPS生命周期是begin和end之间
- 对于考察固定压测并发,通常应用和数据库都不会有资源瓶颈,最终压测结果和数据库sql执行的快慢强相关。
- 对于可以加大并发测出拐点性能的考察模式,理论上压测结果与sql执行快慢和sql执行成本强相关。
- TPS*平均响应延时=1,系统平均响应越快,耗时越短,TPS越高。
小插曲
作者在某次poc测试时,目标是测试出拐点性能,但是压测平台显示增加了压测并发之后,TPS无明显提升,且数据库各项资源使用率<50%,后面排查到原因是应用服务器资源使用达到了瓶颈,导致的即使再增加压测并发,应用也不能处理更多的请求,这样TPS也不会有提升。
这个也给作者了一个启发,虽然压测的目标是换国产数据库去测试,想去测试国产数据库性能,但是应用压测实际上测试的是整个系统的能力,调优要把视野放大。这点很重要,后面会谈到调优排查到应用的问题。。。
tidb高性能部署原则
tikv节点部署推荐
tikv磁盘部署最佳实践是利用上服务器本地多块高速磁盘进行部署,例如nvme ssd等。在poc中,不推荐像单机数据库一样使用中心化存储,nas存储等,有多块盘也不推荐做raid,tidb原生多副本就具有高可用性。
通常单台服务器如果有多块磁盘,会考虑每块磁盘上部署一个tikv节点,如果只有一块磁盘也可以考虑部署两个tikv节点
tidb server 节点部署推荐
通常建议tidb server 数据量不低于tikv节点数据量。在多次实测中表明,在平均每台服务器只部署了一个tidb节点的情况下,将tidb server 数量进行扩容,集群性能有提升。
pd 节点部署推荐
推荐pd部署在ssd上;通常无特殊要求,部署三个节点就行;如果涉及到跨中心测试,推荐参考多中心部署多pd leader 来避免tso wait过高,参考:专栏 - 三地五中心,TiDB POC最佳实践探索 | TiDB 社区
推荐组件绑定numa核心
tidb的组件绑定numa核心后,可避免cpu跨通道访问内存带来的延迟过高。但是存在的问题就是绑定核心的组件只能使用该核心分配的内存,例如tikv混布又绑定了核心,如果涉及到tikv可用内存不足够block cache使用,这就得实测判断是否绑定核心。
业务环境与部署选择
在上述部署推荐中,我有建议部署多数量节点的趋势,也推荐组件去绑定numa核心,这样会涉及到节点混布下,节点相关参数调低,或单组件可用内存上限降低,造成单组件上限瓶颈降低。
但通常而言,核心系统都是都是纯交易系统,功能模块例如:跨行转账,账户信息查询等,几乎都是低成本扁平化sql,多个节点资源使用比较均衡,所以不会存在大expensive sql造成的瓶颈问题。
连接TIDB的方式
使用mysql 8.0 驱动连接tidb
#链接需要加上预编译处理的参数
url: jdbc:mysql://IP:PORT/DB_NAME?useUnicode=true&characterEncoding=UTF-8&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true&prepStmtCacheSqlLimit=1000000000&prepStmtCacheSize=102400&useConfigs=maxPerformance&rewriteBatchedStatements=true
使用tidb loadblance驱动连接tidb
在poc测试中更推荐使用该驱动去直连接tidb,多次实测表明,使用该驱动会比mysql驱动连接f5等负载均衡的方案性能要好一点。
但是该驱动暂未正式GA,作者也在使用过程中发现一些其他问题,记录一下:
遇到的问题一:使用该驱动可能会导致负载不均衡
解决方案:添加random参数jdbc:tidb://{ip}:{port}/db?tidb.jdbc.url-mapper=random
遇到的问题二:该驱动所带的负载均衡没有该可用策略,部分tidb server 节点失活后,请求还是会持续转发到失活节点,导致应用持续报错。
参考haproxy探活,检测到下游节点失活后,后续请求不会转发到不可用节点。
listen tidb-cluster # 配置 database 负载均衡。
bind 0.0.0.0:3390 # 浮动 IP 和 监听端口。
mode tcp # HAProxy 要使用第 4 层的传输层。
balance leastconn # 连接数最少的服务器优先接收连接。`leastconn` 建议用于长会话服务,例如 LDAP、SQL、TSE 等,而不是短会话协议,如 HTTP。该算法是动态的,对于启动慢的服务器,服务器权重会在运行中作调整。
server tidb-1 10.9.18.229:4000 check inter 2000 rise 2 fall 3
# 检测 4000 端口,检测频率为每 2000 毫秒一次。如果 2 次检测为成功,则认为服务器可用;如果 3 次检测为失败,则认为服务器不可用。
server tidb-2 10.9.39.208:4000 check inter 2000 rise 2 fall 3
server tidb-3 10.9.64.166:4000 check inter 2000 rise 2 fall 3
优化SQL解析、编译、优化生成执行计划时间
使用预编译+prepare plan_cache进行调优
1、连接串添加预编译的参数
useServerPrepStmts=true&prepStmtCacheSqlLimit=10000000000&prepStmtCacheSize=102400&useConfigs=maxPerformance&rewriteBatchedStatements=true
2、调整数据库prepare plan cache 参数
3、检查plan_cache效果
dashboard上能看到大部分sql解析时间为0 ,优化时间为微秒级
4、判断是否还需要调整prepare plan_cache参数
plan cache 内存使用小于参数值,且plan_cache命中率高,无需调整参数
未使用使用预编译提交sql
1、开启数据库参数
2、查看效果。
由于non prepared_plan_cache这个功能刚出,大量受到限制的sql无法走上该功能
tidb相关参数调整与建议
tidb server
{
#可以减少日志打印
log.level: error
log.slow-threshold: 3000
}
tikv
{
gc.enable-compaction-filter = true
log.level = error
#如下参数不再给具体值建议,根据环境情况来,最佳性能模式下,这些参数的原则是:不会造成瓶颈。
raftstore.store-pool-size:
readpool.unified.max-thread-count:
server.grpc-concurrency:
storage.block-cache.capacity:
}
排查全局负载均衡
1、排查应用负载是否均衡
观察应用集群每台应用服务器cpu使用率和内存使用率是否均衡
2、查看tidb server 连接数和请求是否均衡
连接均衡是请求均衡的前提条件,请求均衡才是目的
3、排查tikv region和region leader 是否均衡
4、排查tikv请求是否均衡
由于请求类型与请求消耗资源关联有可能非常大,所以我一般直接去看tikv相关的线程使用率是否均衡
SQL调优与常见方向
1、补全索引等
参考:
2、改写sql
有些sql的写法走不了plan_cache,参考:Prepare 语句执行计划缓存 | PingCAP 文档中心
有些sql如标量子查询连接没法下推等。
3、优化表结构
例如:nocluster表换成聚簇表,即找高频唯一索引查询变成clustered index
缓存表
可以考虑给只有DQL,没有DML操作的表加缓存表
1、找到所有DQL操作的表(可借助dashboard)
2、判断这些这些表sql没有DML操作的表(可借助dashboard)
3、ALTER TABLE table_name CACHE
基于颜色优化法排查数据库瓶颈
Performance Overview 面板重要监控指标详解 | PingCAP 文档中心
通过去看整个sql执行流程上各阶段耗时去整体评估系统是否存在性能问题,通常颜色深的部分占比大需要注意和排查
优化coprocessor cache
1、观察监控,miss的可能是因为region有修改,这个没办法,evict要是多可能是因为cache大小不够而产生的缓存淘汰,可以调大cop cache参数
2、调整capacity-mb
的大小。
小表热点
可能会存在这样一种情况,某张表只有几万行,这个时候大概率这张表只有一个region(raft group这里先不讨论),这样对这张表所有的读写都会集中在一个tikv上,但是在进行应用压测的时候这个SQL是高频sql,热力图上也显示该sql读写流量高,这个时候会出现热点瓶颈,也导致整体延时上升
取巧方案:
pdctl
tiup ctl:v<CLUSTER_VERSION> pd -u http://<pd_ip>:<pd_port> [-i]
1、临时关闭合并region的调度
config set max-merge-region-keys 50
config set max-merge-region-size 1
2、多次切割region切割region
operator add split-region 1 --policy=scan
尝试开启非可重复读
在不介意幻读的情况下,可设置该参数,可显著降低tso_wait耗时
该参数是实例级别,需要依次连接每一个实例去设置
set tidb_rc_read_check_ts =on
如果应用事务里面依赖可重复读,开这个参数可能会报错,例如:在一个事务里面多次查序列
排查数据库外耗时
当整个系统响应耗时大部分不在数据库侧时,这时候即使在数据库侧优化的再好,也没办法去优化好整体性能
1、大致评估系统外耗时
2、如果感觉连接空闲时间很长,即数据库外耗时多,则需要排查应用-数据库之间网络延迟,应用资源使用率等
作者在某次排查到应用集群时发现,所有的应用服务器上某个端口的应用实例没有起,所以其实应用出问题也是很正常的。
算计GC间隔与压测项时长
默认配置下,GC 每 10 分钟触发一次,每次 GC 会保留最近 10 分钟内的数据。通常而言压测环境美伦GC任务耗时<2min
常见的应用压测项耗时,10分钟、15分钟。在这种配置下,几乎每轮压测期间都会执行GC任务
为了达到更稳定优异的性能,可以把tidb_gc_run_interval
调大,例如调整到1小时做一次,大概率压测期间就不会碰到在做GC了
手动进行compaction
可以手动对TIKV进行compact操作后再进行压测,谋求更优异的性能
TiKV Control 使用说明 | PingCAP 文档中心
写在最后
1、应用系统压测是对一个系统性能的检验,调优会涉及到方方面面,软件、cpu、内存、网络等等。
2、带你重走 TiDB TPS 提升 1000 倍的性能优化之旅 | PingCAP,写完文章后找到了一篇官方在V5时代出的一篇性能压测的文章,分析的更细致和循序渐进,可以看一看,其中思想和我的文章有重复的,但是我最佳poc大多是基于V6和V7版本做的,有一些新特性。官方文章更侧重讲思路和推理分析,而我这更侧重可行性实操分享。
作者介绍:BraveChen,来自神州数码钛合金战队,是一支致力于为企业提供分布式数据库TiDB整体解决方案的专业技术团队。团队成员拥有丰富的数据库从业背景,全部拥有TiDB高级资格证书,并活跃于TiDB开源社区,是官方认证合作伙伴。目前已为10+客户提供了专业的TiDB交付服务,涵盖金融、证券、物流、电力、政府、零售等重点行业。