簡體   English   中英

是否可以在一次操作中通過鍵從 Ignite 緩存中獲取多個值,在服務器端應用額外的過濾?

[英]Is it possible to get multiple values from an Ignite cache by their keys, applying additional filtering server-side, in one operation?

我有一個點燃緩存:

IgniteCache<String, Record> cache;

給出了這個緩存的一組鍵。 我需要執行以下操作:

  1. 獲取具有指定鍵的記錄
  2. ...但另外通過一些動態定義的邏輯過濾它們(例如“字段name的值John ”)
  3. ... 盡可能快地完成
  4. ...根據交易

我嘗試的一種方法是使用getAll()方法並在我這邊應用過濾:

cache.getAll(keys).values().stream()
        .filter(... filter logic...)
        .collect(toList());

這可行,但如果附加過濾器具有高選擇性(即它拒絕大量數據),我們將浪費大量時間通過網絡發送不需要的數據。

另一種選擇是使用掃描:

cache.query(new ScanQuery<>(new IsKeyIn(keys).and(new CustomFilter())))

這使得所有的過濾工作都在服務器節點端進行,但它是全掃描,如果緩存中有很多條目,而輸入鍵只占其中的一小部分,又浪費了很多時間,這不需要的掃描時間。

並且有invokeAll()允許在服務器節點端進行過濾:

cache.invokeAll(new TreeSet<>(keys), new AdditionalFilter())
        .values().stream()
        .map(EntryProcessorResult::get)
        .collect(toList());

在哪里

private static class AdditionalFilter implements CacheEntryProcessor<String, Record, Record> {
    @Override
    public Record process(MutableEntry<String, Record> entry,
            Object... arguments) throws EntryProcessorException {
        if (... record matches the filter ...) {
            return entry.getValue();
        }
        return null;
    }
}

它通過它們的鍵查找條目,它在服務器節點端執行過濾邏輯,但在我的數據上它甚至比掃描解決方案還要慢。 我想(但不確定)這是因為invokeAll()可能是一個更新操作,所以(根據它的 Javadoc)它會鎖定相應的鍵。

我希望能夠通過給定的鍵找到條目,在服務器節點端應用額外的過濾,而不是支付額外的鎖(在我的例子中它是一個只讀操作)。

可能嗎?

我的緩存分布在 3 個服務器節點之間,它的原子性是TRANSACTIONAL_SNAPSHOT 讀取是在事務下完成的。

  1. SQL 是最簡單的解決方案,並且可能是最快的,給定適當的索引。

  2. IgniteCompute#broadcast + IgniteCache#localPeek

Collection<Key> keys = ...;
Collection<Collection<Value>> results = compute.broadcast(new LocalGetter(), keys);

...

    class LocalGetter implements IgniteClosure<Collection<Key>, Collection<Value>>
    {
        @Override public Collection<Value> apply(Collection<Key> keys) {
            IgniteCache<Key, Value> cache = ...;

            Collection<Value> res = new ArrayList<>(keys.size());
            
            for (Key key : keys) {
                Value val = cache.localPeek(key, CachePeekMode.PRIMARY);
                
                if (val != null && filterMatches(val)) {
                    res.add(val);
                }
            }
            
            return res;
        }
    }

通過這種方式,我們可以通過鍵有效地檢索緩存條目,然后在本地應用過濾器,並且僅通過網絡將匹配的條目發送回。 只有 N 次網絡調用,其中 N 是服務器節點的數量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM