作者: Gin 原文来源:https://tidb.net/blog/55452f4f
【是否原创】是
【首发渠道】TiDB 社区
【正文】
一、背景
TiDB 计算层 —— tidb-server 的无状态特点、以及事务状态由存储组件(TiKV)分布式管理的特性不同于一般单机数据库或具备 GTM 的分布式数据库,可以使用常常被部署在应用前端的负载均衡器来实现 tidb-server 的负载均衡,同时也使 TiDB 计算层具备了高可用能力(高可用性详见 TiDB 集群可用性详解及 TiKV Label 规划 - Google 文档)。
理论上讲,TiDB 支持所有 4 层(TCP/IP)负载均衡器(LB - Load Balancer),并支持负载均衡器上的 7 层 MySQL 协议探活机制。
常见 4 层负载均衡器包括:
连接池用于维护应用到数据库之间的长连接,避免了每次请求都要建立新的连接而造成的时间开销。常见的 Java 应用连接池:
Druid:阿里开源的数据库连接池,主要特点是功能全面, 性能和稳定性也都不错,被国内用户广泛使用。
C3P0:早期一款数据库连接池产品, Hibernate 将其作为内置的数据库连接池,简单易用稳定性好,但性能差,架构复杂。
DBCP:2014 年 DBCP 更新 2.0,性能尚可,但相比于竞品没有明显优势。
HikariCP:Springboot2.+ 官方默认的数据库连接池,性能强劲,稳定性好。
IBM WAS 内置连接池,传统金融用户广泛使用。
Oracle Weblogic 内置连接池,传统金融用户广泛使用。
二、负载算法
如上一章所讲,应通过长连接的方式来访问数据库以保障性能,因此建议使用最小连接数(least connection)的负载算法配置 LB,使连接数最少的服务器优先接收连接。
三、空闲连接超时配置策略
应用通过连接池维护应用到 LB 之间的长连接,同样的,LB 通过长连接和 TiDB 进行交互,而应用连接池和 LB 这两者都具备自动清理超时空闲连接的机制(idle timeout),为了避免出现空闲连接被“多次”清理的问题,需要考虑整体的配置策略。
根据过往的客户项目经验,我们建议将空闲连接超时交给应用连接池来处理,将 LB 的空闲连接超时配置为无限制或足够长的时间(比如一年),这样建议的原因是应用连接池更贴近应用程序和业务,方便管理连接和排查问题。
一定要避免将 LB 的空闲连接超时配置的比连接池更短,这将使 LB 提前杀死连接而导致连接池不知情。
四、探活
探活分为 4 层探活(ip:port)和 7 层探活(SQL 语句探活),主流的 LB 和连接池都支持这两种探活机制,4 层探活为固有能力,7 层探活一般需要额外配置。
就探活频率来说,LB 的探活频率较高些,而连接池一般支持在创建连接、关闭连接、连接空闲时进行探活。
以 Druid 连接池为例,7 层探活配置如下:
# validation-query 设置探活语句,当不设置时,下面三个参数将不生效
spring.datasource.druid.validation-query = select 1
# test-on-borrow 为 true 时,在创建连接时探活,影响性能,一般建议关闭
spring.datasource.druid.test-on-borrow = false
# test-on-return 为 true 时,在关闭连接时探活,影响性能,一般建议关闭
spring.datasource.druid.test-on-return = false
# test-while-idle 为 true 时,在连接空闲时探活,对性能基本无影响,建议开启
spring.datasource.druid.test-while-idle = true
复制代码
除了以上配置项外,注意还需要在应用代码中加入:
System.setProperty("druid.mysql.usePingMethod","false");
这条代码的作用是关闭 ping 探活方式,让 validation-query 能够生效,1.x 版本以上可用。
以 HAProxy 负载均衡器为例,7 层探活配置如下:
option mysql-check user haproxy post-41 #对性能基本无影响,建议开启
下表展示了在不同故障下,配置了 7 层探活的 LB 和连接池的响应。
表 1:故障下 LB 与连接池的响应
五、负载均衡器 IP 透传
应用服务通过 LB 连接到 TiDB 时,其原本的服务器 IP 会被屏蔽掉,show processlist
中只能看到 LB 的 IP,不方便问题排查和定位。而通过配置负载均衡器 IP 透传策略,可以使 TiDB 的诊断日志中记录原始请求发起位置的 IP 地址,方便问题的排查。
HAProxy:
在节点条目上增加 send-proxy 配置项
server tidb1 10.0.1.4:4000 send-proxy
调整 TiDB 启动脚本,增加 proxy 协议配置项 *
–proxy-protocol-networks
* 注意:开启 proxy 协议支持后,tidb-server 将无法直连,只能通过 HAProxy 连接。
LVS 或其他支持 TOA(TcpOptionAddress)的 LB:
调整 TiDB 配置项 enable-tcp4-only(从 v5.0 版本开始引入)值为 true,这是因为 LVS 的 TOA 模块可以通过 TCP4 协议从 TCP 头部信息中解析出客户端的真实 IP。
六、连接池配置参考
springboot-druid:
# jdbc url
spring.datasource.druid.url=JDBC:mysql://{TiDBIP}:{TiDBPort}/{DBName}?characterEncoding=utf8&useSSL=false&useServerPrepStmts=true&prepStmtCacheSqlLimit=10000000000&useConfigs=maxPerformance&rewriteBatchedStatements=true&defaultfetchsize=-2147483648
# 用户名
spring.datasource.druid.username=root
# 密码
spring.datasource.druid.password=root
# 驱动
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
# 初始化时建立物理连接的个数
spring.datasource.druid.initial-size=5
# 最大连接池数量
spring.datasource.druid.max-active=30
# 最小连接池数量
spring.datasource.druid.min-idle=5
# 获取连接时最大等待时间,单位毫秒
spring.datasource.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 连接保持空闲而不被驱逐的最小时间
spring.datasource.druid.min-evictable-idle-time-millis=300000
# 用来检测连接是否有效的sql,要求是一个查询语句
spring.datasource.druid.validation-query=SELECT 1
# 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
spring.datasource.druid.test-while-idle=true
# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-borrow=false
# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-return=false
# 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=true
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=50
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
spring.datasource.druid.filters=stat,wall
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
# 合并多个DruidDataSource的监控数据
spring.datasource.druid.use-global-data-source-stat=true
复制代码
七、负载均衡器配置参考
HAProxy:
global
log 127.0.0.1 local2
maxconn 4096
user haproxy
group haproxy
chroot /var/lib/haproxy
daemon
pidfile /var/run/haproxy.pid
stats socket /var/run/haproxy.sock # Make sock file for haproxy
nbthread 40 # 启动 n(以 40 为例) 个线程并发转发
defaults
log global
mode http
option tcplog
option dontlognull
retries 3
option redispatch
maxconn 1024
timeout connect 500000s
timeout client 500000s
timeout server 500000s
listen tidb_cluster
bind 0.0.0.0:8001 # 真正的 proxy 名以及接受服务的地址
mode tcp
balance leastconn # 这个方法最适用于数据库
option mysql-check user haproxy post-41 # 7层探活
server tidb1 172.16.4.81:4000 check
server tidb2 172.16.4.81:4001 check
server tidb3 172.16.4.88:4000 check
server tidb4 172.16.4.88:4001 check
server tidb5 172.16.4.91:4000 check
#IP 透传
#server tidb1 172.16.4.81:4000 check send-proxy
复制代码
评论