И еще интересно: у Вас после восстановления данных из бэкапов новые бэкапы создались внутри одного ДЦ? Мне кажется, их не должно б быть. Тогда и скорость put'ов еще возрастет…
Да, бэкапы создаются в рамках оставшейся части нод одной группы партиций. У нас это четко видно на графиках мониторинга количества элементов в коллекциях и количества забэкапленных элементов коллекций — после отключения одного ДЦ их количество не изменяется
Поскольку SmartRouting у Вас отключен, запросы с клиента идут не прямо на ноду, содержащую данные, а на случайную ноду кластера. Могут попасть и в другой ДЦ, затем запрос будет перенаправлен в «правильный» ДЦ. Запросы между ДЦ, обычно, гораздо медленнее запросов внутри одного ДЦ. Поэтому, когда один ДЦ отключился, все стало ~ в два раза быстрее
При отключенном smartRouting клиент подключается не к рандомной ноде кластера, а к той, что прописана в настройках подключения. Далее получение данных отдано на откуп Hazelcast. Клиента одного ДЦ подключаются к нодам того же ДЦ.
В обоих схемах не избежать походов за данными в другой ДЦ. Да, на графике виден эффект от исключения похода в другой ДЦ
Сколько памяти вы даете каждой ноде? Где-то видел рекомендацию про не более 4Гб.
512*25 серверов=12.5Gb. Нам хватает с кратным запасом. Кластер расположен на серверах рядом с другими сервисами. Если вам нужна другая конфигурация, то нужно просто провести нагрузочное тестирование, подтюнить GC.
Вот тест с 2Тб — https://www.youtube.com/watch?v=DozGQMHRoZI
Можете рассказать подробнее про потерю нод, датацентра? Как быстро кластер выкидывает ноду и продолжает работать? Как вы тестировали? (про потерю датацентра видел, но интересует с точки зрения простоев и SLA).
Весь процесс выключения ноды занимает ~500мс, из них ~30 мс штатный вывод из кластера. Бывают исключения, когда весь процесс затягивается до 5 секунд, что связано с Gracefull Shutdown.
Выкидывание по причине потери связи с одной из нод бывает крайне редко, обычно укладывается в таймауты.
Время за которое кластер восстанавливает нормальную работу хорошо видно в Kibana — это период времени когда был всплекс ошибок чтения/записи в Hazelcast. При нештатном выкидывании ноды из кластера в логах наблюдаются единичные ошибки в течении максимум 1 секунды
hazelcast.client.max.no.heartbeat.seconds,
hazelcast.heartbeat.interval.seconds,
hazelcast.client.invocation.timeout.seconds
и другие таймауты
?
По дефолту они выставлены в довольно большие значения и при потере ноды hazelcast уходит в себя. В статье видел упоминания про 400 мс ограничение на клиенте. Получается, кластер у вас тормозит, когда нода выпадает, но со стороны клиента вы как-то в итоге повторяете ту же самую операцию?
Значения таймаутов клиента установлены по умолчанию. Таймаутом управляет конкретный бизнес процесс. Например, задача запускается из асинхронной очереди и пытается получить данные из Hazelcast с помощью IMap::getAsync(key).get(operationTimeout.getMillis(), TimeUnit.MILLISECONDS)), где operationTimeout — параметр конфигурации клиентского приложения, согласно требованиям к нему. Если Hazelcast ушел в себя, компонент ушел в себя, сеть мигнула или пожар, то ничего страшного — через operationTimeout задача прервется и через некоторое время запустится вновь.
В случае синхронных операций, которым требуется сделать вызов Hazelcast, прерывание операции так же обрабатывает клиент запустивший эту операцию. Например, пришел http запрос и мы пытаемся получить из Hazelcast кэш данных, не дождавшись данных за operationTimeout отдаем клиенту ошибку, который может сделать повторный вызов для исключения единичных сбоев.
А вы подкладываете в Hazelcast свои jar-ы (domain-классы) для сериализации/десериализации/выборке по индексу? Удается ли в случае изменений в таких классах обновляться без остановки кластера?
Так как мы запускаем каждую ноду программно как часть java-приложения, то храним доменные объекты прямо в коде этого компонента. Однако, это не широко распространенный кейс из-за описанных вами сложностей. Фактически мы не меняем доменные объекты.
Основной объем информации хранится в виде IMap<String, String>, в качестве ключа — уникальный идентификатор, значение — POJO сериализованный в JSON. Сериализацией/десериализацией управляет клиент, обратная совместимость реализуется очень просто. В результате никаких простоев
Начиная с 3.6, клиенты и ноды начали общаться по стандартному протоколу Hazelcat Open Client Protocol, что позволяет обновлять минорные версии нод и клиентов в разное время.
В 3.8 EE (Enterprise Edition) появилась возможность обновлять минорные версии нод «на горячую», т.е. обновлять 3.8 -> 3.9, 3.9->3.10 и тд.
Исходя из всего выше описанного, обновление на 3.8 очень рекомендовано..
В первую очередь собираемся обновляться до 3.8 как раз для этого. Можете порекомендовать варианты миграции с предыдущих версий? Мы сейчас в процессе изобретения велосипеда для миграции без простоя (:
Соглашусь что документация хорошая, актуальная и позволяет получить информацию и рекомендации по продукту. Но лучшая документация — исходный код. Он у вас хорош, действительно. Прочитал код и сразу все понятно как работает
вот только вчера выкатили 3.9-EA (early access) с новой фичей про добавление конфигураций динамически.
Можно пробовать!
Позволяет добавлять только новые конфигурации на горячую. Основной кейс у нас — изменение текущих конфигураций. Программное добавление конфигураций подразумевает реализацию динамического изменения конфигов в компоненте, запускающем Hazelcast ноду. Это усложняет разработку, тестирование и поддержку компонента. Гораздо прозрачней для эксплуатации безопасно выключить ноду и запустить с новыми конфигами
(MapListener) Я бы не рекомендовал. Лучше поглядите на Diagnostics — фича, highly inspired by Metrics framework.
Спасибо за рекомендацию. Однако, мы логируем с помощью MapListener не статистику, а события по изменениям данных в коллекциях. Например, добавления с конкретным значением key, эвикты, удаления.
Статистику по каждой коллекции мы мониторим на основе данных IMap::LocalMapStats, отправляя их напрямую в Graphite. Таким образом получаем графики с latency, которые присутствуют в статье
Начиная с 3.7, eviction был очень сильно переработан. Об алгоритме можно почитать тут и тут.
Проблема с ложным срабатыванием FREE_HEAP_PERCENTAGE воспроизводится на 3.8. Проблема описана в статье — политика срабатывает при достижении размера занимаемой памяти всем приложением. На графике «Garbage Collector за работой» показано как происходит выделение и освобождение памяти — видно, что график много раз за день пересекает границу в 75% от доступной памяти. Это приводит к срабатыванию FREE_HEAP_PERCENTAGE=25%, хотя данных в коллекциях не так много. Я бы не назвал это ошибкой в Hazelcast, скорее — особенностью реализации. А вот за реализацией нужно идти в исходный код, в документации про реализацию ничего не сказано
Обычно, из-за высокой latency между датацентрами, мы не рекомендуем размазывать кластер Hazelcast на множестно датацентром. есть WAN Replication, но как и у многих конкурентов она входит в платный пакет.
Наш опыт показывает что latency просаживается не существенно. Не нашел в документации информацию по WAN Replication — поддерживается ли репликация между двумя разными версиями Hazelcast?
Информация
В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Да, бэкапы создаются в рамках оставшейся части нод одной группы партиций. У нас это четко видно на графиках мониторинга количества элементов в коллекциях и количества забэкапленных элементов коллекций — после отключения одного ДЦ их количество не изменяется
При отключенном smartRouting клиент подключается не к рандомной ноде кластера, а к той, что прописана в настройках подключения. Далее получение данных отдано на откуп Hazelcast. Клиента одного ДЦ подключаются к нодам того же ДЦ.
В обоих схемах не избежать походов за данными в другой ДЦ. Да, на графике виден эффект от исключения похода в другой ДЦ
512*25 серверов=12.5Gb. Нам хватает с кратным запасом. Кластер расположен на серверах рядом с другими сервисами. Если вам нужна другая конфигурация, то нужно просто провести нагрузочное тестирование, подтюнить GC.
Вот тест с 2Тб — https://www.youtube.com/watch?v=DozGQMHRoZI
Весь процесс выключения ноды занимает ~500мс, из них ~30 мс штатный вывод из кластера. Бывают исключения, когда весь процесс затягивается до 5 секунд, что связано с Gracefull Shutdown.
Выкидывание по причине потери связи с одной из нод бывает крайне редко, обычно укладывается в таймауты.
Время за которое кластер восстанавливает нормальную работу хорошо видно в Kibana — это период времени когда был всплекс ошибок чтения/записи в Hazelcast. При нештатном выкидывании ноды из кластера в логах наблюдаются единичные ошибки в течении максимум 1 секунды
Значения таймаутов клиента установлены по умолчанию. Таймаутом управляет конкретный бизнес процесс. Например, задача запускается из асинхронной очереди и пытается получить данные из Hazelcast с помощью IMap::getAsync(key).get(operationTimeout.getMillis(), TimeUnit.MILLISECONDS)), где operationTimeout — параметр конфигурации клиентского приложения, согласно требованиям к нему. Если Hazelcast ушел в себя, компонент ушел в себя, сеть мигнула или пожар, то ничего страшного — через operationTimeout задача прервется и через некоторое время запустится вновь.
В случае синхронных операций, которым требуется сделать вызов Hazelcast, прерывание операции так же обрабатывает клиент запустивший эту операцию. Например, пришел http запрос и мы пытаемся получить из Hazelcast кэш данных, не дождавшись данных за operationTimeout отдаем клиенту ошибку, который может сделать повторный вызов для исключения единичных сбоев.
Так как мы запускаем каждую ноду программно как часть java-приложения, то храним доменные объекты прямо в коде этого компонента. Однако, это не широко распространенный кейс из-за описанных вами сложностей. Фактически мы не меняем доменные объекты.
Основной объем информации хранится в виде IMap<String, String>, в качестве ключа — уникальный идентификатор, значение — POJO сериализованный в JSON. Сериализацией/десериализацией управляет клиент, обратная совместимость реализуется очень просто. В результате никаких простоев
В первую очередь собираемся обновляться до 3.8 как раз для этого. Можете порекомендовать варианты миграции с предыдущих версий? Мы сейчас в процессе изобретения велосипеда для миграции без простоя (:
Соглашусь что документация хорошая, актуальная и позволяет получить информацию и рекомендации по продукту. Но лучшая документация — исходный код. Он у вас хорош, действительно. Прочитал код и сразу все понятно как работает
Позволяет добавлять только новые конфигурации на горячую. Основной кейс у нас — изменение текущих конфигураций. Программное добавление конфигураций подразумевает реализацию динамического изменения конфигов в компоненте, запускающем Hazelcast ноду. Это усложняет разработку, тестирование и поддержку компонента. Гораздо прозрачней для эксплуатации безопасно выключить ноду и запустить с новыми конфигами
Спасибо за рекомендацию. Однако, мы логируем с помощью MapListener не статистику, а события по изменениям данных в коллекциях. Например, добавления с конкретным значением key, эвикты, удаления.
Статистику по каждой коллекции мы мониторим на основе данных IMap::LocalMapStats, отправляя их напрямую в Graphite. Таким образом получаем графики с latency, которые присутствуют в статье
Проблема с ложным срабатыванием FREE_HEAP_PERCENTAGE воспроизводится на 3.8. Проблема описана в статье — политика срабатывает при достижении размера занимаемой памяти всем приложением. На графике «Garbage Collector за работой» показано как происходит выделение и освобождение памяти — видно, что график много раз за день пересекает границу в 75% от доступной памяти. Это приводит к срабатыванию FREE_HEAP_PERCENTAGE=25%, хотя данных в коллекциях не так много. Я бы не назвал это ошибкой в Hazelcast, скорее — особенностью реализации. А вот за реализацией нужно идти в исходный код, в документации про реализацию ничего не сказано
Наш опыт показывает что latency просаживается не существенно. Не нашел в документации информацию по WAN Replication — поддерживается ли репликация между двумя разными версиями Hazelcast?