Hazelcast Java Сериализация / десериализация ArrayList Pitfall - PullRequest
0 голосов
/ 27 ноября 2018

Я переключился с Memcached на Hazelcast.Через некоторое время я заметил, что размер кэша был больше обычного.С мужским центром.

Итак, я сделал так: 1. Прежде чем вызывать IMap.set (ключ, значение (ArrayList), я десериализирую значение в файл размером 128K. 2. После IMap.set ()называется, я IMap.get () та же карта, которая неожиданно имеет теперь 6 МБ .

У рассматриваемого объекта есть много объектов, на которые ссылаются несколько раз в одной и той же структуре.

Я открыл 2 двоичных файла и увидел, что в 6-мегабайтном файле много дублированных данных. Сериализация, используемая hazelcast, каким-то образом делает копии ссылок

  • Все классы, созданные для Cache, являются сериализуемыми, кроме Enums.

  • при использовании Memcached размер значения в обоих случаях составляет 128K.

  • Я попробовал Kryo с помощью фундука, и не было никакой разницы, все еще более 6 МБ

У кого-то была похожая проблема с hazelcast? Если да, как вы решили эту проблему без изменения кэша?провайдер.

Я мог бы ппокажите структуру объекта и попробуйте воспроизвести ее с нечувствительными данными, если это кому-то нужно.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Я не притворяюсь, но после потерянного дня я наконец нашел решение, которое обходит это.Я не могу сказать, является ли это функцией или просто проблемой для сообщения.

Во всяком случае в Hazelcast, если вы введете IMap значение как ArrayList , таким образом, будет сериализованВход по входу.Это означает, что если у нас есть 100 записей одного и того же экземпляра A, который равен 6 КБ, у нас будет 600 КБ с Hazelcast.Вот короткий RAW-код, который подтверждает мой ответ.

Чтобы обойти или избежать этого с помощью сериализации Java, вы должны обернуть ArrayList в объект, это поможет.

(только с Serializable, без других реализаций)

   @Test
public void start() throws Exception {



    HazelcastInstance client = produceHazelcastClient();

    Data data = new Data();

    ArrayList<Data> datas = new ArrayList<>();

    IntStream.range(0, 1000).forEach(i -> {
        datas.add(data);
    });

    wirteFile(datas,"DataLeoBefore","1");


    client.getMap("data").put("LEO", datas);

    Object redeserialized = client.getMap("data").get("LEO");

    wirteFile(redeserialized,"DataLeoAfter","1");

}

public void wirteFile(Object value, String key, String fileName) {
    try {
        Files.write(Paths.get("./" + fileName + "_" + key), SerializationUtils.serialize(((ArrayList) value)));
    } catch (IOException e) {
        e.printStackTrace();
    }
}
0 голосов
/ 27 ноября 2018

Hazelcast может быть настроен на использование нескольких различных схем сериализации;Сериализация Java (по умолчанию) наименее эффективна с точки зрения времени и пространства.Как правило, выбор правильной стратегии сериализации дает большую отдачу, чем любая другая оптимизация, которую вы могли бы сделать.

Справочное руководство дает хороший обзор различных схем сериализации и соответствующих компромиссов. IMDG Справочное руководство v3.11 - Сериализация

Обычно я использую IdentifiedDataSerializable, если мое приложение полностью Java, или Portable, если мне нужно было поддерживать многоязычные клиенты или управление версиями объектов.

Если вам по какой-то причине нужно использовать сериализацию Java, вы можете проверить и убедиться, что для свойства SharedObject установлено значение true, чтобы избежать создания нескольких копий одного и того же объекта.(Это свойство может быть установлено с помощью элемента в hazelcast.xml или программно через объект SerializationConfig).

...