【问题标题】:Ignite Scan Query Issue点燃扫描查询问题
【发布时间】:2020-07-29 15:21:12
【问题描述】:

我正在使用 Ignite 将 K-V 类型为 String-String 的缓存值存储在名为“DOCIDS”的缓存中。

我使用 HashMap 的二进制转换对象作为另一个名为“URLS”的 K-V 缓存中的值。键将仅为字符串,但值为“com.xyz.scrapy.common.ignite.IgniteObject”。

现在,当我查询扫描操作时,我正在这样做

//This scan query should only happen on cache which has K-V types as String-String.
        public Object scan(Object... allObjects) throws Exception {
            Set<Object> matchedKeys = new HashSet<>();
            try (QueryCursor<Cache.Entry<String, String>> cursor =
                         cacheHolder.getSecondaryCache().query(new ScanQuery<>(
                                 (k, v) -> k.contains(allObjects[0].toString())
                         ))) {
                for (Cache.Entry<String, String> entry : cursor) {
                    matchedKeys.add(entry.getKey());
                }
            }
            return matchedKeys;
        }

在 allObjects 中,值将是某个字符串模式的每次。这是肯定的。但是当 Ignite 筛选这些值时,某处的值是 IgniteObject 类型,我没有首先将其插入“DOCIDS”缓存中。异常附在下面:

"com.xyz.scrapy.common.ignite.ScrapyIgniteException: IGNITE EXCEPTION :: Exception while scanning for keys with given pattern in Ignite db - DOCIDS. Exception - IDSCaused by: javax.cache.CacheException: class org.apache.ignite.IgniteCheckedException: Failed to execute query on node [query=GridCacheQueryBean [qry=GridCacheQueryAdapter [type=SCAN, clsName=null, clause=null, filter=com.xyz.scrapy.common.ignite.IgniteQuery$QueryObject$$Lambda$243/2029270129@58665d95, transform=null, part=null, incMeta=false, pageSize=1024, timeout=0, incBackups=false, forceLocal=false, dedup=false, prj=org.apache.ignite.internal.cluster.ClusterGroupAdapter@1dfc48e7, keepBinary=false, subjId=0ef0942f-d2d1-4ac0-aa5b-783b3e1a0960, taskHash=0, mvccSnapshot=null, dataPageScanEnabled=null], rdc=null, trans=null], nodeId=f01b04de-66c0-4edc-8efe-4977ecf656b1]
    at org.apache.ignite.internal.processors.cache.GridCacheUtils.convertToCacheException(GridCacheUtils.java:1272)
    at org.apache.ignite.internal.processors.cache.query.GridCacheQueryFutureAdapter.next(GridCacheQueryFutureAdapter.java:167)
    at org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager$5.onHasNext(GridCacheDistributedQueryManager.java:645)
    at org.apache.ignite.internal.util.GridCloseableIteratorAdapter.hasNextX(GridCloseableIteratorAdapter.java:52)
    at org.apache.ignite.internal.util.lang.GridIteratorAdapter.hasNext(GridIteratorAdapter.java:44)
    at org.apache.ignite.internal.processors.cache.AutoClosableCursorIterator.hasNext(AutoClosableCursorIterator.java:47)
    at com.xyz.scrapy.common.ignite.IgniteQuery$QueryObject.scan(IgniteQuery.java:103)
    at com.xyz.scrapy.common.ignite.IgniteQuery.executeFieldsQuery(IgniteQuery.java:47)
    at com.xyz.scrapy.common.ignite.IgniteConnectionHandler$CacheHolder.scanKeys(IgniteConnectionHandler.java:302)
