在 Hazelcast 中序列化 class 层次结构的最佳方法是什么?
What is the best way to serialize class hierarchies in Hazelcast?
我想在 Hazelcast 中序列化和缓存一个与另一个 @Entity 具有双向关系的 @Entity。
我正在寻找在这种情况下被认为是官方最佳实践的解决方案:
- 正确序列化可能包含 null 的 class 层次结构
引用以及对集合和列表的引用
- 处理图表中的引用循环
到目前为止,我通过在图表中的每个 @Entity 中实现 DataSerializable 成功地实现了前者。我按以下方式处理空值和集合:
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeBoolean(certificationNumber != null);
if (certificationNumber != null)
out.writeUTF(certificationNumber);
out.writeShort(getSkills().size());
for (SkillEntity s: getSkills())
s.writeData(out);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
if (in.readBoolean()) {
certification = new CertificationEntity();
certification.readData(in);
}
short size = in.readShort();
skills = new HashSet<>();
for(int i=0; i<size; i++)
skills.add(in.readObject());
}
然而,打破引用循环更具挑战性。 This 线程建议:
I think it would be based on maintaining a threadlocal map.
On serialization you need to lookup of your object to serialize
already is in that map.. if so.. you need to serialize some kind of
placeholder (e..g a uuid)
If it isn't in that map, generate a placeholder and put it in that map
and write the actual object and you probably want to write the
placeholder so you can use this information when deserializing.
I think this should put you in the right direction, but since I have
not implemented this before I don't know if there are any gotcha's
here.
虽然上面的建议非常合理,但我不太确定如何去做,即应用什么软件工程模式以及如何将我的实体与序列化逻辑完全分开。
有什么指点吗?
我想我的问题的答案在 'Mastering Hazelcast 3.9' 手册的第 201 页,可以从 Hazelcast 网站下载。
页面内容:
public class PersonKryoSerializer implements StreamSerializer<Person> {
private static final ThreadLocal<Kryo> kryoThreadLocal
= new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(Person.class);
return kryo;
}
};
@Override
public int getTypeId() {
return 2;
}
@Override
public void write(ObjectDataOutput objectDataOutput, Person product)
throws IOException {
Kryo kryo = kryoThreadLocal.get();
Output output = new Output((OutputStream) objectDataOutput);
kryo.writeObject(output, product);
output.flush();
}
@Override
public Person read(ObjectDataInput objectDataInput)
throws IOException {
InputStream in = (InputStream) objectDataInput;
Input input = new Input(in);
Kryo kryo = kryoThreadLocal.get();
return kryo.readObject(input, Person.class);
}
@Override
public void destroy() {
}
}
The PersonKryoSerializer is relatively simple to implement. The nice
thing is that Kryo takes care of cycle detection and produces much
smaller serialized data than Java serialization. For one of our
customers we managed to reduce the size of map entries from a 15
kilobyte average using Java Serialization, to a less than six kilobyte
average. When we enabled Kryo compression, we managed to get it below
three kilobytes.
我想在 Hazelcast 中序列化和缓存一个与另一个 @Entity 具有双向关系的 @Entity。
我正在寻找在这种情况下被认为是官方最佳实践的解决方案:
- 正确序列化可能包含 null 的 class 层次结构 引用以及对集合和列表的引用
- 处理图表中的引用循环
到目前为止,我通过在图表中的每个 @Entity 中实现 DataSerializable 成功地实现了前者。我按以下方式处理空值和集合:
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeBoolean(certificationNumber != null);
if (certificationNumber != null)
out.writeUTF(certificationNumber);
out.writeShort(getSkills().size());
for (SkillEntity s: getSkills())
s.writeData(out);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
if (in.readBoolean()) {
certification = new CertificationEntity();
certification.readData(in);
}
short size = in.readShort();
skills = new HashSet<>();
for(int i=0; i<size; i++)
skills.add(in.readObject());
}
然而,打破引用循环更具挑战性。 This 线程建议:
I think it would be based on maintaining a threadlocal map.
On serialization you need to lookup of your object to serialize already is in that map.. if so.. you need to serialize some kind of placeholder (e..g a uuid)
If it isn't in that map, generate a placeholder and put it in that map and write the actual object and you probably want to write the placeholder so you can use this information when deserializing.
I think this should put you in the right direction, but since I have not implemented this before I don't know if there are any gotcha's here.
虽然上面的建议非常合理,但我不太确定如何去做,即应用什么软件工程模式以及如何将我的实体与序列化逻辑完全分开。
有什么指点吗?
我想我的问题的答案在 'Mastering Hazelcast 3.9' 手册的第 201 页,可以从 Hazelcast 网站下载。
页面内容:
public class PersonKryoSerializer implements StreamSerializer<Person> {
private static final ThreadLocal<Kryo> kryoThreadLocal
= new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(Person.class);
return kryo;
}
};
@Override
public int getTypeId() {
return 2;
}
@Override
public void write(ObjectDataOutput objectDataOutput, Person product)
throws IOException {
Kryo kryo = kryoThreadLocal.get();
Output output = new Output((OutputStream) objectDataOutput);
kryo.writeObject(output, product);
output.flush();
}
@Override
public Person read(ObjectDataInput objectDataInput)
throws IOException {
InputStream in = (InputStream) objectDataInput;
Input input = new Input(in);
Kryo kryo = kryoThreadLocal.get();
return kryo.readObject(input, Person.class);
}
@Override
public void destroy() {
}
}
The PersonKryoSerializer is relatively simple to implement. The nice thing is that Kryo takes care of cycle detection and produces much smaller serialized data than Java serialization. For one of our customers we managed to reduce the size of map entries from a 15 kilobyte average using Java Serialization, to a less than six kilobyte average. When we enabled Kryo compression, we managed to get it below three kilobytes.