[ 
https://issues.apache.org/jira/browse/SOLR-18558?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18129660#comment-18129660
 ] 

Jerry Chung commented on SOLR-18558:
------------------------------------

Additional Details:

*Why nothing self-heals* (verified by grep across {{{}solr/core{}}}):
 * {{zkController.register()}} is only invoked from core-load time 
({{{}CoreContainer.java:1002{}}} background, {{:1442/:1451}} sync) and 
{{ZkController.onReconnect()}} (re-registers all cores {*}only on ZK session 
expiration/reconnect{*}). There is no background task that re-registers a core 
that is loaded locally but {{DOWN}} in cluster-state.

 * *This also explains why our RELOAD did nothing* — a core RELOAD re-opens the 
index but the re-registration path does not re-invoke {{registerInZk}} for an 
already-registered core. The only two things that re-trigger registration are 
exactly the two we observed working: *a full JVM restart* (re-runs core load → 
{{{}registerInZk{}}}) and a ZK session drop.

*Minimal fix candidates:*
 # Bounded retry with backoff in {{registerInZk}} (or 
{{{}ZkController.register{}}}) on 
{{{}SolrException(SERVICE_UNAVAILABLE){}}}/{{{}NoNode{}}} — the znode race is 
transient by nature; a few retries with escalation would have healed n91 within 
seconds.

 # Stop swallowing {{NoNodeException}} in 
{{ShardLeaderElectionContextBase.runLeaderProcess}} — reschedule the election 
({{{}LeaderElector.retryElection{}}}) instead of silently returning.

 # A watchdog that detects "core loaded locally + {{DOWN}} in cluster-state for 
> N minutes" and re-triggers registration (this is the safety net that would 
have caught n91 at ~01:30 instead of 16:44).