Caused by: class org.apache.ignite.binary.BinaryInvalidTypeException: com.xyz.scrapy.common.ignite.IgniteObject
    at org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:643)
    at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1755)
    at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1714)
    at org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinary(CacheObjectUtils.java:177)
    at org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinaryIfNeeded(CacheObjectUtils.java:40)
    at org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager$ScanQueryIterator.advance(GridCacheQueryManager.java:3050)
    at org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager$ScanQueryIterator.onHasNext(GridCacheQueryManager.java:2952)
    at org.apache.ignite.internal.util.GridCloseableIteratorAdapter.hasNextX(GridCloseableIteratorAdapter.java:52)
    at org.apache.ignite.internal.util.lang.GridIteratorAdapter.hasNext(GridIteratorAdapter.java:44)
    at org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager.runQuery(GridCacheQueryManager.java:1141)
    at org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager.processQueryRequest(GridCacheDistributedQueryManager.java:232)
    at org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager$2.apply(GridCacheDistributedQueryManager.java:108)
    at org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager$2.apply(GridCacheDistributedQueryManager.java:106)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager.processMessage(GridCacheIoManager.java:1142)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager.onMessage0(GridCacheIoManager.java:591)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager.handleMessage(GridCacheIoManager.java:392)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager.handleMessage(GridCacheIoManager.java:318)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager.access$100(GridCacheIoManager.java:109)
    at org.apache.ignite.internal.processors.cache.GridCacheIoManager$1.onMessage(GridCacheIoManager.java:308)
    at org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1635)
    at org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1255)
    at org.apache.ignite.internal.managers.communication.GridIoManager.access$4300(GridIoManager.java:144)
    at org.apache.ignite.internal.managers.communication.GridIoManager$8.execute(GridIoManager.java:1144)
 Caused by: java.lang.ClassNotFoundException: com.xyz.scrapy.common.ignite.IgniteObject
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

有人能解释一下为什么 Ignite 从缓存 DOCIDS 中获取 IgniteObject 吗?因为我只将 IgniteObject 存储在“URLS”缓存中而不是“DOCIDS”中。实际的例外是它没有加载类 IgniteObject。我什至不确定为什么它无法加载,因为我可以毫无问题地插入这些对象。

IgniteObject类如下

import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryObjectBuilder;
import java.io.Serializable;

//If value is not String, every value of K-V Store should wrap its contents with this Object
public class IgniteObject implements Serializable {

    //Value set via Reflection
    private Object object;

    public static BinaryObject convertToBinaryObject(Object object) throws Exception{
        //IgniteConnectionHandler.getConnection() will get Ignite Object named ignite. getObjectBuilder will do ignite.binary().builder(stringValue)
        BinaryObjectBuilder builder = IgniteConnectionHandler.getConnection().getObjectBuilder(IgniteObject.class.getName());
        builder.setField("object", object);//No I18N
        return builder.build();
    }

    public Object getActualObject(){
        return object;
    }
}

注意:cacheHolder.getSecondaryCache() 将给对象 - IgniteCache。

【问题讨论】:

    标签: java ignite gridgain


    【解决方案1】:

    您在Cache.Entry 中同时获得了键和值,即使您只使用键,这也是急切地发生的。

    你可以试试

    cacheHolder.getSecondaryCache().withKeepBinary().query(...)
    

    避免需要IgniteObject 类。

    【讨论】:

    • 我只需要获取某种模式的键。但它要求提供两种类型。当你说“急切地发生”时,我不明白。我一定会尝试的,但我想了解它背后的概念。当您进行这样的查询时,是否意味着它也会获取其他缓存值?
    • 是的,Scan Query 总是同时获取 key 和 value
    • 但为什么我会从缓存 DOCIDS 中获取“IgniteObject”类型的值。它应该只是字符串吧? “withKeepBinary”有什么作用?
    • 您将获得一个条目,其中包含 IgniteObject 作为值,即使您从未使用它。 withKeepBinary() 将使用 BinaryObject 代替。
    • 哦,好的,我明白了。但我没有在 DOCIDS 缓存中插入 IgniteObject 类型的值。我要求的扫描查询在 DOCIDS 缓存上。在那个缓存中,我也只将 K-V 作为字符串插入。这是否意味着,扫描查询将在所有缓存的所有值上运行?
    猜你喜欢
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-04
    • 2012-12-08
    相关资源
    最近更新 更多