前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >云数据库MySql故障切换下的应用重连配置最佳实践

云数据库MySql故障切换下的应用重连配置最佳实践

原创
作者头像
云顾问-为您服务
发布2024-05-03 00:34:06
1760
发布2024-05-03 00:34:06

本文面向云数据库用户,希望能给您带来收获,如有共鸣或者纠错,欢迎随时联系。


背景

云数据库 MySQL 支持单节点、双节点、三节点、集群版等架构,配合多可用区部署,可为用户业务提供高可用性支持,保证用户可以快速恢复数据库操作而无需管理干预,如出现可用区中断、主数据库实例故障(主实例因负载过高 hang 住、硬件故障等),数据库可以自动处理故障转移(实例切换),即主数据库实例(节点)会自动切换到备可用区的备用副本。日常的数据库运维过程中,数据库实例规格调整、数据库引擎版本升级等操作,也会可能涉及到实例切换。

云数据库实例切换时会出现秒级别的连接闪断,同时需要客户端(访问数据库服务的应用)具备自动重连功能,否则当发生主备切换后,会导致应用连接异常,进而影响业务的正常访问。基于此背景,本文介绍了应用的客户端重连配置实践,用于指导用户最佳使用姿势,提升应用健壮性。

基本概念

应用程序访问数据库步骤

应用访问数据库的步骤基于编程语言、数据库类型而有所不同,大致为:初始化---》建立连接---》执行Sql---》获取Sql数据---》关闭连接:

1、 初始化:引入数据库驱动,详见下文-数据库驱动

2、 建立数据库连接,数据库url、port、database、用户名、密码等信息

3、 操作执行Sql,增删改查

4、 操作获取Sql数据,查询数据,执行结果

5、 关闭数据库连接,释放资源

数据库驱动

数据库驱动程序是用于在应用程序和数据库之间建立通信和交互的软件组件。数据库驱动程序的主要目的是处理与数据库的通信细节,包括建立连接、发送SQL语句、接收和处理查询结果等。它们隐藏了底层数据库的复杂性,使开发人员能够专注于应用程序的逻辑而不必关心数据库的具体实现细节。数据库驱动程序通常由数据库供应商或第三方开发人员提供,并根据特定的数据库连接协议和API规范进行开发。每个数据库驱动程序都针对特定的数据库类型和版本进行了优化和调整,以提供最佳的性能和兼容性。通过使用数据库驱动程序,开发人员可以轻松地在应用程序中连接和操作数据库,无论是在Java、Python还是其他编程语言中。举例MySql数据库驱动:

MySQL :: MySQL Connectors

数据库连接池

在应用连接数据库的过程中,数据库连接会被创建和关闭,该步骤会有一定的性能开销,同时数据库服务本身也会有一定数量的数据库连接数数量限制以确保服务稳定,防止资源耗尽或者性能下降,为了提升性能和效率,引入了数据库连接池。

数据库连接池是一种管理和维护数据库连接的技术,它通过预先创建一组数据库连接并将它们保存在一个连接池中,以便在需要时重复使用这些连接,而不是每次都创建新的连接。这样可以提高应用程序的性能和响应速度,并减少数据库连接的开销。连接池一般具有连接重用、生命周期管理(创建、回收等)、连接池大小控制、超时验证等功能,使用数据库连接池可以有效地管理和优化数据库连接,提高应用程序的性能和可伸缩性。

应用重连机制

概述

数据库实例切换期间,已建连的数据库连接会断开,应用访问数据库会出现异常,为了减少该类场景下的业务影响,一般建议应用具备重连机制,即对旧的连接进行回收,同时新建数据库连接,从而保证业务对数据库的正常访问,故障后不需要重启应用即可恢复。

确认应用是否支持重连,需要确认应用的数据库连接管理实现,使用了哪些组件以及组件相关配置是否合理,如基于需要增加相应的组件支持,优化相关组件重连配置参数,最后基于数据库主从切换混沌演练测试应用重连机制是否正常工作。

Java应用

Java JDBC(Java Database Connectivity)是Java语言中用于与关系型数据库进行交互的标准API,它提供了一组接口和类,用于连接数据库、执行SQL语句、处理结果集等操作,开发人员可以直接基于JDBC封装数据层进行数据库的访问。早期应用基于JDBC规范访问数据库,参考如下代码示例:加载驱动、获取connection、执行sql语句、关闭connection。如果每次执行都是从数据库获取connection,在数据库出现主从切换的故障场景下,仅影响到故障期间获取到的connection,新获取的connection不会影响,即故障下应用客户重连恢复。

