首批通过分布式安全可靠测评,为关键业务系统打造
无主
更新时间:2025-12-09 15:05:43
无主的报错为 -4038,在发现 4038 错误后,有两种可能:
- 当前 Leader 存在,但是 Leader 不是本节点,可能是发生切主后 Location Cache 未刷新。
- 当前 Leader 不存在,需要排查日志流的网络连通性。
当前 Leader 存在
可能因为切主后(包括异常切主和优雅切主),Location Cache 未刷新,远程执行时目的节点已经不是 Leader,返回 4038 错误码,然后语句级重试。可以通过如下方式确认:
- 通过
DBA_OB_SERVER_EVENT_HISTORY视图确认是否确实发生了切主。 - 通过系统日志确认目的端是否确实返回了 4038 错误码。
# grep 4038 observer.log
[2021-01-21 09:46:31.305260] WARN setup_next_scanner (ob_direct_receive.cpp:292) [15256][YB420B4043DA-0005A535D6FAE816] [lt=2] , ret=-4038
[2021-01-21 09:46:31.305295] WARN [SQL.EXE] setup_next_scanner (ob_direct_receive.cpp:295) [15256][YB420B4043DA-0005A535D6FAE816] [lt=31] while fetching first scanner, the remote rcode is not OB_SUCCESS(ret=-4038, err_msg="", dst_addr=""11.xx.xx.xx:2882"")
[2021-01-21 09:46:31.305302] WARN [SQL.EXE] inner_open (ob_direct_receive.cpp:123) [15256][YB420B4043DA-0005A535D6FAE816] [lt=6] failed to setup first scanner(ret=-4038)
[2021-01-21 09:46:31.305308] WARN [SQL.ENG] open (ob_phy_operator.cpp:138) [15256][YB420B4043DA-0005A535D6FAE816] [lt=4] Open this operator failed(ret=-4038, op_type="PHY_DIRECT_RECEIVE")
[2021-01-21 09:46:31.305314] WARN [SQL.ENG] open (ob_phy_operator.cpp:128) [15256][YB420B4043DA-0005A535D6FAE816] [lt=5] Open child operator failed(ret=-4038, op_type="PHY_ROOT_TRANSMIT")
[2021-01-21 09:46:31.305366] WARN [SERVER] test_and_save_retry_state (ob_query_retry_ctrl.cpp:242) [15256][YB420B4043DA-0005A535D6FAE816] [lt=2] partition change or not master or no response, reutrn it to packet queue to retry(client_ret=-4038, err=-4038, retry_type_=2)
当前 Leader 不存在
日志流是否有主取决于三个模块,自底向上分别是选举模块、CLOG 模块、RoleChangeService 模块。因此,当日志流没有 Leader 的时候,可以采用自底向上的方式排查:
- 确认是否存在 Election Leader。
- 确认是否存在 CLOG Leader。
- 确认 RoleChangeService 模块工作是否正常。
确认 Election Leader 是否存在
在日志流存在的任意节点上可以通过系统日志查询当前的 Election Leader,例如以下命令查询 1 号租户 1 号日志流的 Election Leader,如果是查询其他日志流,将 T1 和 id:1 换成其他租户和日志流的 ID 即可。
grep 'T1_.*{id:1}' ./election.log | grep 'dump acceptor info'
其中的,lease:{owner:"xx.xx.xx.xx:xxxxx" 表示该日志流的 Election Leader,xx.xx.xx.xx 表示 IP 地址,xxxxx 表示端口号。
若当前 Election Leader 不存在,很大概率是日志流的网络连通状态有问题,例如:
- 因为租户没有内存接收不到消息,但是还能发送消息,导致单向网络连通。
- 因为工作队列积压导致无法接收消息。
- 因为节点处于 Stop 状态无法接收消息。
- 其他原因导致的网络连通性问题。
需要进一步根据网络交互统计信息分析日志流级别的网络连通性,可以通过如下命令查询。
grep 'T1_.*{id:1}' ./election.log | grep 'dump message count'
该日志统计了本副本与其他副本间的消息收发记录,并按照 IP 与消息类型分类,记录最后一次交互的时间戳。
根据网络联通统计数据,可以初步判断是哪个节点异常,问题在发端还是收端,从而到对应节点上进一步排查。
除了根据系统日志,还可以根据内部视图事件查询和分析,通过系统租户下的 DBA_OB_SERVER_EVENT_HISTORY 视图查询。
obclient >
SELECT VALUE4,svr_ip,svr_port,event,name3,value3
FROM DBA_OB_SERVER_EVENT_HISTORY
WHERE module="ELECTION" AND value1=$tenant_id AND value2=$ls_id
ORDER BY VALUE4 limit 10;
如果 Election Leader 存在,继续确认 CLOG Leader 是否存在。
确认 CLOG Leader 是否存在
Election Leader 确认存在的情况下,可以进一步排查 CLOG Leader 是否存在。
如果集群可用(SQL 客户端可连接),可以通过系统租户下的 GV$OB_LOG_STAT 视图查询。
obclient >
select * from GV$OB_LOG_STAT
where tenant_id=$tenant_id and ls_id=$ls_id and role="LEADER";
注意
如果查询结果中节点个数少于 memberlist 中的副本数,则说明某些日志流副本的状态已经出现了异常,需要进一步排查。
如果集群不可用(SQL 客户端不可连接),可以通过系统日志排查,在上一步中获取到的 Election Leader 节点上,执行以下命令。
grep 'Txxx_.*PALF_DUMP.*palf_id=xxxx,' observer.log.* | less
# 其中 Txxx 为 tenant_id,例如 T1001 为搜索 1001 租户的日志;
# palf_id 为日志流 id,例如 palf_id=1001 为搜索 1001 日志流的日志
如果日志中的 role 是 Follower,说明 CLOG Leader 不存在,需要进一步排查 CLOG Leader 不存在的原因。
如果 CLOG Leader 存在,继续确认 RoleChangeService 工作是否正常。
确认 RoleChangeService 工作是否正常
当 CLOG 发生角色切换时,会投递一个异步任务到 RoleChangeService 的任务队列,RoleChangeService 的后台线程负责执行主备切换工作,可以根据系统日志排查 RoleChangeService 的工作状况,命令如下。
grep 'Txxx_RCS' observer.log rootservice.log.xxxx -h | sort | less
如果最后一条日志不是
end handle_role_change_event_,说明执行切主动作时卡住,可以进一步查看最后一条日志中的堆栈以确认问题。如果最后一条日志是
end handle_role_change_event_,并且 CLOG 有主,说明 RoleChangeService 模块异常,需要进一步排查。
常见的租户无主的原因
时钟偏差
当前 Election 模块依赖任意两个 OBServer 之间的时钟偏差不超过 2s,如果超过则可能导致无主,可以通过如下命令检查 OBServer 之间的时钟是否同步。
sudo clockdiff $IP
如果结果显示偏差值超过 2s,需要继续检查时钟服务是否工作正常。常见的时钟服务包括 NTP、Chrony。
租户/表/分区被删除
如果某个租户被删除或表/分区被删除,由于多个副本删除时机可能不一致,若 Leader 最后删,可能由于收不到投票而连任失败,Lease 过期时发生无主。
多数派副本发生宕机
如果有副本宕机,正常副本无法满足多数派,就会发生无主。
网络问题
如果多数派副本进程都在,未发生宕机,且 Leader 副本的系统日志出现 leader lease is expired 的报错,说明 Leader 副本连任(延长自己的 Lease)失败,可能发生网络故障(单向/双向网络隔离、RPC 请求积压、RPC 延迟),需要进一步排查。
报错示例如下。
# grep 'leader lease is expired' election.log
[2018-09-27 23:09:04.950617] ERROR [ELECT] run_gt1_task (ob_election.cpp:1425) [38589][Y0-0000000000000000] [log=25]leader lease is expired(election={partition:{tid:1100611139458321, partition_id:710, part_cnt:0}, is_running:true, is_offline:false, is_changing_leader:false, self:"11.xx.xx.xx:2882", proposal_leader:"0.0.0.0", cur_leader:"0.0.0.0", curr_candidates:3{server:"100.xx.xx.xx:2882", timestamp:1538050146803352, flag:0}{server:"11.xx.xx.xx:2882", timestamp:1538050146803352, flag:0}{server:"100.xx.xx.xx:2882", timestamp:1538050146803352, flag:0}, curr_membership_version:0, leader_lease:[0, 0], election_time_offset:350000, active_timestamp:1538050146456812, T1_timestamp:1538069944600000, leader_epoch:1538050145800000, state:0, role:0, stage:1, type:-1, replica_num:3, unconfirmed_leader:"11.xx.xx.xx:2882", takeover_t1_timestamp:1538069933400000, is_need_query:false, valid_candidates:0, cluster_version:4295229511, change_leader_timestamp:0, ignore_log:false, leader_revoke_timestamp:1538069944600553, vote_period:4, lease_time:9800000}, old_leader="11.xx.xx.xx:2882")
系统负载高
如果系统 load 值非常高,也可能导致无主。可以通过系统命令查看对应时间点的 load 值是否正常。
CLOG 盘写满
如果 CLOG 盘使用超过阈值(由租户配置项 log_disk_utilization_limit_threshold 控制,默认值为 95%),会强制停写,此时该节点上的副本无法当选为 Leader,如果多数派副本所在节点都发生这种情况,那么集群会无主。
租户内存写满
当租户的 MemTable 内存写满时,无法继续回放日志,进一步导致日志无法回收(回收依赖回放、转储)。因此,为了避免 CLOG 盘写满,租户内存写满时,副本不允许继续从 Leader 接收日志。如果多数派 Follower 发生了租户内存写满,Leader 的日志同步就会卡住,从而无法达成多数派而发生集群无主。
CLOG reconfirm 失败
如果 Election 模块工作正常,选出了 Leader,但在 CLOG 模块执行 reconfirm 时失败了,此时 Leader 会主动卸任。需要进一步排查 reconfirm 失败的原因。
Takeover 失败
CLOG reconfirm 成功后,会进入 takeover 状态,由 RoleChangeService 模块继续执行具体的上任逻辑。如果 RoleChangeService 模块工作异常,会导致集群无主。需要进一步排查 Takeover 失败的原因。
事务回调执行异常
Leader 副本的事务滑动窗口左边界的 CLOG 日志如果超过一定阈值(10秒)没有达成多数派并滑出,会导致 Leader 异常卸任从而发生集群无主。
报错示例如下。
# grep 'check_leader_sliding_window_not_slide_' observer.log
[2022-11-29 11:19:12.239777] ERROR [CLOG] check_leader_sliding_window_not_slide_ (ob_log_state_mgr.cpp:2243) [7393][0][Y0-0000000000000000-0-0] [lt=66] leader_active_need_switch_(partition_key={tid:1099511627898, partition_id:2, part_cnt:0}, now=1669691952239687, last_check_start_id_time_=1669691939215423, sw max_log_id=16282, start_id=16282) BACKTRACE:0xfbdfc9f 0xfbc93dd 0x55391ef 0x9c0a1f9 0x9af215d 0x532d801 0x532c0ae 0x532bc69 0x532bb4f 0x529b6a6 0x9adee54 0x5522e04 0xfa8d123 0xfa8cf7f 0xfd6284f
可进一步排查:
- 本机 CLOG 写盘慢,排查 CLOG 盘的负载、await 等指标。
- Follower 副本写盘慢,排查方式同上。
- Leader 和 Follower 之间的网络慢,例如
packet fly cost too much time显示网络包耗时很大。