Apache Ignite基本概念及最佳实践(四)——问答篇

1,166 阅读3分钟

前言

Apache Ignite系列

一、数据分区LOCAL模式是否可用

答:不可用

  • 在2.12.0版本被标记为即将废弃
  • 在最新的2.15.0版本中已经不存在CacheMode#LOCAL
  • 官方文档参考Data Partitioning

二、存储big data限制是否有限制

答:有限制

  • 单个条目必须小于64MB(默认)
  • 可以通过配置dataStorageConfiguration中的walSegmentSize的值来保存更大的条目
  • 官方文档参考Changing WAL Segment Size
<bean class="org.apache.ignite.configuration.IgniteConfiguration" id="ignite.cfg">
    <property name="dataStorageConfiguration">
        <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
            <!-- set the size of wal segments to 128MB -->
            <property name="walSegmentSize" value="#{128 * 1024 * 1024}"/>
            <property name="defaultDataRegionConfiguration">
                <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                    <property name="persistenceEnabled" value="true"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

三、是否可以保存复杂对象

答:如果使用SQL索引,是不可以的,不能保存嵌套对象,List,Map等复杂对象

  • 如果不使用SQL创建索引,查询数据,是可以保存的
  • 如果使用SQL创建索引和查询,预定义的数据类型如下:
    • 所有的基本类型和包装类,除了char和Character
    • String
    • BigDecimal
    • byte[]
    • java.util.Date, java.sql.Date, java.sql.Timestamp
    • java.util.UUID
  • 官方文档参考Defining Indexes

四、查询缓存的返回值,是否可以返回真正的对象

答:SqlFieldQuery不可以,ScanQuery和IndexQuery可以

  • SqlFieldQuery:不能直接返回实体,只支持按序号获取字段值
  • ScanQuery:可以直接返回实体,缺点是需要全表扫描,执行较慢
  • IndexQuery:可以直接返回实体,遍历部分索引树即可,返回的是构建索引时的对象
  • 官方文档参考Using Cache Queries
// SqlFieldQuery
IgniteCache<Integer, Student> cache = ignite.getOrCreateCache("myCache");
SqlFieldsQuery sql = new SqlFieldsQuery("select concat(classId, '----', name) from STUDENT");
QueryCursor<List<?>> cursor = cache.query(sql);
for (List<?> row : cursor) {
    System.out.println("学生信息:" + row.get(0));
}

// ScanQuery
IgniteCache<Integer, Person> cache = ignite.getOrCreateCache("myCache");
IgniteBiPredicate<Integer, Person> filter = (key, p) -> p.getSalary() > 1000;
try (QueryCursor<Cache.Entry<Integer, Person>> qryCursor = cache.query(new ScanQuery<>(filter))) {
    qryCursor.forEach(
            entry -> System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()));
}

// IndexQuery
QueryEntity personEntity = new QueryEntity(Integer.class, Person.class)
    .setFields(new LinkedHashMap<String, String>() {{
        put("orgId", Integer.class.getName());
        put("salary", Integer.class.getName());
    }})
    .setIndexes(Collections.singletonList(
        new QueryIndex(Arrays.asList("orgId", "salary"), QueryIndexType.SORTED)
            .setName("ORG_SALARY_IDX")
    ));
CacheConfiguration<Integer, Person> ccfg = new CacheConfiguration<Integer, Person>("entityCache")
    .setQueryEntities(Collections.singletonList(personEntity));
IgniteCache<Integer, Person> cache = ignite.getOrCreateCache(ccfg);
QueryCursor<Cache.Entry<Integer, Person>> cursor = cache.query(
    new IndexQuery<Integer, Person>(Person.class, "ORG_SALARY_IDX")
        .setCriteria(eq("orgId", 1))
);

五、是否有权限控制,节点访问权限,restapi访问权限

答:是有的

  • 有Authentication,用户级别的权限控制
    • 可以在数据库中配置用户名和密码(CREATE USER, ALTER USER, DROP USER)
    • 在节点的配置文件中,设置authenticationEnabled为true,同时要开启持久化功能才可生效
    • 官方文档参考authentication
  • 不支持对增删改查语句及用户角色做细粒度的权限控制

六、ignite是否可以集成hibernate做二级缓存

答:是可以的

  • hibernate的L1缓存是会话级别的,由内部实现
  • hibernate的L2缓存有很多可插拔的实现,Ignite可以作为L2缓存
  • 官方文档参考Hibernate L2 Cache image.png

七、Parititioned是否可以根据某个字段分区

答:是可以的

  • 如果没有显式指定关联键,默认缓存的key是关联键;如果用SQL语句,默认主键是关联键
  • 想要让两个不同缓存的数据在同一个分区需要以下条件:
    • 必须使用一个复杂对象作为Key
    • 在想用作关联键的字段上加@AffinityKeyMapped注解
  • 实际使用时,可以对每一个Value创建一个对应的key,例:PersonKey,一个字段为id,另一个加注解的字段为要分区的字段
  • 官方文档参考Affinity Colocation
    static class Person {
        private int id;
        private String companyId;
        private String name;

        public Person(int id, String companyId, String name) {
            this.id = id;
            this.companyId = companyId;
            this.name = name;
        }

        public int getId() {
            return id;
        }
    }

    static class PersonKey {
        private int id;

        @AffinityKeyMapped
        private String companyId;

        public PersonKey(int id, String companyId) {
            this.id = id;
            this.companyId = companyId;
        }
    }

八、thin Client如何连接server节点

答:client连接server节点默认端口是47500,thin Client连接server节点默认端口是10800

  • 在server节点配置ClientConnectorConfiguration来制定thin Client连接端口,默认是10800
  • 官方文档参考Thin Clients