对Java应用,如果是自研实现了连接池,可以检查连接心跳检测、连接超时设置、连接回收策略、连接重建等实现逻辑,确保有连接重连机制实现,当然建议您可以直接使用业界成熟的数据库连接池组件,Java比较成熟的连接池有HikariCP、Druid、DBCP、C3P0等。

Druid

Druid 是一个 JDBC 组件库,包含数据库连接池、SQL Parser 等组件, 同时提供了强大的监控和扩展功能,被大量业务和技术产品使用或集成。

Druid默认配置是支持自动重连,所以不需要进行特殊的配置,通过源码分析,重连涉及到2个关键参数(如下),如果应用中将breakAfterAcquireFailure配置为true,在超过connectionErrorRetryAttempts重试次数后,Druid将不在尝试重连,在数据库主从切换场景下只能重启应用才能重新连接数据库。这里建议保持默认配置,这样您的应用即可支持自动重连,无需重启应用。

##是否中断重试重连,默认值为fasle,即不会中断

spring.datasource.druid.break-after-acquire-failure=false

##重连失败重试次数,默认值为1,

spring.datasource.druid.connection-error-retry-attempts=1

Druid 配置参数:这里也列举下Druid重连相关的重要配置参数,可以按需配置来提升connection的保活敏感度,复杂业务场景下优化解决connection失活的问题,注意新老版本的参数有差异,具体基于使用后的Druid版本:

配置项名称

缺省值

参数说明

maxActive

8

连接池最大活跃连接数量,当连接数量达到该值时,再获取新连接时,将处于等待状态,直到有连接被释放,才能借用成功注意合理配置maxActive可以确保连接池在高负载情况下能够提供足够的连接,同时避免资源浪费和性能下降。1、根据应用并发访问量和连接使用情况,确定最大活动连接数2、所有应用的maxActive之和不超过数据库的最大连接数限制。超过数据库的最大连接数限制可能导致连接被拒绝或性能下降。

maxWait

-1

获取连接时最大等待时间,单位毫秒。

minIdle

0

连接池最小空闲数量

testOnBorrow

FALSE

申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,其实一般情况下都可以开启,只有性能要求极其高且连接使用很频繁的情况下才有必要禁用。

testOnReturn

FALSE

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,这个一般不需要开启。

testWhileIdle

TRUE

建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

timeBetweenEvictionRunsMillis

60000

有两个含义:1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明

validationQuery

null

用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果数据库不支持ping,则会用到该属性去测试connection有效性。

validationQueryTimeout

-1

单位:秒,检测连接是否有效的超时时间,大于0才生效。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法

keepAlive

FALSE

在Druid-1.0.27之前的版本,DruidDataSource建议使用TestWhileIdle来保证连接的有效性,但仍有很多场景需要对连接进行保活处理。在1.0.28版本之后,新加入keepAlive配置,缺省关闭。使用keepAlive功能,建议使用最新版本,比如1.1.21或者更高版本打开KeepAlive之后的效果初始化连接池时会填充到minIdle数量。连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。当网络断开等原因产生的由ExceptionSorter检测出来的死连接被清除后,自动补充连接到minIdle数量。

keepAliveBetweenTimeMillis

120000(2min)

keepAlive为true,如果空闲时间小于timeBetweenEvictionRunsMillis但大于keepAliveBetweenTimeMillis扔执行探活操作

minEvictableIdleTimeMillis

1800000(30min)

配置一个连接在池中最小生存的时间,单位是毫秒如果有连接空闲时间超过minEvictableIdleTimeMillis,并且这些连接的数量超过了minIdle,则超过的这部分的连接会被回收

maxEvictableIdleTimeMillis

25200000(7h)

配置一个连接在池中最大生存的时间,单位是毫秒空闲时间只要超过了maxEvictableIdleTimeMillis,则被回收;

Druid 配置示例(示例为Druid Spring Boot Starter配置文件,动态配置以及其他配置文件具体参考方法名、参数名)

Druid重连接异常报错示例

相关链接

