Lưu task trong một hàng đợi time-bucket / ưu tiên đánh khoá theo thời điểm đến hạn, chỉ poll các task đến hạn ngay bây giờ, rồi giao cho worker idempotent với giao nhận at-least-once. Đừng bao giờ quét 10 triệu hàng mỗi nhịp — index theo thời điểm bắn để mỗi lần poll chỉ chạm những gì đến hạn.
Kiến trúc
API ─▶ Task store (DB/Redis ZSET, score = due_ts) ── 10M tasks, sharded
│
Poller (leader per partition) ── ZPOPMIN due<=now ──▶ Ready queue (Kafka)
│ leader election (etcd/ZK) │
▼ ▼
other pollers idle/standby Worker pool (idempotent)
└─ ack ✔ / retry ✖ ─▶ DLQ
