管理 hazelcast 中模型对象的更改?

Managing changes to model objects in hazelcast?

系统的总体架构是一个连接到hazelcast的轻量级应用服务器以及两者之间的公共模型依赖关系。该应用程序可以关闭,但业务要求 hazelcast 集群必须在升级之间保持运行(以免丢失上下文会话数据)。

如果我在 hazelcast 中定义了一个地图:

        <hz:map name="Fruit"
                backup-count="${hazelcast.default.backup-count}"
                time-to-live-seconds="${hazelcast.default.time-to-live-seconds}"
                max-idle-seconds="${hazelcast.default.max-idle-seconds}"
                eviction-policy="${hazelcast.default.eviction-policy}"
                max-size="${hazelcast.default.max-size}"
                eviction-percentage="${hazelcast.default.eviction-percentage}"
                in-memory-format="${hazelcast.in-memory-format}"/>

其中存储了一个名为 Fruit 的 class:

public class Fruit implements Serializable {

    private static final long serialVersionUID = -7184021704842980361;

    //some fields and methods
}

假设应用程序的 v1、模型和 hazelcast 服务器都已部署并且在生产环境中运行良好。 然后新的需求出现了,我被迫对 Fruit class 进行更改(更新 serialVersionUID 以表示对 class 的更改):

private static final long serialVersionUID = -5284413340344918080L;

public boolean isPoisonous(){
    return determineToxicityOnHumans();
}

问题是,当我部署依赖于模型 v2 的 api 的新版本时(水果 class 存在),我得到一个异常:

com.hazelcast.nio.serialization.HazelcastSerializationException: java.io.InvalidClassException: 

io.anew.hz.model.Fruit; local class incompatible: stream classdesc serialVersionUID = -5284413340344918080, local class serialVersionUID = -7184021704842980361

这对我来说很有意义,因为 serialVersionUID 已从版本 1 更改为版本 2。我设想并且目前正在努力解决的问题是在不导致集群停机的情况下管理此更改。

我的问题是:其他人在管理对 hazelcast 对象依赖项的模型更改方面有哪些经验?管理集群的不同模型更改有哪些工作策略?迁移是一种有效的策略吗?

您可能想看看可以处理版本控制的自定义序列化程序。所以在序列化的时候给stream加一个version,反序列化的时候就知道怎么处理了。

寻找 (Identified)DataSerializable、StreamSerializer 和 Portable。 https://github.com/hazelcast/hazelcast-code-samples/tree/master/serialization

如果要向 class 添加新字段,出于显而易见的原因,这不能使用 Java 序列化来完成 - 一个版本的序列化对象不能在没有潜在数据的情况下反序列化为另一个版本损失(即使 serialVersionUID 被篡改)。

不幸的是,我不认为 Hazelcast 的 Portable serialization mechanism, plays nicely if you try to read a field that doesn't exist in the stream (which will happen when you start rolling your new class out through the cluster), nor does it like you reading the remaining bytes of the object stream, so you're going to have to roll-you-own Custom serialization mechanism

你需要支持的重要概念(借用Coherence)是未来数据之一。

未来数据是指将对象反序列化为 class 的旧版本时,不会有字段来保存所有值。如果该对象没有办法保存这些值,那么如果该对象被推回缓存(或从一个节点移动到另一个节点),它们可能会丢失。

您的自定义序列化需要支持的是能够从字节数组中读取已知值加上作为字节数组的剩余未知值。然后可以将这个包含未知值的字节数组存储在对象中,并在重新序列化时写回。

一旦这个机制起作用,你只需要做一个滚动升级,每个缓存节点依次升级。