【问题标题】:Persistence and Split brains Scenario持久性和脑裂场景
【发布时间】:2016-03-17 08:56:25
【问题描述】:

1.ignite如何处理集群模式下的裂脑场景?

2.在putAll的情况下,它是为每个条目命中持久存储还是一次将所有内容都放入存储?

3.如果我们设置批量大小,putAll 对持久存储如何工作?

4.如果分区有备份,数据移动的顺序是什么? primary->backup->persistence 还是 primary->backup 同时异步成持久化?

5.如果在持久化存储中进行了更新,如何在不重新加载的情况下将其反映到缓存中?(如何处理后端更新)

6.如果我们使用 loadCache 重新加载缓存,则在后端进行更新并反映缓存中的更改时,缓存中不会更新更改,或者如果我们直接使用 get() 也不会反映更新.只有在清除缓存一次然后调用 loadcache 或 get api 后才会反映更新。这是重新加载缓存的正确方法吗?

 Person p1 = new Person(1, "Benakaraj", "KS", 11, 26, 1000);
    Person p2 = new Person(2, "Ashwin", "Konale", 13, 26, 10000);
    Connection con = null;
    Statement stmt = null;

    con = ds.getConnection();
    stmt = con.createStatement();
    String sql =
        "create table Person(per_id int,name varchar(20),last_name varchar(20),org_id int,age int,salary REAL,primary key(per_id))";
    stmt.executeUpdate(sql);

    ROCCacheConfiguration<Integer, Person> pesonConfig = new ROCCacheConfiguration<>();
    pesonConfig.setName("bkendupdtCache");
    pesonConfig.setCacheMode(CacheMode.PARTITIONED);
    JdbcType jdbcType = new JdbcType();

    jdbcType.setCacheName("bkendupdtCache");
    jdbcType.setDatabaseSchema("ROC4Test");
    jdbcType.setDatabaseTable("Person");
    jdbcType.setKeyType(Integer.class);
    jdbcType.setValueType(Person.class);
    // Key fields for PERSON.

    Collection<JdbcTypeField> keys = new ArrayList<>();
    keys.add(new JdbcTypeField(Types.INTEGER, "per_id", int.class, "perId"));
    jdbcType.setKeyFields(keys.toArray(new JdbcTypeField[keys.size()]));

    // Value fields for PERSON.
    Collection<JdbcTypeField> vals = new ArrayList<>();
    vals.add(new JdbcTypeField(Types.INTEGER, "per_id", int.class, "perId"));
    vals.add(new JdbcTypeField(Types.VARCHAR, "name", String.class, "name"));
    vals.add(new JdbcTypeField(Types.VARCHAR, "last_name", String.class, "lastName"));
    vals.add(new JdbcTypeField(Types.INTEGER, "org_id", int.class, "orgId"));
    vals.add(new JdbcTypeField(Types.INTEGER, "age", int.class, "age"));
    vals.add(new JdbcTypeField(Types.FLOAT, "salary", Float.class, "salary"));
    jdbcType.setValueFields(vals.toArray(new JdbcTypeField[vals.size()]));

    Collection<JdbcType> jdbcTypes = new ArrayList<>();

    jdbcTypes.add(jdbcType);

    CacheJdbcPojoStoreFactory<Integer, Organization> cacheJdbcdPojoStorefactory4 =
        context.getBean(CacheJdbcPojoStoreFactory.class);
    cacheJdbcdPojoStorefactory4.setTypes(jdbcTypes.toArray(new JdbcType[jdbcTypes.size()]));

    pesonConfig.setCacheStoreFactory((Factory<? extends CacheStore<Integer, Person>>) cacheJdbcdPojoStorefactory4);
    pesonConfig.setReadThrough(true);
    pesonConfig.setWriteThrough(true);
    ROCCache<Integer, Person> personCache2 = rocCachemanager.createCache(pesonConfig);
    personCache2.put(1, p1);
    personCache2.put(2, p2);
    assertEquals(personCache2.get(2).getName(), "Ashwin");
    sql = assertEquals(personCache2.get(2).getName(), "Abhi");

"update Person set name='Abhi' where per_id=2";
        stmt.execute(sql);

        //fails and asks for assertion with the stale value
        personCache.loadcache(null);
        assertEquals(personCache2.get(2).getName(), "Abhi");

        //works fine
        personCache2.clear(2);
        assertEquals(personCache2.get(2).getName(), "Abhi");

        //works fine
        personCache2.clear();
        personCache2.loadcache(null);
        assertEquals(personCache2.get(2).getName(), "Abhi");

        sql = "drop table Person";
        stmt.executeUpdate(sql);
        con.close();
        stmt.close();
        rocCachemanager.destroyCache("bkendupdtCache");

【问题讨论】:

    标签: ignite


    【解决方案1】:
    1. 默认情况下,您将获得两个独立的集群,它们将永远不会再次相互连接(否则可能会出现数据不一致)。您将不得不手动停止其中一个集群并在网络恢复后重新启动。但是,自动解析可以作为插件实现。例如,GridGain 提供了开箱即用的功能:https://gridgain.readme.io/docs/network-segmentation

    2. Ignites 尝试尽可能减少持久性存储调用。如果您的存储支持批量读写,那么在实现loadAllwriteAllremoveAll 方法时最好利用这一点。

    3. 批量更新操作将根据节点映射拆分批次。批处理的每个部分将一次持久化到相应的主节点上。

    4. 使用主节点自动更新存储(如果写入存储失败,则不更新缓存,反之亦然)。默认情况下,备份在后台异步更新。

    5. 如果可能,您应该避免这种情况,并将 Ignite 视为主数据存储,在后端有一个可选存储(即始终通过 Ignite API 访问数据)。没有简单的方法将数据库更新传播到 Ignite。

    6. 您可以使用clear/clearAll 方法使条目无效,或使用loadAll 方法重新加载它们。另一种选择是使用过期:https://apacheignite.readme.io/docs/expiry-policies

    【讨论】:

    • 批量大小是指一次进入缓存的条目数
    • 在后面写的过程中,即使存储也是异步更新的?备份还会异步更新吗?
    • 写后存储是异步更新的,没错。备份是否同步更新由CacheConfiguration.writeSynchronizationMode 属性定义。默认为PRIMARY_SYNC,其中仅同步更新主节点。在FULL_SYNC 模式下,客户端会等待所有节点。
    • 那么多个缓存会发生什么?基本上三种情况: 1)一个缓存在超过 1 个段中更新,但从不更新到相同的 key 2)一个缓存在超过 1 个段中更新,但在两边都更新了相同的 key(冲突) 3)一个缓存仅在 1 段中更新这三种情况会以不同方式处理吗? “独立”集群语句是否仅适用于场景 2 中的缓存,还是也适用于 1 和/或 3?
    猜你喜欢
    • 2014-02-18
    • 2023-03-27
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 2019-02-22
    • 2018-04-18
    相关资源
    最近更新 更多