- Hazelcast 教程
- Hazelcast - 首页
- Hazelcast - 简介
- Hazelcast - 设置
- Hazelcast - 第一个应用程序
- Hazelcast - 配置
- 设置多节点实例
- Hazelcast - 数据结构
- Hazelcast - 客户端
- Hazelcast - 序列化
- Hazelcast 高级特性
- Hazelcast - Spring 集成
- Hazelcast - 监控
- Map Reduce & 聚合
- Hazelcast - 集合监听器
- 常见问题 & 性能技巧
- Hazelcast 有用资源
- Hazelcast - 快速指南
- Hazelcast - 有用资源
- Hazelcast - 讨论
Hazelcast - 序列化
Hazelcast 理想应用于数据/查询分布在多台机器的环境中。这需要将我们的 Java 对象序列化为可在网络上传输的字节数组。
Hazelcast 支持多种类型的序列化。但是,让我们来看一些常用的序列化方式,即 Java 序列化和 Java Externalizable。
Java 序列化
示例
首先让我们来看 Java 序列化。假设我们定义一个实现了 Serializable 接口的 Employee 类。
public class Employee implements Serializable{ private static final long serialVersionUID = 1L; private String name; private String department; public Employee(String name, String department) { super(); this.name = name; this.department = department; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @Override public String toString() { return "Employee [name=" + name + ", department=" + department + "]"; } }
现在让我们编写代码将 Employee 对象添加到 Hazelcast map 中。
public class EmployeeExample { public static void main(String... args){ //initialize hazelcast server/instance HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance(); //create a set to track employees Map<Employee, String> employeeOwners=hazelcast.getMap("employeeVehicleMap"); Employee emp1 = new Employee("John Smith", "Computer Science"); // add employee to set System.out.println("Serializing key-value and add to map"); employeeOwners.put(emp1, "Honda"); // check if emp1 is present in the set System.out.println("Serializing key for searching and Deserializing value got out of map"); System.out.println(employeeOwners.get(emp1)); // perform a graceful shutdown hazelcast.shutdown(); } }
输出
它将产生以下输出:
Serializing key-value and add to map Serializing key for searching and Deserializing value got out of map Honda
这里一个非常重要的方面是,只需实现 Serializable 接口,我们就可以让 Hazelcast 使用 Java 序列化。还要注意,Hazelcast 存储键和值的序列化数据,而不是像 HashMap 一样将其存储在内存中。因此,Hazelcast 承担了序列化和反序列化的繁重工作。
示例
但是,这里有一个陷阱。在上面的例子中,如果员工的部门发生变化怎么办?这个人还是同一个人。
public class EmployeeExampleFailing { public static void main(String... args){ //initialize hazelcast server/instance HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance(); //create a set to track employees Map<Employee, String> employeeOwners=hazelcast.getMap("employeeVehicleMap"); Employee emp1 = new Employee("John Smith", "Computer Science"); // add employee to map System.out.println("Serializing key-value and add to map"); employeeOwners.put(emp1, "Honda"); Employee empDeptChange = new Employee("John Smith", "Electronics"); // check if emp1 is present in the set System.out.println("Checking if employee with John Smith is present"); System.out.println(employeeOwners.containsKey(empDeptChange)); Employee empSameDept = new Employee("John Smith", "Computer Science"); System.out.println("Checking if employee with John Smith is present"); System.out.println(employeeOwners.containsKey(empSameDept)); // perform a graceful shutdown hazelcast.shutdown(); } }
输出
它将产生以下输出:
Serializing key-value and add to map Checking if employee with name John Smith is present false Checking if employee with name John Smith is present true
这是因为 Hazelcast 不会反序列化键,即在比较时反序列化 Employee。它直接比较序列化键的字节码。因此,具有相同属性值的相同对象将被视为相同。但是,如果这些属性的值发生变化,例如上面的场景中的部门,则这两个键将被视为唯一。
Java Externalizable
如果在上面的例子中,我们在执行键的序列化/反序列化时不关心部门的值怎么办?Hazelcast 也支持 Java Externalizable,它使我们可以控制在序列化和反序列化中使用哪些标记。
示例
让我们相应地修改我们的 Employee 类:
public class EmplyoeeExternalizable implements Externalizable { private static final long serialVersionUID = 1L; private String name; private String department; public EmplyoeeExternalizable(String name, String department) { super(); this.name = name; this.department = department; } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Deserializaing...."); this.name = in.readUTF(); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("Serializing...."); out.writeUTF(name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @Override public String toString() { return "Employee [name=" + name + ", department=" + department + "]"; } }
因此,正如您从代码中看到的,我们添加了 readExternal/writeExternal 方法,它们负责序列化/反序列化。鉴于我们在序列化/反序列化时对部门不感兴趣,我们在 readExternal/writeExternal 方法中排除了它们。
示例
现在,如果我们执行以下代码:
public class EmployeeExamplePassing { public static void main(String... args){ //initialize hazelcast server/instance HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance(); //create a set to track employees Map<EmplyoeeExternalizable, String> employeeOwners=hazelcast.getMap("employeeVehicleMap"); EmplyoeeExternalizable emp1 = new EmplyoeeExternalizable("John Smith", "Computer Science"); // add employee to map employeeOwners.put(emp1, "Honda"); EmplyoeeExternalizable empDeptChange = new EmplyoeeExternalizable("John Smith", "Electronics"); // check if emp1 is present in the set System.out.println("Checking if employee with John Smith is present"); System.out.println(employeeOwners.containsKey(empDeptChange)); EmplyoeeExternalizable empSameDept = new EmplyoeeExternalizable("John Smith", "Computer Science"); System.out.println("Checking if employee with John Smith is present"); System.out.println(employeeOwners.containsKey(empSameDept)); // perform a graceful shutdown hazelcast.shutdown(); } }
输出
我们得到的输出是:
Serializing.... Checking if employee with John Smith is present Serializing.... true Checking if employee with John Smith is present Serializing.... true
如输出所示,使用 Externalizable 接口,我们可以为 Hazelcast 提供仅包含员工姓名的序列化数据。
还要注意,Hazelcast 会对我们的键进行两次序列化:
一次在存储键时,
第二次是在 map 中搜索给定键时。如前所述,这是因为 Hazelcast 使用序列化字节数组进行键比较。
总的来说,如果我们想要更好地控制要序列化的属性以及如何处理它们,与 Serializable 相比,使用 Externalizable 的好处更多。