Comments 17
Согласны с тем, что Reactive-фреймворки хорошо подходят для программирования интерфейсов в web и мобильных приложениях, и что они просто прекрасны везде, где есть взаимодействие с человеком через UI. Но не на бэкенде! Там это прекращается в боль.
Отнюдь не верное утверждение. Существует множество сетевых решений, построенных на базе реактивного стека, превышающих нагрузку и в 50 тыс. активных соединений. Конечно, порог вхождения куда выше, чем в императивном программировании. А не разобравшись с технологией, и пробовать даже не стоит. Про любую технологию, в неумелых руках, можно сказать, что она для чего-то не подходит.
Но есть несколько нюансов:
- как уже вы сказали, порог вхождения в такие технологии выше, и чтобы овладеть ими на уровне, необходимом для построения надёжных решений, нужно немало ресурсов (время, деньги, люди);
- насколько я понимаю, реактивный стек более требователен к ресурсам, там гораздо больше слоёв абстракций, и не всегда это хорошо работает, а разбираться с этим тяжеловато;
- в статье мы честно признаёмся, что у нас нет хороших компетенций по реактивному стеку для backend-разработки, и для нас это боль :)
Вторая проблема — это редкие, но внезапные потери сообщений из Redis. Опыт эксплуатации показал, что Redis растеряйка тот еще: его pub-sub механизм не самый надежный, так как клиент, подписываясь на каналы в Redis’е и получая из них сообщения, не отсылает назад никаких подтверждений, а Redis их не повторяет, что порой приводит к потерям.
тут ничего внезапного нет, redis pub-sub всегда был at-most-once системой :) для гарантий at-least-once в редисе есть стримы, на которых тоже можно организовать pub-sub взаимодействие.
Немного странно что редис оказался крайним, при том принятые решения кажутся крайни необдуманными. Хранить в редисе связанные данные и пытаться строить там индексы, вообще кто придумал эти rdbms и зачем там “r” в начале…
Если вам нужна гарантированная доставка зачем ругать редис за то что он ее не гарантирует?
Вдумываться в текст я перестал когда вы решили переписать Java/Kotlin сервис на питон для решения проблем с памятью и производительностью…
Субъективно, каждый инструмент создан для решения определенной проблемы, в данном случае если выкинуть Rx из ЦУП (можно даже Котлин и использовать просто Java), использовать обычную rdbms (Postgres, MySQL) и ходить в ЦУП с ретрансляторов через простой http подняв 1-2 дополнительные ноды ЦУПа для того чтобы избежать потери при деплоях/крашах, дало бы вам стабильное и производительное решение для поддержки которого не сложно найти людей с экспертизой.
Постараюсь ответить по пунктам.
вообще кто придумал эти rdbms и зачем там “r” в начале…
Ну собственно мы и взяли Tarantool для этого, так как он позволяет хранить в том числе и связанные данные :) Redis — да, не очень продуманное решение было, это был скорее прототип. Сами понимаете, прототипы иногда лепятся на скорую руку без особых раздумий :)
Если вам нужна гарантированная доставка зачем ругать редис за то что он ее не гарантирует?
Ругани в сторону Redis особо нет, просто констатировали факт, что его pubsub — не самое надежное решение. В комментариях выше указали на redis streams — интересная вещь, действительно можно было бы её использовать, но это не сильно облегчило бы нам жизнь.
Вдумываться в текст я перестал когда вы решили переписать Java/Kotlin сервис на питон для решения проблем с памятью и производительностью…
На моей практике именно Java имела проблемы с утечками и требовательностью к памяти, в то время как python в этом плане проявил себя лучше: работая с python, реже приходилось вспоминать о памяти и сборщике мусора. А работая с Java-стеком, мне постоянно приходилось держать в голове эти проблемы. Да и многие коллеги ворчали на Java, не только я.
По поводу производительности здесь надо отметить, что приложение сетевое, его задача — принять пакет из одного сокета, что-то с ним сделать, бросить пакет в другой сокет и переключиться на обработку следующего пакета. И производительности python + asyncio хватило бы за глаза и за уши.
Субъективно, каждый инструмент создан для решения определенной проблемы
Безусловно.
в данном случае если выкинуть Rx из ЦУП (можно даже Котлин и использовать просто Java), использовать обычную rdbms (Postgres, MySQL) и ходить в ЦУП с ретрансляторов через простой http подняв 1-2 дополнительные ноды ЦУПа для того чтобы избежать потери при деплоях/крашах, дало бы вам стабильное и производительное решение для поддержки которого не сложно найти людей с экспертизой.
Вы упустили из виду тот момент, что у нас не было тогда хороших компетенций по Java/Kotlin для backend-разработки, да и не очень мы этот стек любим. С, Lua и Python нам гораздо ближе :)
подняв 1-2 дополнительные ноды ЦУПа
Здесь вот какой нюанс: ЦУП общается с MQTT-брокером, и такова специфика, что он должен держать одно соединение с ним, создавать некоторый постоянный набор подписок, и он же должен отслеживать состояние устройств, которые присылают свою телеметрию в ответ на какие-то команды, и в зависимости от их состояния нужно принимать какие-то решения: посылать куда-то что-то или нет, выдать ошибку.
Если же поднимать несколько узлов ЦУПа, то надо решить следующие вопросы:
- репликация состояния, устойчивая к помехам;
- определение того, кто будет мастером, а кто репликой, чтобы соединение с mqtt-держал только мастер;
- механизм failover, чтобы реплика смогла подхватить эстафету при падении мастера.
Уже того, что перечислено, хватит чтобы глубоко задуматься. На Java есть разные решения, но они местами сложные, с ними довольно муторно разбираться. По той же причине отказались от Python/asyncio, так как по факту, мы бы получили точно такой же черный ящик, который сложно будет исследовать в случае каких-то проблем, и для которого надо всё вот это реализовывать вручную.
В случае с Тарантулом это проще: в нем базовые механизмы для работы с репликацией и failover уже есть. Еще немаловажную роль сыграло то, что к нему можно подключиться в консоли и поисследовать состояние системы. Это вообще жирный плюс :)
использовать обычную rdbms (Postgres, MySQL)конечно можно взять классическую RDBMS и попытаться на этом что-то построить, но… Проблема опять же, с увеличением количества устройств растёт и трафик, телеметрии приборы посылают больше и весь этот трафик надо уметь обрабатывать очень быстро. И здесь логичнее держать все данные в памяти, с подушкой безопасности в виде WAL и снимков состояний (snapshots).
к нему можно подключиться в консоли и поисследовать состояние системы
Я осторожно пытался донести мысль, что, не умаляя преимуществ Tarantool, перечислены недостатки не самого Redis, а опыта работы с ним. У них на сайте достаточно подробно изложены основы Best Practices, и, если им не следовать, он конечно будет странно себя вести под серьёзной нагрузкой. Как и любая другая система.
Согласен с тем, что это больше выглядит как недостаток опыта работы с Redis, и недостаток знаний по лучшим практикам. Тем не менее приведу аргумент, который не совсем технический, он больше субъективно-философский.
При сравнении Tarantool и Redis существенным фактором является простота использования. Redis поддерживает широкий спектр различных структур данных и функций, связанных с ними, но, это требует изучения, набивания шишек и нарабатывания какой никакой практики. И это несмотря на первоначальную простоту — установил и пошёл использовать GET'ы и SET'ы (а там и другие структуры и функции), всё вроде бы просто.
С Tarantool приходится немного повозиться в самом начале, но затем его использование становится простым: базис, необходимый для изучения и который пригоден для выполнения 90% задач, довольно небольшой. И имея этот базис, можно повторить практически всё то, что есть в Redis, при этом реализуя это, ты получаешь реальное понимание того, как работает та или иная функция или структура данных. В этом плане Tarantool является более низкоуровневым инструментом, но в то же время весьма эффективным и простым.
И наконец, на базе Redis сложнее строить in-memory computing решения, когда тебе необходимо знать и состояние данных (приходится лезть отдельно в сам Redis через redis-cli), так и состояние программы. Причем это зачастую требуется выяснять на production серверах, а с этим проблематично практически во всех системах программирования, кроме Erlang и Tarantool. Там (в Erlang и Tarantool) можно подключиться к экземпляру сервиса и повыполнять код, с помощью которого можно инспектировать состояние системы.
Подытожу.
Каждый инструмент необходимо знать хорошо, важно уметь с ним работать. Но при выборе инструмента следует учитывать еще и субъективные ощущения от работы с ним, к чему склоняешься больше, что приятнее и что интереснее. Для меня Redis всё же был и остаётся просто навороченным кешом, в котором несколько затруднительно сделать что-то нестандартное, в то время как Tarantool предоставляет мне необходимую свободу действий, так как он позволяет реализовывать всё, что нужно, пусть даже если на это потребуется время.
Надеюсь, мне удалось прояснить свою позицию в этом вопросе :)
Мне кажется, ровно наоборот: Redis гораздо ближе к «продолжению кодовой базы» на уровне примитивов, чем остальные, ощущается, как если-бы вы использовали модули кэша на уровне приложения.
Из серьёзных плюсов:
на нём (частично) работает очень много супер высоконагруженных систем, включая Твиттер и Инстаграмм, и они охотно делились своими конфигурациями.
По нему очень много информации и уже решённых проблем на SO.
У него есть очень продвинутые дополнительные модули.
Совсем не обязательно работать через cli, прокидываете через туннель соединение с продакшен и используете RedisInsight.
Просто сравните размеры сообществ и количество каналов связи с профессионалами.
Я ещё штук 10 плюсов могу накидать, но я не уверен, что оно вам нужно, раз вы уже с него съехали на Тарантул. Да и остальные я пробовал не так основательно, в основном по литературе, докладам и бенчмаркам, без реального жамканья руками и сравнений по схожим нагрузкам.
Tarantool'у тоже есть что сказать :)
Его сообщество не такое конечно большое, но оно развивается и растёт. Чем больше людей интересуется и пробует, тем больше всяких разных вопросов возникает, больше исправлений, больше отдачи, больше наработок.
По поводу поддержки со стороны компаний — Mail.ru ведь большая компания, и она поддерживает этот продукт и использует :) И Tarantool используется не только в mail.ru.
Мне кажется, ровно наоборот: Redis гораздо ближе к «продолжению кодовой базы» на уровне примитивов, чем остальные, ощущается, как если-бы вы использовали модули кэша на уровне приложения.
Если требуется построить систему на выбранном языке (Go/Pyton/Java/whatever) и использовать Redis как полностью внешний агент, то наверное да, с учётом поддержки его в разных ЯП, это вполне обосновано, действительно можно использовать как модуль для кеширования без особых заморочек.
Но в нашем случае у нас построена система, где вычисления производятся рядом с данными, нет издержек на обмен по сети между сервисом и хранилищем, и это не совсем укладывается в схему, где in-memory система используется как незаметный кеш. Tarantool в этом случае подходит больше. Более того, модель данных в Tarantool близка к реляционной, и там есть возможность строить индексы по значениям, и это сильно удобнее, чем городить массу ключей и структур в Redis, чтобы связать все данные (о чём и написано было в статье). А нам приходится связывать данные между собой, их структура не совсем простая :)
То есть, здесь я акцентирую внимание ещё на том, что мы используем Tarantool как сервер приложений с in-memory БД, а не чисто как внешнее хранилище в памяти.
Совсем не обязательно работать через cli, прокидываете через туннель соединение с продакшен и используете RedisInsight.
Здесь я имел в виду общее удобство работы с системой. Совершенно неважно, GUI или CLI это, важен другой аспект: возможность отладки и залезания прямо в процесс самого сервиса, и всё это в одной связке — и данные и код. То есть, цикл разработки и отладки такой получается: «вижу проблему» -> «подключаюсь к процессу сервиса» -> «смотрю состояние кода, выполняю некоторый Lua-код прямо в консоли, смотрю данные» -> «нахожу проблемное место, исправляю данные и состояние, пробую» -> «оцениваю результат» -> «заношу исправление в репозиторий с кодом». Как то так получается. Даже если мы берём RedisInsight, то во первых, мы вынуждены будем прыгать между RedisInsight, отладчиком и чем то там ещё; а во вторых — нет возможности «исправить» проблему тут же, на месте, надо вносить изменения в код, потом пересобирать, перезапускать, и так далее. Это не для production-использования, для production весь доступ к данным в режиме отладки конечно же readonly, но для отладки кода при разработке это очень удобно.
И напоследок, хотелось бы поинтересоваться…
я до сих пор не уверен в правильности выбора и пока фарш ещё можно провернуть назад.
А какими критериями при выборе in-memory решения вы руководствуетесь?
А какими критериями при выборе in-memory решения вы руководствуетесь?
В порядке убывания важности:
- Мнением адвайзера — главного DB архитектора нескольких огромных высоконагруженныз систем (знание тонкостей и валидность прогнозов достигается только многими годами узкой специализации)
- Быстродействием (это всего лишь реплика горячей части данных, консистентность важна меньше)
- Горизонтальной расширяемостью (решается по разному)
- Распространённостью применения (и, соответственно, массой готовых решений)
- Базой типовых «лучших практик» для каждой задачи
- Доступом к профессионалам с многолетним опытом (у остальных по 2 канала связи и спецов на рынке, ну типа нет вообще)
- Отсутствием статуса монополиста у производителя и его возможности с этим играться
Было серьёзное искушение плюнуть на все соображения и использовать VoltDB, но я сварщик не настоящий для такого лихачества.
Чем Tarantool круче Redis'а для IoT-сервисов