Apache Druid | Apache® Druid

GitHub - alibaba/druid: 阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池

druid/druid-spring-boot-starter at master · alibaba/druid · GitHub

HikariCP

”快速、简单、可靠。 HikariCP 是一个“零开销”生产就绪的 JDBC 连接池。该库大约 130Kb,非常轻。“ 这是HikariCP的官网介绍,就如同它本身一样,非常轻,非常简洁。

HikariCP具有快速恢复的能力,可以在连接故障后快速恢复并重新建立连接。HikariCP的配置参数中并没有重连机制的相关参数,默认支持重连机制的,只要应用集成了HikariCP,即支持重连。通过源码分析,HikariCP基于心跳检测、连接超时、连接验证、异常处理、回收策略等机制尽量保持一定数量的可用连接,以满足应用程序的需求,同时避免过多的空闲连接占用资源。

HiKariCP配置示例这里也列举下Druid重要配置参数:

配置项名称

缺省值

参数说明

autoCommit

TRUE

此属性控制从池返回的连接的默认自动提交行为。它是一个布尔值。

connectionTimeout

30000(30s)

此属性控制客户端(即您)等待来自池的连接的最大毫秒数。如果超过此时间而没有可用连接,则会抛出 SQLException。可接受的最低连接超时为 250 毫秒。

idleTimeout

600000(10min)

此属性控制允许连接在池中保持空闲状态的最长时间。仅当minimumIdle定义为小于maximumPoolSize时,此设置才适用。一旦池达到MinimumIdle连接,空闲连接将不被取消。连接是否以空闲状态退役,最大变化为+30秒,平均变化为+15秒。在此超时之前,连接永远不会因为空闲而退役。值为0表示永远不会从池中删除空闲连接。最小允许值为10000ms(10秒)。

keepaliveTime

0(禁用)

此属性控制 HikariCP 尝试保持连接活动的频率,以防止数据库或网络基础设施超时。该值必须小于该 maxLifetime值。 保活只会发生在空闲连接上。当针对给定连接的保活时间到达时,该连接将从池中删除、“ping”,然后返回到池中。 “ping”是以下之一:调用 JDBC4isValid()方法,或执行 connectionTestQuery.通常,池外的持续时间应以个位数毫秒甚至亚毫秒为单位进行测量,因此应该很少或没有明显的性能影响。允许的最小值为 30000 毫秒(30 秒),但分钟范围内的值是最理想的。

maxLifetime

1800000(30min)

该属性控制池中连接的最长生命周期。正在使用的连接永远不会退休,只有当它关闭时才会被删除。在逐个连接的基础上,应用较小的负衰减以避免池中的大规模灭绝。 我们强烈建议设置此值,它应该比任何数据库或基础设施施加的连接时间限制短几秒。 值 0 表示没有最大寿命(无限寿命),当然取决于设置idleTimeout。允许的最小值为 30000 毫秒(30 秒)。

connectionTestQuery

none

如果您的驱动程序支持 JDBC4,我们强烈建议不要设置此属性。这适用于不支持 JDBC4 的“旧版”驱动程序Connection.isValid() API。这是在从池中向您提供连接之前执行的查询,以验证与数据库的连接是否仍然有效。再次尝试在没有此属性的情况下运行池,如果您的驱动程序不兼容 JDBC4,HikariCP 将记录一条错误来通知您。

minimumIdle

10

该属性控制HikariCP 尝试在池中维护的最小空闲连接数。如果空闲连接低于此值并且池中的总连接数小于maximumPoolSize,HikariCP 将尽最大努力快速有效地添加其他连接。但是,为了获得最大性能和对高峰需求的响应能力,我们建议不要设置此值,而是允许 HikariCP 充当固定大小的连接池。

maximumPoolSize

10

此属性控制池允许达到的最大大小,包括空闲连接和正在使用的连接。基本上这个值将决定到数据库后端的实际连接的最大数量。合理的值最好由您的执行环境决定。当池达到此大小并且没有可用的空闲连接时,对 getConnection() 的调用将connectionTimeout在超时之前阻塞长达几毫秒。

HiKariCP 配置示例(示例为HiKariCP Spring Boot Starter配置文件,动态配置以及其他配置文件具体参考方法名、参数名)

HiKariCP重连接异常报错示例

相关链接

GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.

Python应用

