ShardRouting source = startedShard.relocate(nodeId, expectedShardSize); ShardRouting target = source.getTargetRelocatingShard(); updateAssigned(startedShard, source); node(target.currentNodeId()).add(target); assignedShardsAdd(target); addRecovery(target); //找恢复源(这里用到的恢复源不一定是迁出节点的) changes.relocationStarted(startedShard, target);
@Nullable //给一个副本分片,返回一条“可以用来当恢复源”的主分片路由。
private ShardRouting findAssignedPrimaryIfPeerRecovery(ShardRouting routing) {
ShardRouting primary = null;
if (routing.recoverySource() != null && routing.recoverySource().getType() == RecoverySource.Type.PEER) {
List<ShardRouting> shardRoutings = assignedShards.get(routing.shardId());
if (shardRoutings != null) {
for (ShardRouting shardRouting : shardRoutings) {
if (shardRouting.primary()) { //这里只选主分片
if (shardRouting.active()) {
return shardRouting;
} else if (primary == null) {
primary = shardRouting;
} else if (primary.relocatingNodeId() != null) { //如果当前这个shardRouting还没active,并且旧的主分片正在作为迁移源往外迁移,
primary = shardRouting;
}
}
}
}
}
return primary;
}
完全正确 —— **“迁出节点”≠“恢复源节点”**:
1. `startedShard.relocate(...)` 只是**生成两条路由记录**:
- **源**:状态 `RELOCATING`,仍在**原节点**;
- **目标**:状态 `INITIALIZING`,在**新节点**。
2. 后续副本做 **PEER 恢复**时,**选源逻辑只看“哪条主分片路由当前能提供数据”**(通常就是那条 `RELOCATING` 源记录),**不管它物理上在哪个节点**;
因此恢复流量走向是:
**“选中的主分片路由所在节点” → 副本节点**
3. 如果主分片本身也在 relocating,**旧节点**上的 `RELOCATING` 源分片仍处于 `STARTED` 状态,**照样能当数据源**;
一旦旧主分片关闭、新主分片 `STARTED`,恢复源会自动切换到新节点。
**结论:**
**“迁出节点”只是路由表里的一个中间状态,真正的恢复源由 `findAssignedPrimaryIfPeerRecovery` 动态选择,两者没有绑定关系。**

2379

被折叠的 条评论
为什么被折叠?



