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

Vert.x SharedData能否可靠存储类LRU结构?有无低锁可变列表存储方案?

解决方案

1. 用AsyncMap的原子更新操作替代全局锁

不用给整个Map加锁,而是利用AsyncMap提供的get+replace原子组合操作处理列表更新,步骤如下:

  • 通过get(key)获取当前队列列表
  • 修改列表:添加新元素,若长度超过设定容量则移除最早的条目
  • 调用replace(key, oldList, newList)完成原子替换
  • 如果replace返回false,说明期间有其他节点修改了该值,重试整个流程即可

这种方式仅当并发修改同一个key时才会触发重试,锁粒度远小于全局锁,示例代码:

private void addToQueue(AsyncMap<String, List<String>> asyncMap, String key, String item, int maxSize) {
  asyncMap.get(key)
    .onSuccess(currentList -> {
      List<String> newList = currentList == null ? new ArrayList<>() : new ArrayList<>(currentList);
      newList.add(item);
      if (newList.size() > maxSize) {
        newList.remove(0); // 移除最早条目
      }
      asyncMap.replace(key, currentList, newList)
        .onSuccess(replaced -> {
          if (!replaced) {
            // 并发冲突,重试
            addToQueue(asyncMap, key, item, maxSize);
          }
        })
        .onFailure(err -> {
          // 处理错误
        });
    })
    .onFailure(err -> {
      // 处理错误
    });
}

2. 本地缓存+EventBus同步(适合读多写少场景)

如果队列访问有较强的局部性,可以在每个节点维护LocalMap的本地队列副本,更新逻辑如下:

  • 优先操作本地LocalMap里的队列:添加元素并检查容量,移除最早条目
  • 发送EventBus消息到集群内其他节点,通知它们同步更新对应key的队列
  • 其他节点收到消息后,更新自己的本地LocalMap副本

这种方式大部分操作都是本地的,仅同步时用到EventBus,完全避免分布式锁,但要注意最终一致性——短时间内不同节点的队列副本可能不一致,适合对一致性要求不高的场景。

3. 细粒度Key锁

给每个队列对应的key单独申请分布式锁,而非给整个AsyncMap加锁:

  • 通过SharedData.getLock(key)获取该key专属的锁
  • 锁获取成功后,执行get→修改列表→put的操作
  • 操作完成后释放锁

这样不同key的队列操作可以并行执行,只有同一key的并发请求才会互斥,锁竞争比全局锁小很多,示例代码:

private void addToQueueWithLock(SharedData sharedData, String key, String item, int maxSize) {
  sharedData.getLock(key)
    .onSuccess(lock -> {
      sharedData.<String, List<String>>getAsyncMap("my-queue-map")
        .onSuccess(asyncMap -> {
          asyncMap.get(key)
            .onSuccess(currentList -> {
              List<String> newList = currentList == null ? new ArrayList<>() : new ArrayList<>(currentList);
              newList.add(item);
              if (newList.size() > maxSize) {
                newList.remove(0);
              }
              asyncMap.put(key, newList)
                .onSuccess(v -> lock.release())
                .onFailure(err -> {
                  lock.release();
                  // 处理错误
                });
            })
            .onFailure(err -> {
              lock.release();
              // 处理错误
            });
        })
        .onFailure(err -> {
          lock.release();
          // 处理错误
        });
    })
    .onFailure(err -> {
      // 处理锁获取失败
    });
}

注意事项

  • 原子更新的重试次数要限制,避免无限循环
  • 容量检查逻辑要统一,确保所有节点执行相同的移除规则
  • 若用EventBus同步,要处理消息丢失的情况(比如添加消息重试机制)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:27:39