[Bug] PD TTL cleanup deletes the marker-shaped name instead of the expired key, so expired values stay in the store until read
维护者通常 1 天内回复
评估
调研方向
Read hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/KvService.java, especially clearTTLData and getValue, then inspect core/KvServiceTest. Run the reported KvServiceTest#testTtlCleanupDeletesTheExpiredKey case and review how cleanup interacts with keepAlive and putTTL. Done means expired values and markers are removed safely without deleting a renewed value.
由索引模型根据 Issue 内容生成。
描述
Bug Type (问题类型)
logic (逻辑设计问题)
Before submit
- I have confirmed and searched that there are no similar problems in the historical issue and documents
Environment (环境信息)
- Server Version: PD on
masterat86c05ef9c(1.8.0-SNAPSHOT); the code below is unchanged since43cae1d2e(#2478, 2024-04-19) - Backend: PD's own RocksDB metadata store (the KV service), checked without raft as the
pd-core-testsuite runs it - OS: macOS, JDK 17.0.20.1
- Data Size: one key
Expected & Actual behavior (期望与实际表现)
A key written with a TTL (KvService.put(key, value, ttl), the KV putTTL RPC, PD locks, the KV watch registrations, the balance-shard flag) gets a marker K@T@<expireAt>@<key> next to it. TaskScheduleService runs KvService.clearTTLData() every second on the leader, and it should delete the expired key and its marker.
It deletes a different key. clearTTLData takes the key from the marker after key.indexOf(KV_DELIMITER, 2), which is the @ right after T, so it deletes <expireAt>@<key>, a key that never exists, and then removes the marker. hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/KvService.java at 86c05ef9c, lines 300 to 306:
for (KV kv : kvList) {
String key = new String(kv.getKey());
int index = key.indexOf(KV_DELIMITER, 2);
String delKey = key.substring(index + 1);
delete(delKey);
meta.remove(kv.getKey());
}
The same expression on a real marker key:
key = "K@T@1729430000000@ttl-test/a"
index = 3
delKey = "1729430000000@ttl-test/a"
Measured 2026-10-20 on master 86c05ef9c with JDK 17.0.20.1, by adding this test to hg-pd-test's core/KvServiceTest and running mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-core-test -Dtest='org.apache.hugegraph.pd.core.KvServiceTest#testTtlCleanupDeletesTheExpiredKey':
KvService service = new KvService(getPdConfig());
service.put("ttl-test/a", "old", 1L);
byte[] storeKey = service.getStoreKey("ttl-test/a");
Thread.sleep(20L);
service.clearTTLData();
Assert.assertNull(service.getMeta().getOne(storeKey)); // fails: the value is still stored
java.lang.AssertionError: expected null, but was:<[B@1b18fa79>
at org.apache.hugegraph.pd.core.KvServiceTest.testTtlCleanupDeletesTheExpiredKey(KvServiceTest.java:75)
What this does and does not break:
- Reads are not affected:
getandscanWithPrefixgo throughgetValue, which returns nothing for an expired value and removes it then. So a reader never sees an expired value. - An expired value that nobody reads again stays in the store for good, with no marker left that would ever delete it.
keepAlive(key)does not check the expiry, so it revives an expired lease that nobody has read yet, which the cleanup was meant to have deleted within a second.getValue(line 130) removes the marker under a wrong name too (getTTLStoreKey(new String(keyBytes), ...)passes the store key,K@<key>, where the key is expected), so its marker is left for the cleanup.
The parse fix is small (start the search after K@T@), but the cleanup then deletes keys that writers may be renewing at that moment: a keepAlive or a putTTL of the same key that lands between the cleanup's read and its delete would be deleted. The delete should be conditional at the apply: only while the marker still exists and the key still holds the expired value it read.
Vertex/Edge example (问题点 / 边数据举例)
N/A
Schema [VertexLabel, EdgeLabel, IndexLabel] (元数据结构)
N/A
- 主要语言
- Java
- 星标
- 3.2k
- 派生
- 640
- 平均合并
- 1 天 12 小时
- 30 天内合并 PR
- 98
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
apache/hugegraph 的其他 Issue
-
[Bug] PD task REST: balanceLeaders throws a bare HTTP 500 during the balance-shard window, and task responses cannot be told apart from a no-op or a follower answer可能已有人在做 @pallavithegod 于 6 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 70/100
apache/hugegraph#3231 · 2 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 55/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 35/100
维护者通常 1 天内回复
-
[Task] Establish systematic performance baselines and optimization tracking可能已有人在做 @contrueCT 于 6 天前认领。 未关闭help wanted improvement rust
难度 5/5 一周以上 新手友好度 12/100
apache/hugegraph#3346 · 2 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
[Bug] CI accepts obsolete PR targets after retargeting or force-push可能重新可做 关联的 PR 已关闭且未合并。 未关闭
难度 3/5 1-2 天 新手友好度 25/100
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 79/100
checkstyle/checkstyle#22145 ·
维护者通常 1 天内回复
-
rset command throws NPE in ResultsFormat.guessSyntax可能已有人在做 @Ostrzyciel 今天认领。 未关闭bug
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
enhancement good first issue help wanted
难度 2/5 1-3 小时 新手友好度 83/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 82/100
objectionary/eo#9593 ·
维护者通常 1 天内回复
-
release bug
难度 2/5 1-3 小时 新手友好度 68/100
OpenLiberty/open-liberty#36124 ·
维护者通常 1 天内回复