unbridled-41 opened a new issue, #11043:
URL: https://github.com/apache/rocketmq/issues/11043

   ### Before Creating the Bug Report
   
   - [X] I found a bug, not just asking a question, which should be created in 
[GitHub Discussions](https://github.com/apache/rocketmq/discussions).
   - [X] I have searched the [GitHub 
Issues](https://github.com/apache/rocketmq/issues) and [GitHub 
Discussions](https://github.com/apache/rocketmq/discussions) of this repository 
and believe that this is not a duplicate.
   - [X] I have confirmed that this bug belongs to the current repository, not 
other repositories of RocketMQ.
   
   ### Runtime platform environment
   Linux, JDK 21, develop (ff8f6f74c)
   
   ### RocketMQ version
   5.x develop
   
   ### Describe the Bug
   
   Since the introduction of `BatchUnregistrationService`, the decision that a 
broker should be unregistered (heartbeat expiry in `scanNotActiveBroker`, or a 
channel-close event) and its execution are separated by queue latency and 
blocking `closeChannel` I/O. `setupUnRegisterRequest` matches only by 
`clusterName + brokerAddr` in `brokerAddrTable`, and `unRegisterBroker` then 
removes **unconditionally**:
   
   - `brokerLiveTable.remove(brokerAddrInfo)` (no freshness re-check),
   - the addr mapping via `removeIf(item -> 
item.getValue().equals(brokerAddr))` (matching by address only, ignoring the 
`brokerId` carried in the request — while `registerBroker` carefully 
distinguishes ids for the same address),
   - and all topic QueueDatas for the broker.
   
   If the broker is actually alive and re-registers between the expiry decision 
and the queued execution (e.g. after a namesrv GC pause / scan backlog that 
expired live brokers), the brand-new registration — new `BrokerLiveInfo`, 
address mapping and topic QueueDatas — is deleted. The live broker then 
vanishes from all routes until its next periodic re-registration 
(`registerNameServerPeriod`, ~30s), producing cluster-wide TOPIC_NOT_EXIST / 
no-route windows. The same defect lets a queued unregister for a slave at addr 
A remove a master entry re-registered at the same addr A, because removal 
matches on address only.
   
   Note the `onChannelDestroy(Channel)` overload already guards by channel 
identity (`entry.getValue().getChannel() == channel`) at decision time — but 
the `BrokerAddrInfo` overload (used by the expiry scan) has no such check, and 
even the channel guard cannot cover the decision-to-execution gap.
   
   ### Steps to Reproduce
   
   1. Register broker (channel1).
   2. Fire the destroy event for it: `onChannelDestroy(new 
BrokerAddrInfo(cluster, addr))` — the unregister request is queued 
asynchronously.
   3. Re-register the same broker with channel2 (fresh registration).
   4. Let the queued request execute: the fresh registration is removed; 
`pickupTopicRouteData` returns null for its topics.
   
   ### Expected Behavior
   
   A destroy-derived unregister must not remove a registration that is newer 
than the event it was derived from: if the current live entry for the address 
belongs to a different (newer) channel, the queued request is stale and must be 
skipped. Explicitly initiated unregisters (the broker's own UNREGISTER_BROKER 
request) remain unconditional.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to