-
Notifications
You must be signed in to change notification settings - Fork 171
Region Metadata Management
每个实例每隔30s上报,Meta会置实例状态为PB::NORMAL,同时更新时间戳,如果实例3次心跳间隔还未上报心跳状态会被置为PB::FAULTY,超过60次心跳间隔还未上报心跳状态会置为pb::DEAD。
每一个region都是一个raft-group,正常情况下,region是三副本,设为(A,B,C),A为leader。baikalStore会定期将region信息上报给MetaServer,其中Leader每隔30s上报一次,follower每隔30min上报一次。
Role | 上报间隔 |
---|---|
Leader:A | 30s |
Follower:B,C | 30min |
MeteServer维护了一个_region_state_map记录region的状态(NORMAL or FAULTY)和Leader上报时的系统时间,Leader在3次心跳间隔未成功上报心跳该region状态会被置为FAULTY。只有region的Leader更新_region_state_map。
目前region删除的场景有:
场景 | 描述 |
---|---|
删除表 | 执行drop table时表对于的region信息也会被删除,meta会根据之前上报的region信息获取所有peers,向这些peer都发删除请求。这里meta记录的信息可能不是最新的(比如刚进行了add_peer),导致region的peer未被删除;如果region刚分裂成功,新分裂出的region还未上报给Meat时也不能被删除。 |
负载均衡 | 删除peer的前提是peer数大于表配置的副本数1.修改resource_tag会先在新的resource_tag实例上add_peer然后删除老resource_tag的peer,即resource_tag和表不匹配的peer优先被删除2.保证机房副本分布或实例peer数均衡情况下优先选择多出来的peer进行删除 |
人工向store发送remove_region指令 | 人工处理脏region时会这样做,但是一般不需要,在上报peer时会判断peer是否有效 |
- 注:上报peer时会判断peer是否有效会判断peer的log_index,如果peer的log_index比meta的大,表明peer数据更新,先不删除
case | 描述 |
---|---|
节点dead(长时间未上报心跳) | 节点长时间不上报心跳,meta认为节点dead,尝试删除region的raft-group中的这个节点的peer,删除条件:1.region满足副本条件(不满足先尝试add_peer) 2.region有leader(leader最近上报过心跳) |
region的某个peer在遇到实例宕机,或者磁盘满导致peer的raft状态机ERROR,或者被误删除,这种情况下三副本一个副本不可用,导致可用性降低,一旦再有一个副本出问题,raft就选不了主。在迁移时meta只是根据实例状态判断是否可以迁移,可能实例状态是正常的但是region的peer是不可用的(磁盘满导致peer的raft状态ERROR,或者被误删除)。
希望能够:
- 快速发现region的peer是否可用,以便及时调整
- region删除后有恢复能力
- meta维护region每个peer的状态,在Leader进行心跳上报时更新,这些状态作为参考,在负载均衡进行remove_peer时可以作为选择依
- region增加一个类似ttl的功能
peer角色 | 处理 |
---|---|
leader | leader接收到删除请求后,记录一个标记,将自己设置为raft-group唯一节点(只保留一个副本节省空间),停止上报心跳,等到一个配置的ttl时间才真正删除。要考虑的问题: 1. store重启,要保证记录标记成功,meta处理response |
follower | 直接删除。要考虑的问题: 1.region之前就没有选出主,[A,B,C]至少有两个不可用,如果此时有一个副本是好的,可以将该副本按Leader流程处理,三副本都不可用的场景先不考虑 |
总结 | 可以选择一个健康的副本,将其设置为raft-group唯一节点(只保留一个副本节省空间),停止上报心跳,等到一个配置的ttl时间才真正删除 |
需要恢复时,meta主动向store发请求,让region重新上报心跳,只要在ttl时间内,这个机制可以保证数据快速恢复。
-
meta发送删除region的操作用一个队列进行,方便控制
-
删除表操作也引入ttl功能
meta根据region上报的心跳信息维护每个peer的状态在_region_peer_state_map中,为不同的状态定义了如下状态值:
enum PeerStatus {
STATUS_NORAML = 0; // 正常状态
STATUS_UNSTABLE = 1; // add_peer时正在catchup STATUS_ERROR = 3; // raft leader连不上peer,一般可能是peer对应实例挂掉,或者peer被误删了
STATUS_ILLEGAL_PEER = 4; // 无效的peer,add_peer false negitive的peer或者set_peer后残留的peer
STATUS_NOT_HEARTBEAT = 5; // region长时间未上报心跳到meta,meta将peer状态设置为STATUS_NOT_HEARTBEAT
STATUS_NO_LEADER = 6; // peer上报meta时如果没有leader时设置
STATUS_SET_PEER = 7; // 在执行OP_RECOVERY_ALL_REGION恢复reigon时表明该region是通过set_peer恢复(说明至少有一个peer存活)
STATUS_INITED = 8; // 在执行OP_RECOVERY_ALL_REGION恢复reigon时表明该region是通过init_region恢复(说明所有peer都没了)
};
meta为每个region维护一个有效的peer集合和无效的peer集合
struct RegionPeerState {
std::map legal_peers_state; // 有效集合
std::map ilegal_peers_state; // 无效集合
};
ThreadSafeMap _region_peer_state_map;
在leader上报心跳时会更新有效集合,在peer上报心跳时如果说自己没有leader那么有效集合和无效集合都可能被更新。
// peer没有leader
if (peer_info.has_exist_leader() && !peer_info.exist_leader()) {
bool legal_peer = check_legal_peer(master_region_info);
if (!legal_peer) {
new_peer_info.set_peer_status(pb::STATUS_ILLEGAL_PEER);
peer_state.ilegal_peers_state[instance] = new_peer_info;
} else {
new_peer_info.set_peer_status(pb::STATUS_NO_LEADER);
peer_state.legal_peers_state[instance] = new_peer_info;
}
_region_peer_state_map.set(region_id, peer_state);
}
通过发送QUERY_REGION_PEER_STATUS指令给meta查询peer有问题的region的信息,有问题的peer包括
- ilegal_peers_state中所有的peer
- legal_peers_state记录的peer状态有问题(region_healthy_check_function函数会定期检查region是否上报心跳,没有及时上报心跳会将peer状态设置为STATUS_NOT_HEARTBEAT) src/tools/script/meta_query_region_peers_status.sh
echo -e "query region peer status\n"
echo 'param: address'
curl -d '{ "op_type" : "QUERY_REGION_PEER_STATUS" }'
http://$1/MetaService/query
查询目的是查看region peer状态信息,判断region是否有问题,给之后恢复提供帮助,因为meta的信息是定时上报的,所以有滞后,进行恢复时需要更多的信息指导。
通过发送OP_RECOVERY_ALL_REGION指令给meta快速恢复有问题的region,包括两种
- 有peer存活的region,向每个peer查询log_index,同时询问是否有leader,没有leader时,选log_index最大的peer通过强制set_peer恢复该region的读写
- region的所有peer都未存活,此时根据meta保存的region信息选择一个peer通过init_region来恢复读写
- 可以按照resource_tags控制恢复集群 src/tools/script/meta_region_recovery.sh
#!/bin/bash
echo -e '\n'
echo -e "bad region recovery"
curl -d '{ "op_type" : "OP_RECOVERY_ALL_REGION", "resource_tags" : ["atom", "ocpc"] }' http://$1/MetaService/meta_manager
恢复之前必做步骤
-
检查是否有实例挂掉(机器宕机,进程退出不存在)
-
检查实例是否卡住(因为压力过大没有及时上报心跳,磁盘满了)