Comments 23
Но теперь, в один прекрасный момент, случайно, система дала сбой и кеш рухнул. Ничего особенного – ведь кеш выбрали по требованию «высокая скорость чтения и записи, остальное неважно»… Вывод: высоконагруженные проекты в проде требуют от системы кеширования не только высокой скорости чтения и записи, но также сохранности данных и устойчивости к сбоям.


Можно поподробнее, что такое «кеш рухнул»? В чем конкретно это выражалось на клиентской и серверной частях и как долго продолжалось?

Но, здесь такой выбор оказался неудачным – под наш профиль нагрузки Hazelcast работает не просто медленно, а жутко медленно.


Интересно! Хотелось бы деталей касательно профиля.
Можно поподробнее, что такое «кеш рухнул»?

Очень подробный и точный ответ дан в предыдущем комментарии, от miksir

Добавлю только, что прогрев кеша на продакшн-объемах данных — в редкой системе не приведет к выходу даунтайма за рамки SLA.
Добавлю только, что прогрев кеша на продакшн-объемах данных — в редкой системе не приведет к выходу даунтайма за рамки SLA.


Можно здесь конкретизировать, в цифрах? Скорость прогрева кэша, каковы рамки SLA?
для админки к товарному контуру, в 2017 было требование прогонять все данные за 10 минут. Прогреть кеш — в нашем случае можно было только запустив ETL на всех данных. Это порядка 30Гб сериализованных данных для результатов промежуточных вычислений.
Благодарю — то, что надо!

Однако ж, еще пара вопросов, если можно.

1) Какова была архитектура кеша до падения ( количество узлов, распределенность/репликация?)
2) 30Гб — что это за данные, вкратце? Описание товаров/складов/пользователей/счетов или что-то еще типа заказов/оплат/списаний?
1. На первых порах взяли IMap с репликацией 1, в кластере из 4 узлов. То есть, для каждого шарда в кластере есть 2 узла, на которых он представлен. Но, когда узел «отваливался» из кластера — вот на нем то данных и не хватало.
Сейчас перешли на ReplicatedMap.

2. Здесь я указал данные по админке, которые нужны в ETL-расчетах — в основном для обеспечения вычислений по дельтам данных (флаги, что где проходило ранее). Немного про эту систему будет в следующей части статьи. И, возможно, подробно расскажу про наш дельта-процессор отдельным постом. Но это объемно и не скоро )
В чем конкретно это выражалось на клиентской и серверной частях и как долго продолжалось?

На проде мы такой неприятности не ловили. Подготовились благодаря тестам на uat.
Для Hazelcast версий 6-ти летней давности, при запуске в сетевом окружении того времени — узлы довольно часто теряли друг друга из вида, из-за чего кластер перестраивался. Потом кластер восстанавливался, но на некоторое время узел мог остаться без части данных. Потребовалось время, чтоб разобраться в настройках. Сейчас такой проблемы нет.
Хотелось бы деталей касательно профиля.

Профиль нагрузки в задачах админки того времени: put/get запросы в любой пропорции и за объектами любого размера.
Точной картинки спектра не сохранилось, но примерно:
* пропорция put/get в основном попадает в диапазон от 1:2 до 1:10, но есть несколько пиков в районе 1:100 и 1:10 000
* размер объектов — от небольших с 2-5 полями, до слонопотамов с 15 этажами вложенности (в сериализованном виде 10Кб, и несколько объектов поболее 100Кб)

на этом этапе Hazelcast кое-как устраивал. То есть, было плохо, в заданные рамки 10^5 RPS мы совершенно не укладывались, но была надежда, что можно что-то подкрутить, что-то вынести в специальный «горячий» кеш в памяти (тех самых итоговых слонопотамов, которых генерили в ETL). Была надежда, что потом еще что-нибудь в логике оптимизируем и будет нормально.

Но условия поменялись.
Добавилось очень, очень много запросов, когда по ключу нужно хранить только true/false.
И вот здесь стало совсем плохо.
То, что должны были выполнять за 10 минут — работало более 30 часов. То есть, через 30 часов тест прекратили, за сколько он отработал бы — осталось не известно.
Можно поподробнее, что такое «кеш рухнул»?

Я не автор, но видимо кеш просто очистился ;)


Если делается неперсистентный кеш, то он может разом пропасть. Т.е. неперсистентный кеш можно использовать для снижения времени ответа, но нельзя — для экономии железа. Или если хочется использовать для экономии железа — должна быть система прогревки кеша с допустимым даунтаймом сервиса или какая-то система деградации сервиса на время прогревки кеша. Но все это с потерей аптайма.