> Stale leader election znode left after DELETEREPLICA blocks the remaining 
> replica from becoming leader; registration fails with "Could not get leader 
> props"
> ------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: SOLR-18558
>                 URL: https://issues.apache.org/jira/browse/SOLR-18558
>             Project: Solr
>          Issue Type: Bug
>          Components: Server, SolrCloud
>    Affects Versions: 10.0
>            Reporter: Jerry Chung
>            Priority: Major
>
> After a DELETEREPLICA on a shard, the election znode of the deleted replica 
> was left in /collections/<c>/leader_elect/<shard>/election, at the head of 
> the queue. The remaining replica joined the election behind it and never ran 
> its leader process. Registration of its core timed out after about 13 
> minutes, and the shard stayed unloaded with no leader. Nothing logged that 
> the replica was waiting on another election node.
> Environment
> - Solr 10.0.0 (SolrCloud), ZooKeeper 3.9.4
> - The shard has one replica, core_node93 (replica_n91)
> - Node was restarted at 03:11 (clean shutdown) and the core loaded at 03:13:08
> - DELETEREPLICA had earlier removed core_node94 from the same shard. [The 
> node hosting core_node94 was live at the time but possibly busy. Add the time 
> and the Overseer/collection-API log if available.]
> Observed
> 1. ZkController.register → getLeader (ZkController.java:1419) polls 
> /collections/<c>/leaders/<shard>/leader once a second for leaderVoteWait + 
> 600000 ms. At 03:26:09 it failed:
> SolrException: Could not get leader props  (ZkController.getLeaderProps:1715)
> Caused by: KeeperException$NoNodeException: NoNode for 
> /collections/<c>/leaders/shard22/leader
> SolrException: Error getting leader from zk for shard shard22  
> (ZkController.getLeader:1661)
> ZkContainer: Exception registering core <c>_shard22_replica_n91
> 2. Election queue:
> $ solr zk ls /collections/<c>/leader_elect/shard22_v10/election
> 144115188964327726-core_node94-n_0000000001
> 216172782927479120-core_node93-n_0000000005
>    core_node94 no longer exists in the clusterstate. Its node is ahead of 
> core_node93.
> 3. Terms also hold stale entries for the deleted replica:
> {"core_node94":7, "core_node93":8, "core_node94_recovering":1}
>    These don't block core_node93: it has the max term and no _recovering 
> marker, so canBecomeLeader is true.
> 4. Between 03:13:08 and the timeout, the registration thread logged only 
> ShardLeaderElectionContextBase make sure parent is created 
> .../leaders/shard22_v10. There were no Enough replicas found, I may be the 
> new leader, Our node is no longer in line to be leader or Will not register 
> as leader lines. I found no ZK session expiry, disconnect or reconnect in the 
> log from 03:11 to 03:40.
> Why the replica waits silently
> In LeaderElector.checkIfIamLeader (line 125 onward), a replica that isn't 
> first in line only sets a watch on the node below it. The only log message 
> there is at DEBUG ("Watching path ... to know if I could be the leader"). A 
> stale head-of-queue node therefore blocks the shard with no visible warning.
> The stale node is ephemeral, so some ZK session was still holding it. [Add 
> the owner of session 144115188964327726, converted to hex, from the ZK dump 
> command.]
> Suspected cause (not confirmed or reproduced)
> DELETEREPLICA cleans up terms and the election node only when UNLOAD reaches 
> the replica's node. unregister is the only place that does it 
> (ZkController.java:1964-1981). The paths below can leave the election node 
> behind, particularly if the node is slow or busy:
> - DeleteReplicaCmd.java:311-332: UNLOAD is sent only if the node is live. If 
> the node is too slow, waitForCoreNodeGone times out after 30s and 
> deleteCoreNode removes the replica from the clusterstate anyway. The core may 
> still be loading, registering or electing on that node. A non-live node skips 
> UNLOAD entirely, so terms and election nodes are left behind.
> - ShardLeaderElectionContext.runLeaderProcess (line 110): if (core == null) 
> \{ return; } ("shutdown or removed") returns without calling 
> cancelElection(). A node that was already joined stays in the queue until the 
> JVM's session ends.
> - ZkController.unregister vs register: if unregister runs before the 
> registration thread calls joinElection, it finds no context and cancels 
> nothing. The registration thread then creates the election znode and context 
> (ZkController.java:1743-1749), and nothing cancels them afterward.
> - ShardLeaderElectionContext.rejoinLeaderElection (line 503): it checks only 
> cc.isShutDown(), not whether the context is still registered. After 
> unregister has cancelled and removed the context, it can rejoin and leave an 
> election node that nothing owns.
> Expected
> - After DELETEREPLICA completes, no election znode or terms entry remains for 
> the deleted replica.
> - A replica waiting behind another election node logs it at WARN, naming the 
> node it waits on.
> - A shard whose only live replica is behind a stale election node recovers on 
> its own.
> Impact
> The shard is unloaded and has no leader, so it can't serve queries or index. 
> The registration thread blocks for 13 minutes (with default leaderVoteWait), 
> then fails.
> Workaround
> 1. Delete the stale election znode: solr zk rm 
> /collections/<c>/leader_elect/<shard>/election/<stale-node> (add -z <zkHost> 
> if needed).
> 2. Reload the core or restart the node. The registration thread has already 
> given up.
> 3. Optionally remove the stale entries from terms/<shard>.
> Proposed fixes (for discussion)
> 1. In runLeaderProcess, call cancelElection() before returning when the core 
> is null.
> 2. After joinElection in register, re-check that the replica still exists in 
> the clusterstate. Cancel and bail out if it doesn't.
> 3. In rejoinLeaderElection, skip the rejoin if the context is no longer in 
> electionContexts.
> 4. In checkIfIamLeader, log at WARN when waiting on a node whose replica 
> isn't in the clusterstate.
> 5. When DELETEREPLICA targets a non-live node, remove the replica's terms 
> entries.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to