ZQPool对数据库实例状态的检测、清理和自愈机制解析
为了保证服务的可用性,ZQPool会定期对所有的数据库实例做健康检查,将检测出损坏的数据库实例节点移除连接池并对其占用的资源做清理和释放。当ZQPool发现之前损坏的节点已经恢复正常后,会对该节点进行恢复重建,然后重新将其加回连接池。
流程如下图所示:
1.原理解析
1.1 定期健康检查
ZQPool中,实例的状态分为以下5种类型:
- BE_BAD_NO_FREE:表示该数据库实例已经损坏,但是还有资源没有清理掉
- BE_BAD_FREEED:表示该数据库实例已经损坏,且所有的资源都已经被清理
- BE_REMOVING:表示该数据库实例正在被移除
- BE_OFFLINE:表示该数据库实例空闲未被上线使用
- BE_ONLINE:表示该数据库实例状态正常且正在被使用
ZQPool每隔10秒会对所有被标记为BE_ONLINE
状态的数据库实例进行健康检查,与该实例建立一个连接,并查询实例的主备状态:
select pg_is_in_recovery();
如果无法成功建立与数据库实例的连接,或者无法执行并获取到预期的SQL查询结果,系统会立即把该实例的状态标记为BE_BAD_NO_FREE
。
随后,系统将对比该实例当前的实际状态与其先前记录的状态。若此前记录的状态为主库,而当前识别为备库,则认定该数据库发生了故障转移或异常情况,同样将其标记为BE_BAD_NO_FREE
,以示该实例当前不可用或处于非正常状态。
1.2 实例的清理和自愈
在健康检查环节中,ZQPool会检测并识别出状态异常的数据库实例,并对这些实例赋予BE_BAD_NO_FREE
标签,随后将其移出连接池以避免资源浪费和潜在的内存泄漏问题。这些被移除的实例在内存中可能仍存在未释放的残留资源。
每隔2秒,ZQPool会对所有连接池进行逐个深度检查。首先针对标记为BE_REMOVING
的实例执行清理操作,如果发现该实例的所有连接均处于空闲状态,则立即关闭所有连接,并从连接池彻底移除该实例。若发现部分连接仍在使用中,ZQPool将暂时跳过处理此节点,等待后续清理周期。
接下来,ZQPool对标记为BE_BAD_NO_FREE
和BE_BAD_FREEED
的实例,进行相应的清理和恢复工作。对于所有连接均为空闲状态的BE_BAD_NO_FREE
实例,系统将立即释放其全部连接资源。
紧接着,ZQPool启动对这些异常标记实例的重建流程,在此过程中会对实例的运行状况进行全面检测。若重建尝试失败,实例会被重新标记为BE_BAD_NO_FREE
,并在之后的清理周期中继续对其进行处理,以防止任何潜在的内存泄露风险。
若实例成功重建并通过健康检查,ZQPool将会更新其状态标记为BE_ONLINE
,并将该实例重新加入到连接池中启用,从而实现了实例的自动故障恢复与自愈机制。