Персистентный кеш тут выглядит удобнее, но это уже и не кеш вовсе, а полноценная база с денормализованными данными и требованиями по эксплуатации и отказоустойчивости. Соответсвенно смотреть нужно не сколько на скорость, а на то, как осуществляется отказоустойчивость, как обеспечивается персистентность, есть ли шардирование хотя бы на уровне библиотеки, какой опыт эксплуатации базы в команде. Ну и проводить соответсвующие испытания — не "как быстро читает", а "что будет если мы этот вот сервер выключим".

Да, доклад и статья — написаны по мотивам одних и тех же событий :)
Доклад был раньше

Почему все так любят добавлять кеш к серверу? Это же сразу добавление в проект race-conditions и проблем с консистентностью данных. Советую посмотреть доклад на эту тему — https://www.youtube.com/watch?v=5ZjhNTM8XU8

miptalex Я не знаток ритейла и мне сложно представить, что это за данные вы такие кешируете. Судя по описанию у вас в кеше лежит что-то, что должно много раз в секунду обновляться и читаться. Причем нагрузка такая, что нужно иметь несколько серверов. Что это такое у вас в кеше лежит?
в данных, которые использует сайт — достаточно активно обновляются остатки товара, из-за чего происходит пересчет доступности.
Все данные, которые отображаются на сайте и не являются хардкодом — попадают через базу, и почти все кешируются. Это и банеры, плашки, публикации, меню, настройки и все-все-все.
А остатки товара распределены по складам/магазинам или есть какой-то «глобальный остаток» по каждому товару, каковой остаток все часто смотрят?
Остатки распределены, и по складам и по магазинам (выступают в роли складов). Но отображать на сайте требуется не только остатки, но и условия доставки (уровень сервиса) — а на это влияют еще характеристики самого товара (крупно/мелко-габаритный, группы). В итоге, расчетов достаточно.
Как обстоят дела с распределением запросов по товарам на сайте именно сейчаc — не знаю, не могу сказать есть ли ярко выраженные пики (или наоборот, long-tail). Раньше не было.
Я додумаю немного — представим, что корзина покупателя может комплектоваться из разных складов и регионов, тогда для формирования корзины, а также отображения условий покупки товара нужно знать: местоположения пользователя, адрес доставки, остатки товара на всех складах. Сама покупка заключается в получении оплаты и формировании заказа. Формирование заказа это резервация товара, фактически флажек в базе. Далее вся эта история отправляется в доставку, но это уже другая история и другая система.

Если все примерно так, то вам не кеш нужен, а нормальная модель в памяти. Чтения все из памяти, обновления тоже. Модель должна быть сделана так, чтобы при обновлении появлялся diff, который отправляется в очередь, откуда рассылается на другие узлы и записывается в базу. Нужно еще сделать механизм разруливания конфликтов, когда одни и туже вещь купили два раза. Если бы была база, то это решил бы ACID, а тут нужно будет понятие «over sale» иметь в предметной области.
Формирование заказа это резервация товара, фактически флажек в базе.

Да, все именно так, обработка заказа — это другая система.

Модель должна быть сделана так, чтобы при обновлении появлялся diff

Админка, которую разрабатывали, самая сложная ее часть — ровно про это — как генерить diff в данных подготовленных для сайта используя только diff по исходным данным. При этом схема трансформаций — это 100+ узлов и в 2 раза больше связей между ними (в среднем 1,9 связей на 1 узел). Чтоб с этим справиться в плане поддержки/доработки — был составлен движок. Внутренности этого движка активно производят вычисления и дают основную нагрузку по админке. Сложности с кешированием — словили как раз для промежуточных результатов этих вычислений.
Об этом проекте — будет отдельный пост.
Добрый вечер.

Выбрали Apache Ignite по причинам:
1) sql (включая ddl) + полноценный acid, что фактически даёт Distributed RDBMS
2) .net interface
Как следствие linq provider, сервисы на нодах можно писать на шарпах
3) избыточность данных для восстановления при падении ноды
4) в последних версиях можно расширять data storage на HDD/SSD

Остальные фичи — ML, Streams, Messages на выбор не влияли.
Жаль только, что .Net и остальные — языки «второго сорта» и
поддержка основных фич = JVM.
«Как мы в Спортмастере...» из-за такой дикой рекламщины с самого названия, теряется желание читать статью. Будто читателю очень важно знать, в какой именно компании выбирали систему кэширования.
Only those users with full accounts are able to leave comments. Log in, please.