Python应用访问数据库可以基于pymysql、mysql-connector-python、

DBUtils、Django、Flask等实现数据库访问,其中DBUtils是数据库连接池组件库,Django/Flask等框架也内置或支持第三方相应的数据库连接池实现,该类连接池均支持数据库连接管理(创建、重用和释放),以提高应用访问数据库的性能和效率。下面主要以DBUtils为例做下示例说明。

PyMySQL

基于pymysql、mysql-connector-python实现的应用,不支持数据库重连,除非用户自研了数据库连接池实现,同Java应用一样,这里可以检查连接心跳检测、连接超时设置、连接回收策略、连接重建等实现逻辑,确保有连接重连机制实现,当然建议您可以直接使用业界成熟的连接池组件方案,如DBUtils组件或者使用Djano等框架。

DBUtils

DBUtils是一套 Python 模块,允许在线程Python应用程序和数据库之间以安全有效的方式连接。DBUtils 最初是专门为Python作为应用程序和PyGreSQL作为PostgreSQL数据库适配器的Webware 编写的,但它同时也可用于任何其他 Python 应用程序和符合DB-API 2 的数据库适配器。DBUtils 套件实现为一个 Python 包,包含两个模块子集,一个用于任意 DB-API 2 模块,另一个用于经典 PyGreSQL 模块。

DBUtils配置参数:这里看下PooledDB(pooled_db)的重要配置参数:

● mincached:池中初始空闲连接数(默认0表示启动时不建立连接)

● maxcached:池中最大空闲连接数(默认值0或None表示无限池大小)

● maxshared:允许的最大共享连接数(默认值0或None表示所有连接都是专用的)

当达到此最大数量时,如果连接被请求为可共享,则连接将被共享。

● maxconnections:一般允许的最大连接数(默认值0或None表示任意数量的连接)

● 阻塞:确定超过最大值时的行为

如果设置为 true,则阻塞并等待,直到连接数减少,但默认情况下会报告错误。

● maxusage:单个连接的最大重用次数(默认0或None表示无限制重用)

当达到连接的最大使用次数时,连接将自动重置(关闭并重新打开)。

● setsession:可用于准备会话的 SQL 命令的可选列表,例如["set datestyle to german", ...]

● reset:返回到池时应如何重置连接(False或None来回滚以begin()开始的事务,默认值True出于安全考虑总是发出回滚)

● failure:如果默认值(OperationalError、InterfaceError、InternalError)不足以满足所使用的数据库模块,则应应用连接故障转移机制的可选异常类或异常类元组

● ping :一个可选标志,控制何时使用ping()方法检查连接(如果该方法可用)(0 =无= 从不,1 = 默认 = 每当从池中获取时, 2 = 创建游标时,4 = 何时执行查询, 7 = 始终,以及这些值的所有其他位组合)

● 指定为创建者的 DB-API 2 兼容数据库模块的创建者函数或连接函数将接收任何附加参数,例如主机、数据库、用户、密码等。您可以在自己的创建者中选择部分或全部这些参数功能,允许复杂的故障转移和负载平衡机制。

DBUtils配置示例

DBUtils重连接异常报错示例

相关链接

GitHub - WebwareForPython/DBUtils: Database connections for multi-threaded environments

DBUtils

DBUtils User's Guide

Go应用

Go应用访问数据库会直接使用database/sql库,该库包括连接数据库、执行事务等的类型和函数,同时默认支持数据库连接池,连接池适合大多数数据访问需求,对于某些高级应用,支持调整连接池参数或显式使用连接。

当然Go 还支持其他数据访问技术,包括用于对关系数据库进行更高级别访问的 对象关系映射 (ORM) 库如 GORM,对应框架也支持相应连接池的定制。

database/sql

使用database/sql连接池可以支持自动重连,连接池默认不需要配置,也可以基于需要定制连接池配置

● 设置连接池属性:您可以设置指导包如何sql管理连接池的属性。要获取有关这些属性的影响的统计数据,请使用 DB.Stats。

● 设置最大打开连接数:DB.SetMaxOpenConns 对打开连接的数量施加限制。超过此限制,新的数据库操作将等待现有操作完成,此时sql.DB将创建另一个连接。默认情况下,sql.DB当需要连接时,只要所有现有连接都在使用中,就会创建一个新连接。

