[Bug] Timer metrics check logs Offset not matched for Long.MAX_VALUE when no eligible timer slot exists

Đang mở
#11,498 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@Ajax-1 đang làm issue này rồi.

Từ ngày 28/10/2026.

  • #11499 của @Ajax-1 — đang mở

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
64/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
java

Hướng nghiên cứu

Read TimerMessageStore.checkAndReviseMetrics() and TimerWheel.checkPhyPos() in the store timer package, then inspect the existing timer store tests for metrics reconciliation and timer wheel lookups. Add regression coverage for an empty eligible wheel range and a valid slot; done means the empty range avoids a lookup at Long.MAX_VALUE, valid-slot behavior still works, and zero-count metrics reconciliation is preserved.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Runtime platform environment

Linux ARM64 (Kylin); isolated boundary probe also run on Windows x64.

RocketMQ version

5.5.1, using the official 5.5.1 store JAR. The deployed Proxy has an unrelated null-Settings guard; no Broker/store code was modified.

JDK Version

Production: JDK 17.0.19. Local isolated probe: JDK 17.0.18.

Describe the Bug

The scheduled TimerMessageStore.checkAndReviseMetrics() can emit a misleading Offset not matched warning when the timer wheel has no eligible slot but a TimerLog mapped file still exists.

Sanitized observed log:

WARN TimerScheduledThread1 - Offset not matched. Request offset: 9223372036854775807, firstOffset: 0, lastOffset: 104857600, mappedFileSize: 104857600, mappedFiles count: 1

We observed one warning on each of four Broker processes during the same scheduled metrics-check window. Immediately following logs showed the metric count for rmq_sys_REVIVE_LOG_DefaultCluster revised from 0 to 0, and the task completed in 31–41 ms. Timer processing queues and offset backlog were zero around that window. We have not observed message loss or a delivery stall caused by this warning.

Root cause analysis
  1. TimerWheel.checkPhyPos(readTimeMs, 0) initializes minFirst to Long.MAX_VALUE and returns that sentinel when no matching slot is found.
  2. checkAndReviseMetrics() passes this result directly to timerLog.getWholeBuffer(currOffsetPy) without checking the sentinel.
  3. MappedFileQueue.findMappedFileByOffset logs the out-of-range warning and returns null.
  4. The metrics scan breaks and performs its usual metrics update.
Steps to Reproduce

The following is a minimal, local-only probe of the boundary call chain, not a full Broker integration test. No Producer or Consumer is started. Run with the official 5.5.1 libraries:

Path root = Files.createTempDirectory("timer-offset-probe-");
TimerWheel wheel = new TimerWheel(root.resolve("timerwheel").toString(), 16, 1000);
TimerLog log = new TimerLog(root.resolve("timerlog").toString(), 104857600);
// Allocate a local file to represent retained TimerLog storage.
log.getMappedFileQueue().getLastMappedFile(0);
long now = System.currentTimeMillis() / 1000 * 1000;
long offset = wheel.checkPhyPos(now, 0);
assert offset == Long.MAX_VALUE;
assert log.getWholeBuffer(offset) == null;
// With the store-error logger enabled, the lookup emits the warning above.
wheel.shutdown();
log.getMappedFileQueue().shutdown(1000);

A local probe with an allocated TimerLog and an empty wheel confirmed the sentinel/null-lookup behavior. A subsequent valid-slot lookup still succeeded. Production logs supply the full scheduled-task observation.

Expected behavior

An empty eligible timer-wheel range should be handled explicitly without attempting a file lookup at Long.MAX_VALUE and without an alarming out-of-range warning. Preserve the existing metrics reconciliation semantics.

Suggested direction

Guard the sentinel before entering the scan loop. Avoid an unconditional early return from the entire method if that would skip the intended zero-count metrics reconciliation. Add empty-wheel and valid-slot regression coverage.

Related reports checked
  • #9947 / #9948: BLANK record / BufferUnderflowException.
  • #10165: metrics overwritten after timer-engine switch.
  • #10668: stale TimerLog references after CommitLog truncation.
    These appear to have different triggers from this empty-range sentinel case. Searches for Offset not matched, checkAndReviseMetrics, checkPhyPos, and 9223372036854775807 did not find an exact duplicate.
Source references

The same unguarded scan entry is present in develop at 592d59d12db356f8c98332d9e355a89d92590db3.

Ngôn ngữ chính
Java
Star
22.7k
Fork
12k
Merge trung bình
3 ngày 18 giờ
Pull request đã merge (30 ngày)
17

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của apache/rocketmq

Tất cả issue của apache/rocketmq

Issue tương tự

Thêm issue về Java

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.