You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大数量下ConcurrentHashMap出现重复键问题求助

问题原因及解决方案

核心原因:非原子性的“检查-插入”操作引发竞态条件

你遇到的重复问题本质是:ConcurrentHashMap的单个操作线程安全,但组合的“检查key是否存在+插入key”操作并非原子性,在50线程高并发场景下触发了竞态条件:

  • 当两个线程同时处理同一个rowkey时,线程A执行containsKey(key)返回false,线程B在A执行put(key)前也执行containsKey(key)返回false,最终两个线程都完成了put操作,导致同一个key被重复存入。
  • 小数据量时线程竞争概率极低,因此不会触发问题;当数据量接近百万级、线程数较多时,竞态条件触发概率显著提升,所以稳定出现重复,且重复条目随线程调度时机变化而不同。

错误逻辑示例(你大概率采用了类似写法)

如果你的去重逻辑是如下代码,必然会出现重复:

// 错误:containsKey和put是两个独立操作,存在竞态窗口
if (!globalConcurrentMap.containsKey(rowkey)) {
    globalConcurrentMap.put(rowkey, "标记值");
    // 写入HBase的逻辑
}

正确的原子性去重方案

使用ConcurrentHashMap提供的原子性方法putIfAbsent,它会在同一个原子操作内完成“检查key是否存在+不存在则插入”的逻辑:

// 正确:putIfAbsent是原子操作,确保同一个key只会被插入一次
if (globalConcurrentMap.putIfAbsent(rowkey, "标记值") == null) {
    // 仅当key之前不存在时,才执行写入HBase的逻辑
}

putIfAbsent返回值规则:

  • 若key不存在,插入并返回null,此时进入分支执行写入;
  • 若key已存在,直接返回已有值,跳过写入逻辑。

这种写法能彻底避免多线程下的竞态条件,保证去重结果与MySQL distinct的结果一致。

内容的提问来源于stack exchange,提问作者william

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:03:15