- Write-back 缺失 pending 注册:
get()在 Redis miss → MySQL hit 时写回 Redis 的同时,现在会自动将 key 注册到yrdatabase:pending排序集,使 sweep 能对这类 key 执行 TTL 续期。
caching.sweepIntervalSeconds支持配置化,不再硬编码为 30 秒。- 启动时校验三条约束,违反时打印 WARN 日志:
sweepIntervalSeconds ≤ refreshThresholdsweepIntervalSeconds ≤ autoSyncIntervalSecondsdefaultTTL > sweepIntervalSeconds
- 配置文件注释详细说明了各约束的含义。
DatabaseManager新增setOnlineChecker(Predicate<String> checker)接口方法。- 平台层(Allay / Nukkit)注入在线判断逻辑,sweep 只对在线玩家续期 TTL。
- Allay 实现:从 cacheKey 末段提取 playerId,查询
PlayerEventListener.isOnline()。
- 原固定缓冲扫描(
SWEEP_BUFFER_SECONDS=60)替换为两条独立扫描:- Refresh 扫描:
TTL ≤ refreshThreshold且玩家在线 →expire(defaultTTL)+ 更新 pending 分值。 - Persist 扫描:
TTL ≤ autoSyncIntervalSeconds且玩家离线 → 持久化到 MySQL/SQLite +zrem。
- Refresh 扫描:
- 新增
sweepRefreshKey():续期失败(key 已过期)时自动回退到持久化流程。
get()缓存命中后,若autoRefresh=true且剩余 TTL< refreshThreshold,自动调用expire()并更新 pending 分值,无需等待 sweep。
- MySQL Provider 新增
hikariConfig.setKeepaliveTime(60000),每 60 秒 ping 一次空闲连接,防止 MySQL 在maxLifetime前关闭连接导致 HikariCP 报 "Failed to validate connection"。
- 根因:autoSync 路径(
persistOnly → saveToPersist)调用了zrem,导致 key 从 pending 中移除,后续 sweep 的 refresh 扫描找不到该 key。 - 修复:
saveToPersist不再调用zrem。只有persistAndClear、processPendingKey、processPendingKeySync在明确完成数据生命周期时才执行zrem。
setNxEx改用new SetArgs().nx().ex(ttl)直接实例化,避免 Shadow JAR 重定位不更新InnerClasses属性导致的NoClassDefFoundError。
- Redis key 不存在时,
persistOnly现在会主动zrem移除 pending 中的残留条目,避免 sweep 反复处理已失效的 key。
syncAllPending()方法及其定时任务已移除。相关功能完全由双扫描 sweep 接管,逻辑更清晰、无竞态。- 移除
SYNC_LOCK_KEY常量。
config.yml 新增字段(caching 节):
caching:
# pending 集合扫描间隔(秒)
# 必须满足:
# sweepIntervalSeconds ≤ refreshThreshold
# sweepIntervalSeconds ≤ autoSyncIntervalSeconds
# defaultTTL > sweepIntervalSeconds
# 推荐值:min(refreshThreshold, autoSyncIntervalSeconds) 的一半
sweepIntervalSeconds: 30初始版本,基础 Redis + MySQL/SQLite 双层存储,CACHE_FIRST 策略,pending 排序集持久化机制。