请记住,设置限制会使数据库使用类似于获取锁或信号量,从而导致您的应用程序可能会死锁等待新的数据库连接。

● 设置最大空闲连接数:DB.SetMaxIdleConns 更改对保持的最大空闲连接数的限制sql.DB 。

当给定数据库连接上的 SQL 操作完成时,它通常不会立即关闭:应用程序可能很快就需要再次关闭,而保持打开的连接可以避免为下一个操作重新连接到数据库。默认情况下,sql.DB在任何给定时刻都会保留两个空闲连接。提高限制可以避免具有显着并行性的程序中的频繁重新连接。

建议:setMaxOpenConns 和 setMaxIdleConns 可以设置为相同值, 避免高并发时没法充分复用连接。

● 设置连接可以空闲的最大时间:DB.SetConnMaxIdleTime 设置连接关闭之前可以空闲的最长时间。这会导致sql.DB关闭空闲时间超过给定持续时间的连接。

默认情况下,当空闲连接添加到连接池中时,它会保留在那里,直到再次需要它为止。当使用DB.SetMaxIdleConns在并行活动突发期间增加允许的空闲连接数时,还DB.SetConnMaxIdleTime可以使用它安排稍后在系统安静时释放这些连接。

● 设置连接的最长生命周期:使用DB.SetConnMaxLifetime 设置连接在关闭之前可以保持打开状态的最长时间。

默认情况下,连接可以使用并重复使用任意长的时间,但须遵守上述限制。在某些系统中,例如使用负载平衡数据库服务器的系统,确保应用程序不会在不重新连接的情况下长时间使用特定连接会很有帮助。

DBUtils配置示例

建议:dataSourceName 可以加上设置读写超时时间, 当后端不回包时client也可以主动关闭连接

示例:root:xxxxx@tcp(*.*.*.*:port)/?charset=utf8&timeout=10s&readTimeout=10s&writeTimeout=10s

小结

应用访问数据库的重连场景,一是需要应用实现异常的捕获和处理,保证业务的连续性,异常情况下业务容错不会丢数据,应用也不会因为异常而导致进程终止退出;二是需要进行连接保活,即数据库连接池里面丢弃异常连接,更新增加新的连接,使得应用高效复用。当然以上过程涉及到性能、资源的总和考量,满足业务的同时,又能尽可能的容错,有限资源达到更高的吞吐。

本文列举了Java/Python/Go应用的重连机制实现,其他语言PHP等也类似,暂不注意列举。

监控告警

腾讯云通过底层资源巡检预警等多种手段保证云上资源服务的问题,但是还是有很多硬件故障触发的数据库主从切换发生,而该事件对不同客户的业务影响也不同,有些客户的业务对数据库主从切换敏感,如果支持重连,应用一般可以自愈,运维处理善后即可,而对于不支持重连的应用运维需要进行应用重启处理。

腾讯云顾问建议敏感用户业务在腾讯云可观测平台配置云数据库主从切换等事件告警,覆盖核心数据库实例,方便接收事件响应处理。

腾讯云可观测平台 新建告警策略-告警管理-文档中心-腾讯云

腾讯云可观测平台 云数据库 MySQL-事件总线-文档中心-腾讯云

混沌演练

混沌演练平台(Chaotic Fault Generator)提供高效便捷、安全可靠的故障演习服务,除可视化故障注入服务外,还提供行业经验模板,监控护栏等核心功能,致力于帮助用户及时发现业务容灾隐患、验证高可用预案的有效性,从而提高系统的可用性和韧性。

应用重连机制是否有效,腾讯云顾问建议您通过混沌演练进行验证,当前混沌演练平台涵盖主备切换、重启、整体不可用等事件,可以有效模拟数据库故障下的事件,来测试应用表现。

混沌演练平台 产品概述-产品简介-文档中心-腾讯云

混沌演练平台 云数据库 PostgreSQL 主备切换-故障动作库-文档中心-腾讯云

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 基本概念
    • 应用程序访问数据库步骤
      • 数据库驱动
        • 数据库连接池
        • 应用重连机制
          • 概述
            • Java应用
              • Druid
              • HikariCP
            • Python应用
              • PyMySQL
              • DBUtils
            • Go应用
              • database/sql
            • 小结
            • 监控告警
            • 混沌演练
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档