Много пакетов существует готовых и хорошо оптимизированных если не хотите делать сами.
Не понял, причём тут built-in map. Я map привёл в качестве примера к двум предыдущим предложениям: "С Watch вы не получаете полноценную реплику данных. Её функциональность будет ограничена той структурой, которую вы выберете для хранения данных."
Резюме такое: Буду максимальным душнилой, но не считаю что вы что-то ускорили и это некий "тру" путь к высоконагруженным приложениям. На вид очередная борьба с ведьмами из-за неправильного инжиниринга. Конечно, под капот я не заглядывал, но по описанию очень похоже. Более того сам горизантальный шаринг будет как снежный ком накручивать в дальнейшем усложнения в взаимодействии.Вот выше комментарий был что когда данных много, например 100гб. При текущей стоимости RAM – 100гб это ничто. Говорю как человек у которого есть сервис с кэшем внутри себя на 450гб. И если нужно больше, просто докупается либо RAM (если позволяет сервер), либо новый сервер. И как бЭ кому не хотелось рассказать о том что 450гб ого-го, это много...а если откажет...все придет к тому что одно приложение(монолит) которое внутри себя молотит и считает кэш на условном сервере будет быстрее во много-много раз чем любая связка Redis/Watch, и точек отказа меньше...и само поведение более предсказуемо.
Если честно, ничего не понял) Какие ведьмы? Что шардинг накручивать будет? Что там ваш монолит молотит на условном сервере? При чём тут связка redis/watch. Но за интерес к статье спасибо!
Отсюда возникает потребность сформировать общие положения и рекомендации на каких объёмах данных Вас ещё не догнало то, от чего Вы убежали.
В целом мы и не пытались разместить большие объёмы данных в RAM, я писал об этом: "семь из восьми сущностей — это справочные данные, а полный размер их коллекций не превышает нескольких мегабайт".
Когда данных много, ну например 100 Гб. Они явно уже в сервис не влезут. Появляется необходимость шардинга, но уже Ваших сервисов, например - по месяцам. Но один в поле не воин, одна шарда - это не отказоустойчиво. Надо 3 хотябы. Ну и вот Вы создали кластер редиса. Который работает быстрее редиса, потому что у редиса видимо нет API - чтобы данные напрямую из него тащить и watch интегрировать в него. Появился чудо-сложный балансировщик трафика, которому надо ещё правильно клиентские запросы балансировать по Вашим шардам-репликам. А ещё Вы сталкиваетесь с людскими хотелками - хотим отчёт за год, а у Вас данные по разным шардам...
Если есть потребность заиметь горячую сотню другую гигабайт данных, то нужно быть готовым решать не тривиальные технические задачи, взвешивать решения и, возможно, идти на компромиссы, потому что серебряной пули не существует. Я думаю, кейс с большим объёмом данных в RAM - хорошая тема для другой статьи.
А ещё было бы не плохо понять сложность самих запросов на чтение.
Если говорить о запросах, которые генерирует аудитория сайта, и которые создают основную нагрузку, то это максимально простые выборки по первичному ключу.
Есть и сложные запросы с различными вариантами сортировок, которые генерируют менеджеры и внутренние системы-потребители. Это капля в море с точки зрения нагрузки. Но их мы уже, как правило, выполняем средствами mongodb. А сложной иерархии, агрегаций или джойнов средствами БД мы избегаем.
На самом деле подход довольно привычный. Это частный случай event driven архитектуры. Из непривычного здесь только то, что в роли агента (источника события) выступает не приложение, а СУБД, оно же служит и транспортом. То что Watch основан на внутреннем механизме репликации БД вообще восхитительно. Вы гарантировано получаете правильную последовательность событий.
Минус в том что Watch это курсор с пуллингом, когда такох курсоров много сам пуллинг будет сжирать CPU базы.
А много - это сколько?
в Atlas в некоторых сценариях масштабирования базы Cahngestream Cursor просто перестают получать апдейты, каеф.
Не работал с atlas, но было бы интересно узнать, о каких сценариях масштабирования идёт речь, и о причинах, по которым change stream cursor перестаёт получать апдейты и при этом не возвращает ошибку.
не понятно причем тут 30k RPS - сократить количество запросов за счет InMem кэша да, но RPS просто не докатываются до MongoDB.
Я могу ошибаться, но этому кейсу вроде бы вся статья посвящена: как с помощью watch запилить in-memory хранилище, избавиться от запросов в бд, и какой профит можно от этого получить. 30k rps на ресурсах одного ядра, имхо, убедительный профит.
В сообщении watch приходит модель БД. Никто не запрещает обработать(конвертнуть/обогатить/…) её так, как заблагорассудится, перед тем, как разместить в горячем хранилище.
Watch срабатывает, когда данные из oplog доезжают по сети от primary ноды до приложения. В обычном режиме, если у вас нет инфраструктурных проблем, лаг ± соответствует задержке вашей сети. Но он может увеличиваться по ряду причин.
Без watch нам не хватало ресурсов трёх нод по 8cpu на каждой, чтобы выдержать обычную нагрузку, т.е. 24cpu. С watch 15 подов в среднем потребляют по 20% cpu, т.е. 3cpu. Получается, что сократили как минимум в 8 раз.
А вот это прекрасно!
потому что, как с ботом поговорил
А что вы знаете о курсорах mongodb? Известно ли вам, что даже базовый find реализован с помощью курсора?
Который из коннекторов и какое это имеет отношение к статье?
Как с Марусей поговорил)
https://github.com/ivakhin/user/blob/simple-implementation/repo-mongo-watch.go
Только нужно ещё подумать, как обеспечить консистентность данных после разрыва соединения с mongodb.
Не понял, причём тут built-in map. Я map привёл в качестве примера к двум предыдущим предложениям: "С Watch вы не получаете полноценную реплику данных. Её функциональность будет ограничена той структурой, которую вы выберете для хранения данных."
Если честно, ничего не понял) Какие ведьмы? Что шардинг накручивать будет? Что там ваш монолит молотит на условном сервере? При чём тут связка redis/watch. Но за интерес к статье спасибо!
Очень интересный вопрос. Постарался найти ответ на него в документации, но пока не получилось.
В целом мы и не пытались разместить большие объёмы данных в RAM, я писал об этом:
"семь из восьми сущностей — это справочные данные, а полный размер их коллекций не превышает нескольких мегабайт".
Если есть потребность заиметь горячую сотню другую гигабайт данных, то нужно быть готовым решать не тривиальные технические задачи, взвешивать решения и, возможно, идти на компромиссы, потому что серебряной пули не существует. Я думаю, кейс с большим объёмом данных в RAM - хорошая тема для другой статьи.
Если говорить о запросах, которые генерирует аудитория сайта, и которые создают основную нагрузку, то это максимально простые выборки по первичному ключу.
Есть и сложные запросы с различными вариантами сортировок, которые генерируют менеджеры и внутренние системы-потребители. Это капля в море с точки зрения нагрузки. Но их мы уже, как правило, выполняем средствами mongodb. А сложной иерархии, агрегаций или джойнов средствами БД мы избегаем.
«Ненужные вычисления» - это доли процента по сравнению с сетевыми i/o.
Watch в mongodb существует с версии 4.4. Во всех последующих релизах вплоть до текущего стабильного 7.0 обратная совместимость не ломалась.
Ха! А я наоборот реализацию усложнил, чтобы обработать различные отказы.
В ближайшее время постараюсь написать вариант реализации попроще.
На самом деле подход довольно привычный. Это частный случай event driven архитектуры. Из непривычного здесь только то, что в роли агента (источника события) выступает не приложение, а СУБД, оно же служит и транспортом. То что Watch основан на внутреннем механизме репликации БД вообще восхитительно. Вы гарантировано получаете правильную последовательность событий.
А много - это сколько?
Не работал с atlas, но было бы интересно узнать, о каких сценариях масштабирования идёт речь, и о причинах, по которым change stream cursor перестаёт получать апдейты и при этом не возвращает ошибку.
Я могу ошибаться, но этому кейсу вроде бы вся статья посвящена: как с помощью watch запилить in-memory хранилище, избавиться от запросов в бд, и какой профит можно от этого получить. 30k rps на ресурсах одного ядра, имхо, убедительный профит.
В сообщении watch приходит модель БД. Никто не запрещает обработать(конвертнуть/обогатить/…) её так, как заблагорассудится, перед тем, как разместить в горячем хранилище.
Я писал, что с помощью cpulimit выставил для приложения лимит в 100%. Другими словами, ресурсов одного ядра достаточно.
Завезли его ещё в один сервис, который сейчас на финишном этапе разработки.
Пожалуй, да. Хотя за последний год многие команды выбрали монгу в качестве основной СУБД для своих новых проектов.
Постараюсь в обозримом будущем поделиться ещё чем-нибудь интересным.
Watch срабатывает, когда данные из oplog доезжают по сети от primary ноды до приложения. В обычном режиме, если у вас нет инфраструктурных проблем, лаг ± соответствует задержке вашей сети. Но он может увеличиваться по ряду причин.
Без watch нам не хватало ресурсов трёх нод по 8cpu на каждой, чтобы выдержать обычную нагрузку, т.е. 24cpu. С watch 15 подов в среднем потребляют по 20% cpu, т.е. 3cpu. Получается, что сократили как минимум в 8 раз.
По крайней мере регион у mnp останется прежним.