Repository navigation
[ISSUE #10982] Cache serialized topic route responses on demand - #11476
Palaiologos1453 wants to merge 1 commit into
Conversation
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Review by github-manager-bot
Summary
This PR adds an opt-in cache for serialized topic route responses in the NameServer, addressing #10982. The cache is disabled by default (routeInfoCacheMaxBytes=0), startup-only, and uses FIFO eviction with a weight budget. Effective route mutations advance a global revision for invalidation. The implementation is deliberately conservative — no eager cache rebuilding on broker registration, and the docs clearly describe limitations.
Findings
-
[Info]
NamesrvConfig.java:35-38— Good documentation on the new config field. AddingrouteInfoCacheMaxBytesto the config blacklist (configBlackList) is correct — prevents runtime changes to a startup-only option. -
[Info]
RouteInfoManager.java— The globalrouteDataRevisionapproach is clean. Only effective mutations increment the revision; unchanged registrations and heartbeats preserve cached responses. This avoids unnecessary invalidations during normal broker heartbeat cycles. -
[Warning]
TopicRouteDataCache.java— TheinsertionOrderLinkedHashMap is used for FIFO eviction, but I see it is accessed input()andevict()methods. Please confirm that all accesses toinsertionOrderare properly synchronized (either under the same lock or the map is otherwise thread-safe).LinkedHashMapis not thread-safe, and concurrent modifications could cause issues. -
[Info]
TopicRouteDataCache.java:49-54— The 5-minute TTL check (System.nanoTime() - entry.createdNanos >= TimeUnit.MINUTES.toNanos(5)) is a good safety mechanism. Entries that are not accessed for 5 minutes will be refreshed on next lookup, preventing stale data from persisting indefinitely. -
[Warning] The global revision means that any route change (even for an unrelated topic) invalidates the entire cache. In a large cluster with frequent route updates, this could significantly lower hit rates. The PR description acknowledges this tradeoff, but consider adding a metric (e.g., cache hit/miss ratio) so operators can tune
routeInfoCacheMaxBytesbased on actual workload patterns. -
[Info]
RouteInfoManager.java— Releasing the read lock before serialization on cache miss is a good optimization. This prevents the cache fill from blocking other readers while JSON encoding is in progress. -
[Info] The test coverage is excellent — 27 tests covering reuse, invalidation, queue/address/zone/filter changes, topic deletion/recreation, permission changes, static mappings, acting-master transitions, KV ordering, JSON selection, capacity limits, zone hook isolation, and concurrent fill scenarios. The JMH benchmarks in the PR description show meaningful throughput improvements for repeated queries.
Suggestions
-
Thread safety of
insertionOrder: IfLinkedHashMapaccesses are not all under a single lock, consider usingConcurrentLinkedHashMapor synchronizing theput/evictmethods. Alternatively, document the synchronization contract clearly. -
Configurable TTL: The 5-minute refresh interval is hardcoded. Consider making it configurable via
NamesrvConfig(e.g.,routeInfoCacheTtlMinutes) so operators can tune it based on their route change frequency. -
Cache metrics: Add JMX metrics for cache hits, misses, and evictions. This would help operators understand whether the cache is providing value and whether
routeInfoCacheMaxBytesis appropriately sized. -
Documentation: The English docs (
docs/en/namesrv-route-cache.md) are well-written. Consider adding a Chinese version (docs/cn/namesrv-route-cache.md) for consistency with other NameServer documentation.
Cross-repo Note
This PR only affects the NameServer. No changes are needed in apache/rocketmq-clients since the cache is transparent to clients.
Overall
This is a well-designed, conservative approach to route response caching. The default-off behavior and clear documentation of limitations make it safe to merge. The main concerns are thread safety of the LinkedHashMap and the potential for low hit rates in high-churn clusters. The test coverage is comprehensive and the JMH results are promising.
Automated review by github-manager-bot
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Review by github-manager-bot
Summary
Adds an opt-in, startup-only cache for serialized topic route responses in NameServer. Uses a global revision counter for invalidation — effective route mutations advance the revision, while unchanged registrations and heartbeats preserve cached responses. Default disabled (0 bytes), FIFO eviction, bounded by weight budget.
Findings
- [Info] The global revision approach is clean and avoids walking/rebuilding the cache on registration. The revision check in
pickupTopicRouteDataEncodedensures a fill racing a mutation cannot be reused by later requests observing the newer revision. - [Info] Serialization outside the route lock is correct and important — the read lock is held only to detach mutable data, then released before encoding. This prevents serialization from blocking registration.
- [Info] The
lockedflag inpickupTopicRouteDataproperly handles the case wherelockInterruptibly()throws before acquiring the lock, preventing an illegal unlock. Good defensive fix. - [Info] Thread interruption is properly propagated via
Thread.currentThread().interrupt()in the catch block. - [Info] FIFO eviction with hits not touching bookkeeping is a good trade-off — avoids contention on the hot path. The 5-minute refresh interval prevents stale entries from persisting indefinitely.
- [Info] Comprehensive test coverage including race conditions (fill paused across mutation), zone hook isolation, oversized responses, and all mutation types. JMH benchmarks with honest uncertainty analysis are appreciated.
Suggestions
- The
TopicRouteDataCache.putmethod issynchronized, which serializes all fills. Under high fill rates (many cache misses), this could become a bottleneck. Consider using aConcurrentLinkedDequeor similar for the insertion order, or accept the contention as acceptable given fills are rare compared to hits. The current design is safe and correct; this is a future optimization consideration. - The documentation in
docs/en/namesrv-route-cache.mdis excellent — clear, honest about limitations, and includes benchmark methodology. Consider adding a Chinese version underdocs/cn/for consistency with other NameServer docs. - The
routeInfoCacheMaxBytesis added to the config blacklist, preventing runtime changes. This is correct for a startup-only option, but consider logging a warning if someone tries to change it at runtime via the admin API.
Overall this is a well-designed, conservative approach to route caching. The opt-in default, clear documentation, and comprehensive testing make this safe to merge.
Automated review by github-manager-bot
|
The automated review has completed. @RongtongJin @lizhimins, could you please take a look at the design and invalidation approach when convenient? The cache is disabled by default, and the PR includes the JDK 8 NameServer test results and local query/registration benchmark details. |
Which Issue(s) This PR Fixes
Fixes #10982
Brief Description
getRouteInfoByTopiccurrently copies route data and encodes it for every query. Add an opt-in cache of encoded responses so repeated queries of stable routes reuse the response body.routeInfoCacheMaxBytesdefaults to0(disabled), is startup-only, and bounds retained encoded bodies, keys and estimated entry overhead. Oversized responses remain uncached. Cache misses populate only the requested JSON variant; both variants share the weight budget.orderTopicConffrom KV on each query and validate its value and the acting-master setting on hits. Zone filtering transforms a decoded copy and does not alter the shared cache body.This takes a deliberately conservative approach to #4246: no eager route cache rebuilding in broker registration, default off, and a fixed memory budget. The global revision can lower hit rates when unrelated routes change; an undersized cache can churn and be slower than uncached lookup. The docs describe these limits. This is a first implementation for design review, not a claim that all large-cluster cases are solved.
How Did You Test This Change?
mvn -B -f namesrv/pom.xml verify -Djacoco.skip=true— 136 tests, 0 failures/errors/skips; Checkstyle and SpotBugs passed. No SpotBugs suppression was added. JaCoCo was disabled for these local runs.RequestProcessorTestreflective access toField.modifiersthat fails on this JDK; the full successful verification above used JDK 8.mvn -B -f namesrv/pom.xml apache-rat:checkpassed (0 unapproved/unknown files).Local JMH (Windows x86_64, Ryzen 9 7945HX, OpenJDK 17.0.17, JMH 1.19, fixed 512 MiB heap, 8 brokers / 10,000 queried topics; 2 forks, 3 × 1s warmup, 3 × 1s measurement, 1 thread,
-prof gc):The registration uncertainty intervals overlap; no registration speedup is claimed. The upstream control loads
RouteInfoManagercompiled from base commit57c2dc04ahead of the benchmark classpath. Registration payload versions change while effective routes remain equivalent. A 4-reader / 1-registration group also completed; its subgroup results, raw query iteration means and reproduction instructions are indocs/en/namesrv-route-cache.md. The cache fits the working set in the reported hit-path results. These are method-level measurements, not end-to-end throughput or a 300-broker-scale validation.