Infinispan 中集群侦听器的可扩展性,用于具有许多键的缓存?

Posted

技术标签:

【中文标题】Infinispan 中集群侦听器的可扩展性,用于具有许多键的缓存?【英文标题】:Scalability of Clustered Listeners in Infinispan for Cache with many Keys? 【发布时间】:2022-01-17 14:55:23 【问题描述】:

在 Infinispan 中使用嵌入式缓存时,我希望有一个过滤的集群侦听器,每次更新特定键时都会收到通知。我的问题是,缓存检查值更新时应通知哪些侦听器所需的时间是 O(n) 操作,集群中的节点越多,性能也没有提升。这意味着我无法扩展集群以处理大量密钥。

这可能是因为CacheNotifierImpl 中的以下代码 sn-p 会通过所有侦听器:

   private CompletionStage<Void> doNotifyModified(K key, V value, Metadata metadata, V previousValue,
         Metadata previousMetadata, boolean pre, InvocationContext ctx, FlagAffectedCommand command) 
      if (clusteringDependentLogic.running().commitType(command, ctx, extractSegment(command, key), false).isLocal()
            && (command == null || !command.hasAnyFlag(FlagBitSets.PUT_FOR_STATE_TRANSFER))) 
         EventImpl<K, V> e = EventImpl.createEvent(cache.wired(), CACHE_ENTRY_MODIFIED);
         boolean isLocalNodePrimaryOwner = isLocalNodePrimaryOwner(key);
         Object batchIdentifier = ctx.isInTxScope() ? null : Thread.currentThread();
         try 
            AggregateCompletionStage<Void> aggregateCompletionStage = null;
            for (CacheEntryListenerInvocation<K, V> listener : cacheEntryModifiedListeners) 
               // Need a wrapper per invocation since converter could modify the entry in it
               configureEvent(listener, e, key, value, metadata, pre, ctx, command, previousValue, previousMetadata);
               aggregateCompletionStage = composeStageIfNeeded(aggregateCompletionStage,
                     listener.invoke(new EventWrapper<>(key, e), isLocalNodePrimaryOwner));

listener.invoke 函数检查每个侦听器的过滤器以查看是否应该调用该函数。这意味着每个节点都必须为每个事件遍历每个侦听器,只是为了发现几乎所有侦听器都是无操作的。

是否有任何平滑的非 O(n) 方法来添加集群范围的侦听器,其中核心库标识侦听器应仅针对特定键触发?

在使用infinispan-core 库的13.0.0 版本时发现此行为。

【问题讨论】:

【参考方案1】:

在发送到集群监听器注册的节点之前,您可以提供在主节点上应用的过滤器甚至转换器。如果过滤器拒绝该事件,它将不会远程发送它,也不会通知侦听器。

提供的转换器可用于更改发送到侦听器的值,这可能类似于从键或值返回单个变量而不是整个事物,可能会减少有效负载大小。

https://infinispan.org/docs/stable/titles/developing/developing.html#event_filtering_and_conversion

请注意,这意味着您提供的过滤器和转换器必须可由 Infinispan 编组,因为我们在节点之间运送它们。

【讨论】:

问题是,一旦我在缓存中修改了一个集群侦听器,它的过滤器就会针对 每个 发生的修改事件尝试 每个 节点。这意味着如果我有一个带有 1_000_000 个键和侦听器的缓存的集群,则此缓存中的每个修改都必须检查 1_000_000 个过滤器以查看它们是否与更改相关。这就是为什么更新的执行时间会随着侦听器的数量线性增长,这是我需要规避的。 它不在具有集群监听器的每个节点上。过滤器仅适用于所述密钥的主要所有者。如果是这样,那么您遇到了错误。每个过滤器都会针对主要所有者上的每个事件进行评估;关键是要避免事件的远程传输,而不是对所述过滤器的评估。事件的远程传输比应该全部在内存中的过滤器评估要昂贵几个数量级。 当您说“过滤器仅应用于所述密钥的主要所有者”时,您的意思是过滤器仅针对该节点上的事件返回 true,还是您的意思是过滤器仅评估主要所有者?如果过滤器也在所有非主要所有者节点上评估密钥(它永远不会是真的)我有我的问题中提到的 O(n) 情况,不幸的是我的问题没有解决。

以上是关于Infinispan 中集群侦听器的可扩展性,用于具有许多键的缓存?的主要内容,如果未能解决你的问题,请参考以下文章

在 Keycloak 集群的 Infinispan 缓存中存储用户会话的确切用途是啥?

防止Infinispan集群化

在 Wildfly 10.1 中禁用 Infinispan 集群

JBoss EAP 6.4 Infinispan 集群缓存网络问题

Infinispan 集群锁性能不会随着节点的增加而提高吗?

Keycloak - Infinispan Redis 缓存存储