Ignite SQL是否仅操作内存数据集?冷启动读穿透失效如何处理?
我实现了一个基于DynamoDB的Ignite自定义CacheStore:
public class DynamoDBCacheStore extends CacheStoreAdapter<Integer, String> { public DynamoDBCacheStore() { // initialize the DynamoDB client } @Override public String load(Integer key) throws CacheLoaderException { // impl here } @Override public void write(Cache.Entry<? extends Integer, ? extends String> entry) throws CacheWriterException { // impl here } @Override public void delete(Object key) throws CacheWriterException { // impl here } }
为了通过JDBC驱动使用该缓存,我配置了SQL支持:
CacheConfiguration<Integer, String> cacheCfg = new CacheConfiguration<Integer, String>() .setCacheStoreFactory(FactoryBuilder.factoryOf(DynamoDBCacheStore.class)) .setCacheMode(CacheMode.PARTITIONED) .setAtomicityMode(CacheAtomicityMode.ATOMIC) .setName(cacheName) .setReadThrough(true) .setWriteThrough(true) .setIndexedTypes(Integer.class, String.class); IgniteConfiguration cfg = new IgniteConfiguration() .setIgniteInstanceName("embedded-ignite") .setClientMode(false) .setCacheConfiguration(cacheCfg);
但遇到了问题:缓存冷启动(为空)且未调用cache.loadCache()时,SQL查询不会触发读穿透,执行以下代码无输出:
// Running SQL query String sql = "SELECT * FROM LookUpTable WHERE id = ?"; try (QueryCursor<List<?>> cursor = personCache.query(new SqlFieldsQuery(sql).setArgs(25))) { for (List<?> row : cursor) { System.out.println(row); } }
而使用Key/Value API却能正常触发读穿透:
IgniteCache<Integer, String> cache = ignite.getOrCreateCache(cacheName); cache.get(25);
请问:
- Ignite SQL是否仅操作已驻留内存的数据集?
- 当底层存储容量超过Ignite内存时应采用何种方案?
关于Ignite SQL的读穿透行为
是的,Ignite SQL仅针对内存中已存在的缓存数据执行查询,不会自动触发读穿透从底层CacheStore加载数据。原因在于SQL查询依赖内存中的索引和数据集进行扫描,而CacheStore的load方法仅在Key/Value API(如get、getAll)调用时触发,SQL引擎无法直接感知底层存储中未加载到内存的数据。
底层存储容量超过Ignite内存的解决方案
针对这种场景,可采用以下几种方案:
1. 按需加载+SQL查询前置Key/Value操作
若需通过SQL查询特定数据,可先通过Key/Value API的get或getAll方法将目标数据加载到内存,再执行SQL查询。该方式适合查询条件明确、可映射到具体缓存Key的场景。
2. 带过滤的批量加载
若需查询的数据集无法通过明确Key定位,可调用cache.loadCache()方法批量加载数据,但需设置加载过滤器,避免一次性加载全部数据导致内存溢出:
cache.loadCache((key, val) -> { // 自定义过滤条件,仅加载符合要求的数据 return ((Integer)key) > 20 && ((Integer)key) < 30; });
3. 启用Ignite原生持久化
将Ignite配置为使用原生持久化,此时Ignite会自动管理内存与磁盘的分层存储,内存不足时自动将冷数据刷到磁盘,SQL查询可透明访问磁盘上的数据,无需手动处理加载逻辑。配置示例:
CacheConfiguration<Integer, String> cacheCfg = new CacheConfiguration<Integer, String>() // 保留原有配置... .setPersistenceEnabled(true); IgniteConfiguration cfg = new IgniteConfiguration() // 保留原有配置... .setDataStorageConfiguration(new DataStorageConfiguration() .setDefaultDataRegionConfiguration(new DataRegionConfiguration() .setName("Default_Region") .setInitialSize(1024 * 1024 * 1024) // 1GB初始内存 .setMaxSize(2 * 1024 * 1024 * 1024) // 2GB最大内存 .setPersistenceEnabled(true)));
4. 分布式SQL联合查询
如果底层存储支持SQL(如DynamoDB可通过第三方SQL层或原生Query/Scan API适配),可配置Ignite的联合查询,直接将SQL查询下推到底层存储执行,再返回结果。该方式适合大规模数据集查询,无需将数据加载到Ignite内存。
内容的提问来源于stack exchange,提问作者Majid Azimi

