Skip to content

Commit 830adf7

Browse files
OzanCanselakeles85
andauthored
Compact documentation is added. (#1141)
Co-authored-by: Ali Keles <[email protected]>
1 parent 869d8e5 commit 830adf7

File tree

1 file changed

+127
-7
lines changed

1 file changed

+127
-7
lines changed

Reference_Manual.md

Lines changed: 127 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@
4040
* [4. Serialization](#4-serialization)
4141
* [4.1. identified_data_serializer Serialization](#41-identified_data_serializer-serialization)
4242
* [4.2. portable_serializer Serialization](#42-portable_serializer-serialization)
43-
* [4.3. Custom Serialization](#43-custom-serialization)
44-
* [4.4. JSON Serialization](#44-json-serialization)
45-
* [4.5. Global Serialization](#45-global-serialization)
43+
* [4.3. compact_serializer Serialization](#43-compact_serializer-serialization)
44+
* [4.3.1. Compact Serializer](#431-compact-serializer)
45+
* [4.3.2. Schema Evolution](#432-schema-evolution)
46+
* [4.3.3. Generic Record](#433-generic-record)
47+
* [4.4. Custom Serialization](#44-custom-serialization)
48+
* [4.5. JSON Serialization](#45-json-serialization)
49+
* [4.6. Global Serialization](#46-global-serialization)
4650
* [5. Setting Up Client Network](#5-setting-up-client-network)
4751
* [5.1. Providing Member Addresses](#51-providing-member-addresses)
4852
* [5.2. Setting Smart Routing](#52-setting-smart-routing)
@@ -940,9 +944,125 @@ namespace hazelcast {
940944
941945
Note that, this is very similar to `identified_data_serializer` implementation except the method signatures and the derived marker class of `portable_serializer` for the specialized serializer.
942946
943-
`hz_serializer<Person>` specialization of `hz_serializer` should implement the above four methods, namely `get_factory_id`, `get_class_id`, `write_portable`, `read_portable`. In case that the object fields are non-public, you can always define struct `hz_serializer<Person>` as friend to your object class. You use the `portable_writer` class methods when serializing the object into binary bytes and you use the `portable_reader` class methods when de-serializing the bytes into the concrete object instance.
947+
`hz_serializer<Person>` specialization of `hz_serializer` should implement the above four methods, namely `get_factory_id`, `get_class_id`, `write_portable`, `read_portable`. In case that the object fields are non-public, you can always define struct `hz_serializer<Person>` as friend to your object class. You use the `portable_writer` class methods when serializing the object into binary bytes and you use the `portable_reader` class methods when de-serializing the bytes into the concrete object instance.
944948
945-
## 4.3. Custom Serialization
949+
## 4.3. compact_serializer Serialization
950+
As an enhancement to the existing serialization methods, Hazelcast offers compact serialization, with the following main features:
951+
952+
- Separates the schema from the data and stores it for each type, instead of each object which results in less memory and bandwidth usage compared to other formats
953+
- Does not require a class to implement an interface or change the source code of the class in any way
954+
- Supports schema evolution which permits adding or removing fields, or changing the types of fields
955+
- Can work with any kind of types
956+
- Platform and language independent
957+
- Supports partial deserialization of fields, without deserializing the whole objects during queries or indexing
958+
959+
Hazelcast achieves these features by having a well-known schema of objects and replicating them across the cluster which enables members and clients to fetch schemas they don’t have in their local registries. Each serialized object carries just a schema identifier and relies on the schema distribution service or configuration to match identifiers with the actual schema. Once the schemas are fetched, they are cached locally on the members and clients so that the next operations that use the schema do not incur extra costs.
960+
961+
Schemas help Hazelcast to identify the locations of the fields on the serialized binary data. With this information, Hazelcast can deserialize individual fields of the data, without reading the whole binary. This results in a better query and indexing performance.
962+
963+
Schemas can evolve freely by adding or removing fields. Even, the types of the fields can be changed. Multiple versions of the schema may live in the same cluster and both the old and new readers may read the compatible parts of the data. This feature is especially useful in rolling upgrade scenarios.
964+
965+
The Compact serialization does not require any changes in the user classes as it doesn’t need a class to implement a particular interface. Serializers might be implemented and specified separately from the classes.
966+
967+
The underlying format of the compact serialized objects is platform and language independent.
968+
969+
Refer to [documentation](https://docs.hazelcast.com/hazelcast/5.3-snapshot/compact-binary-specification) for more details about compact binary serialization.
970+
### 4.3.1. Compact Serializer
971+
Another way to use compact serialization is to implement the `hz_serializer<T> : compact::compact_serializer` specialization for a `T`. A basic serializer could look like:
972+
973+
``` C++
974+
class PersonDTO
975+
{
976+
int age;
977+
std::string name;
978+
std::string surname;
979+
};
980+
981+
namespace hazelcast {
982+
namespace client {
983+
namespace serialization {
984+
985+
template<>
986+
struct hz_serializer<PersonDTO> : compact::compact_serializer
987+
{
988+
static void write(const PersonDTO& object, compact::compact_writer& out)
989+
{
990+
out.write_int32("age", object.age);
991+
out.write_string("name", object.name);
992+
out.write_string("surname", object.surname);
993+
}
994+
995+
static PersonDTO read(compact::compact_reader& in)
996+
{
997+
PersonDTO person;
998+
999+
person.age = in.read_int32("age");
1000+
boost::optional<std::string> name = in.read_string("name");
1001+
1002+
if (name) {
1003+
person.name = *name;
1004+
}
1005+
1006+
boost::optional<std::string> surname = in.read_string("surname");
1007+
1008+
if (surname) {
1009+
person.surname = *surname;
1010+
}
1011+
1012+
return person;
1013+
}
1014+
1015+
static std::string type_name() { return "person"; }
1016+
};
1017+
1018+
} // namespace serialization
1019+
} // namespace client
1020+
} // namespace hazelcast
1021+
```
1022+
1023+
### 4.3.2. Schema Evolution
1024+
Compact serialization permits schemas and classes to evolve by adding or removing fields, or by changing the types of fields. More than one version of a class may live in the same cluster and different clients or members might use different versions of the class.
1025+
1026+
Hazelcast handles the versioning internally. So, you don’t have to change anything in the classes or serializers apart from the added, removed, or changed fields.
1027+
1028+
Hazelcast achieves this by identifying each version of the class by a unique fingerprint. Any change in a class results in a different fingerprint. Hazelcast uses a 64-bit Rabin Fingerprint to assign identifiers to schemas, which has an extremely low collision rate.
1029+
1030+
Different versions of the schema with different identifiers are replicated in the cluster and can be fetched by clients or members internally. That allows old readers to read fields of the classes they know when they try to read data serialized by a new writer. Similarly, new readers might read fields of the classes available in the data, when they try to read data serialized by an old writer.
1031+
1032+
This means that for one type name, there can be several schemas.
1033+
1034+
In addition, the `compact::compact_reader` class exposes methods such as `field_kind get_field_kind(string name)` which returns the kind (i.e. the actual type) of the field.
1035+
1036+
### 4.3.3. Generic Record
1037+
Compact serialization introduces the `generic_record` and `generic_record_builder` classes, which represents a container and builder object that can be used in place of domain classes. The client always knows how to (de) serialize compact instances and therefore does not require any configuration in order to handle them.
1038+
1039+
A new record can be created as such:
1040+
1041+
``` C++
1042+
using namespace hazelcast::client::serialization::generic_record;
1043+
1044+
generic_record record = generic_record_builder{ "type-name" }
1045+
.set_boolean("field-name-1", true)
1046+
.set_int32("field-name-2", 123)
1047+
.set_string("field-name-3", "hello")
1048+
.build();
1049+
1050+
// Put into map and wait
1051+
map->put(1234, record).get();
1052+
```
1053+
1054+
A generic record can be used as such:
1055+
1056+
``` C++
1057+
auto rec = map->get<int, generic_record>(1234).get();
1058+
bool field1 = rec->get_boolean("field-name-1");
1059+
int field2 = rec->get_int32("field-name-2");
1060+
boost::optional<std::string> field3 = rec->get_string("field-name-3");
1061+
```
1062+
1063+
Refer to the general [documentation](https://docs.hazelcast.com/hazelcast/latest/serialization/compact-serialization) for more details on how to access domain objects without domain classes. [Supported types](https://docs.hazelcast.com/hazelcast/latest/serialization/compact-serialization#supported-types) are listed here.
1064+
1065+
## 4.4. Custom Serialization
9461066

9471067
Hazelcast lets you plug a custom serializer to be used for serialization of objects. It allows you alsoan integration point for any external serialization frameworks such as protobuf, flatbuffers, etc.
9481068

@@ -981,7 +1101,7 @@ namespace hazelcast {
9811101
9821102
`hz_serializer<Person>` specialization of `hz_serializer` should implement the above three methods, namely `get_type_id`, `write`, `read`. In case that the object fields are non-public, you can always define struct `hz_serializer<Person>` as friend to your object class. You use the `object_data_output` class methods when serializing the object into binary bytes and you use the `object_data_input` class methods when de-serializing the bytes into the concrete object instance.
9831103
984-
## 4.4. JSON Serialization
1104+
## 4.5. JSON Serialization
9851105
9861106
You can use the JSON formatted strings as objects in Hazelcast cluster. Creating JSON objects in the cluster does not require any server side coding and hence you can just send a JSON formatted string object to the cluster and query these objects by fields.
9871107
@@ -1008,7 +1128,7 @@ auto result = map->values<hazelcast::client::hazelcast_json_value>(
10081128
hazelcast::client::query::greater_less_predicate(hz, "age", 6, false, true)).get();
10091129
```
10101130
1011-
## 4.5. Global Serialization
1131+
## 4.6. Global Serialization
10121132
10131133
The global serializer is registered as a fallback serializer to handle all other objects if a serializer cannot be located for them.
10141134

0 commit comments

Comments
 (0)