如何直接向IgniteCache中的List类型值添加元素?
Ignite缓存内集合直接修改的解决方案
你遇到的问题本质是:Ignite默认返回的缓存值是脱离缓存上下文的副本(或不可变视图),直接修改cache.get(key)拿到的List,变更不会同步回缓存——因为Ignite无法感知到集合内部的修改操作。
无需取出List再重新放入缓存的可行方法如下:
推荐方案:使用invoke原子操作API
这是Ignite官方推荐的修改缓存内嵌套对象的方式,它会在存储该缓存条目的节点上原子执行修改逻辑,无需将整个List拉取到客户端,同时保证并发安全。
示例代码:
// 向指定key对应的List中添加元素 cache.invoke(key, (entry, args) -> { // 获取缓存内的原List(如果不存在则初始化) List<Integer> list = entry.getValue(); if (list == null) { list = new ArrayList<>(); entry.setValue(list); } // 直接修改缓存内的List list.add((Integer) args[0]); return null; }, value); // value是要添加的元素
为什么直接cache.get(key).add(value)不生效?
Ignite为了保证缓存的一致性和性能,返回的集合对象通常是原对象的快照拷贝,或是受Ignite管控的不可变视图。即使你拿到的是原对象,集合内部的add操作属于对象内部状态变更,不会触发Ignite的缓存更新机制,因此变更不会被持久化到缓存中。
注意事项
- 避免使用先
get再put的方式(比如List<Integer> list = cache.get(key); list.add(v); cache.put(key, list);),这种方式在并发场景下会导致数据丢失,因为多个线程可能同时修改同一个List后覆盖彼此的变更。 invoke操作是原子性的,同一时间只有一个线程能修改该缓存条目,能有效避免并发冲突。
内容的提问来源于stack exchange,提问作者Ritvik Rohatgi
相关产品推荐
相关产品推荐

