Как эффективно добавлять объекты в распределенную очередь в hazelcast?

Добавление элементов в распределенную очередь в hazelcast происходит невероятно медленно (читай: 66 элементов в секунду; это нормально?), когда очередь хранится на узле, отличном от того, на котором выполняется код (и установлен в 0 в конфигурации для этой очереди). Есть ли способ добавить элементы из узла владельца? Есть ли что-то принципиально неправильное в моем подходе с использованием Hazelcast?

Эта операция занимает около 15 секунд:

public static void main(String[] args) throws ExecutionException {
    HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance();
    IQueue<String> configs = hazelcastInstance.getQueue("configs");  
    for(int i = 0; i<1000;i++) {
        configs.add("Some string"+i);
    }
}

Изменение значений и в конфиге (см. ниже) никак не влияет на скорость выполнения. Я бы предположил, что увеличение заблокирует операции вставки, а увеличение - нет (на самом деле цикл должен выполняться так же быстро, как если бы операция #add находилась в локальной очереди). Однако время выполнения цикла for такое же. Даже если я установлю оба значения на 0. Я что-то упустил?

<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xsi:schemaLocation=
  "http://www.hazelcast.com/schema/config hazelcast-config-3.7.xsd"
  xmlns="http://www.hazelcast.com/schema/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <network>
        <port auto-increment="true" port-count="20">5701</port>
        <join>
            <multicast enabled="false">
        </multicast>
        <tcp-ip enabled="true">
            <member>172.105.66.xx</member> 
        </tcp-ip>
        </join>
    </network>

    <queue name="configs">
        <statistics-enabled>false</statistics-enabled>
        <max-size>0</max-size>
        <backup-count>0</backup-count>
        <async-backup-count>1</async-backup-count>
        <empty-queue-ttl>-1</empty-queue-ttl>
    </queue>
</hazelcast>

person cobby    schedule 15.06.2019    source источник


Ответы (1)


Есть несколько способов оптимизировать очередь. Очередь может хранить ваши записи в двоичном виде или в форме объекта. Кроме того, вы можете указать количество резервных копий, чем больше резервных копий, тем медленнее будет. Количество реплицируемых бэкапов по умолчанию равно 1. Это означает, что для каждого pu у вас будет одна репликация помимо пут. Вероятно, больше всего производительность при использовании бинарной формы хранения записей повышает сериализация. Сериализация Java очень медленная. Вместо этого используйте DataSerializeable или IdentifiedDataserializeable.

Вам также необходимо проверить задержку вашей сети для некоторых медленных сетей, у вас будет задержка 1-2 мс только для сетевой связи для 1000 вставок, это будет 1000-2000 мс, что составляет 1-2 секунды ожидания сети.

Для пакетных операций вы можете выполнять вставки параллельно, если порядок вставок не важен.

И Queue может иметь асинхронные резервные копии, которые снова немного повысят производительность.

ОБНОВЛЕНИЕ: при нормальной работе приложения у вас редко будет одиночный сценарий. Поэтому вместо того, чтобы вставлять эти 1000 значений одно за другим, сделайте следующее:
List arrayList = new ArrayList();

for(int i=0;i<1000;++i) {
   arrayList.add("myString " + i);
}

arrayList.paralelstream().forEach(t->configs.put(t));

Теперь вы вставляете параллельно.

person Alexander Petrov    schedule 15.06.2019
comment
Я обновил свой пост о резервных копиях. Я это уже пробовал. Что вы имеете в виду под параллельным выполнением пакетных операций? В разных темах? - person cobby; 15.06.2019
comment
@cobby смотрите обновление. Также вы измерили задержку в вашей сети между двумя серверами? - person Alexander Petrov; 15.06.2019
comment
Да, это 13 мс, что ясно объясняет низкую производительность. Большое спасибо, приятель! Что вы думаете о проблеме резервного копирования очереди? - person cobby; 15.06.2019
comment
@cobby indead :) с таким программным обеспечением вы должны ориентироваться на задержку менее 1 мс в целом. Но это очень сильно зависит от того, что вы можете терпеть. - person Alexander Petrov; 15.06.2019
comment
parallelStream() увеличивает скорость примерно в два раза. Просто собирая объекты в локальный список и выполняя пакетную вставку с configs.addAll() примерно на 100 :) - person cobby; 15.06.2019
comment
Вы заявили, что количество резервных копий снижает скорость (при использовании стратегии синхронизированного резервного копирования). Но что именно блокируется, когда, скажем, узел A выполняет операцию вставки в распределенную очередь, которая находится на узле B? Следующий оператор на узле A, узле B или на обоих узлах задерживается до завершения резервного копирования? - person cobby; 17.06.2019