Комментарии 38
Александр, спасибо за статью. Хотелось бы кое-что прояснить для себя:
1. Не беспокоитесь ли вы, что с ростом количества клиентов у вас будут проблемы с администрированием N баз данных?
2. Как вы шерите общие справочники, актуальные одновременно для всех тенантов?
3. Что такое «монолитные сервисы» и чем они отличаются от микросервисов в вашей интерпретации?
4. Вам не мешает жесткая привязка тенанта к потоку при выполнении асинхронного метода контроллера для http-запроса? Ведь при выполнении асинхронной операции неизвестно в каком потоке будет выполнен continuation после await.
1. Не беспокоитесь ли вы, что с ростом количества клиентов у вас будут проблемы с администрированием N баз данных?
2. Как вы шерите общие справочники, актуальные одновременно для всех тенантов?
3. Что такое «монолитные сервисы» и чем они отличаются от микросервисов в вашей интерпретации?
4. Вам не мешает жесткая привязка тенанта к потоку при выполнении асинхронного метода контроллера для http-запроса? Ведь при выполнении асинхронной операции неизвестно в каком потоке будет выполнен continuation после await.
+3
1. На один облачный стенд у нас приходится около 80 тенантов (80 БД). Таких стендов несколько. Есть еще выделенные стенды для крупных компании, где только 1 БД. Администрировать все БД руками не реально. Поэтому все основные задачи автоматизируются скриптами и джобами (выполняются массово для всех БД) — бэкапы, обновления структуры БД. И админ не один — несколько.
Думаю, таким способом можно администрировать и несколько тысяч БД, если все массовые задачи автоматизировать.
Думаю, таким способом можно администрировать и несколько тысяч БД, если все массовые задачи автоматизировать.
+1
При переводе большой системы в multitennant это, конечно вполне оправданное решение. Но при всех его плюсах, также очевидны и минусы.
Вы бы стали его использовать при проектировании multitennant-системы с нуля или всё же воспользовались бы идентификатором теннанта?
Вы бы стали его использовать при проектировании multitennant-системы с нуля или всё же воспользовались бы идентификатором теннанта?
+2
У нас не было проблем, что большая система не позволяла реализовать другие схемы работы с тенантами. Мы могли в каждую колонку БД добавить идентификатор тенанта. Выбор был осмысленный. У выбранной схемы было больше плюсов. Поэтому даже сейчас для этой системы я бы сделал такой же выбор.
Минусы варианта, когда добавляем колонку «идентификатор тенанта» в каждую таблицу:
— в каждый запрос к БД нужно добавлять фильтр по тенанту
— в каждый индекс в БД нужно добавлять тенант в ключ
— есть таблицы, которые быстро растут в организациях (документы, задачи, права), если сейчас они как бы секционированы (у каждой организации своя БД с таблицами), то если данные организаций объединить запросы станут хуже по скорости (я про поисковые запросы по произвольным свойствам с учетом прав)
А еще мы действительно используем возможность перераспределения тенантов по стендам, т.е. когда данные одного тенанта переносятся на другой стенд.
Минусы варианта, когда добавляем колонку «идентификатор тенанта» в каждую таблицу:
— в каждый запрос к БД нужно добавлять фильтр по тенанту
— в каждый индекс в БД нужно добавлять тенант в ключ
— есть таблицы, которые быстро растут в организациях (документы, задачи, права), если сейчас они как бы секционированы (у каждой организации своя БД с таблицами), то если данные организаций объединить запросы станут хуже по скорости (я про поисковые запросы по произвольным свойствам с учетом прав)
А еще мы действительно используем возможность перераспределения тенантов по стендам, т.е. когда данные одного тенанта переносятся на другой стенд.
+1
2. Общие справочники мы дублируем. У каждого тенанта своя копия записей. Но таких справочников не много, место занимают мало. Это города, страны, регионы, системные роли и пользователи, журналы регистрации…
+1
3. Монолитные (в контексте нашей системы) — это сервисы, в которых большой объем кода, наверное, близко к миллиону строк. Их писали годами, у них много ответственностей (функционала). Один человек не может держать в голове детали по всему функционалу.
А микросервисы (в контексте нашей системы) — это сервисы, у которых явно выделены одна-две ответственности. Их в принципе можно переписать за неделю.
Я говорил у нас 5 монолитных сервисов, но точнее будет так: у нас один монолит (платформа) и на ее базе 5 сервисов с разным АПИ.
А микросервисы (в контексте нашей системы) — это сервисы, у которых явно выделены одна-две ответственности. Их в принципе можно переписать за неделю.
Я говорил у нас 5 монолитных сервисов, но точнее будет так: у нас один монолит (платформа) и на ее базе 5 сервисов с разным АПИ.
0
4. Да, с такой проблемой мы сталкивались. Тут все зависит от того как реализовать привязку. Вначале мы делали привязку так и в какой-то момент получили проблемы:
Потом сменили на:
private static readonly ThreadLocal<string> tenantId = new ThreadLocal<string>();
Потом сменили на:
private static readonly AsyncLocal<string> tenantId = new AsyncLocal<string>();
+1
Куча БД — не масштабируемое решение. Сейчас 80, что уже много, а представьте что будет с 1000 или 10000 клиентов.
Представьте как это дело обновлять. Добавили колонку, а скрипт который обновляет схемы БД падает на каком-то тенанте.
Всем этим зоопарком придется как-то управлять, и почти наверняка чем-то своим самописным.
А еще билинг, еще отчеты. Как сделать выборку всех заказов всех клиентов для аналитики? Все это очень усложняет управление.
Представьте как это дело обновлять. Добавили колонку, а скрипт который обновляет схемы БД падает на каком-то тенанте.
Всем этим зоопарком придется как-то управлять, и почти наверняка чем-то своим самописным.
А еще билинг, еще отчеты. Как сделать выборку всех заказов всех клиентов для аналитики? Все это очень усложняет управление.
+5
Тенанты мы объединяем в группы: 80 тенантов на стенд, размер одной БД ~5 Гб, суммарный объем баз ~400 Гб. Это значит 10000 тенантов будут разбиты на ~100 стендов.
Обновлять стенды можно последовательно. Поэтому проблему, что обновление падает на конкретном тенанте (а проблема кстати существует), будет только для конкретного стенда.
Но то что придется рулить зоопарком в 100 стендов — это конечно напряг, нужны админы.
Отчеты производительности и ошибок — это уже автоматизировано. А отчетов по данным из БД организаций мы не собираем (я не слышал чтобы собирали), это же ECM-система.
Обновлять стенды можно последовательно. Поэтому проблему, что обновление падает на конкретном тенанте (а проблема кстати существует), будет только для конкретного стенда.
Но то что придется рулить зоопарком в 100 стендов — это конечно напряг, нужны админы.
Отчеты производительности и ошибок — это уже автоматизировано. А отчетов по данным из БД организаций мы не собираем (я не слышал чтобы собирали), это же ECM-система.
0
рулить зоопарком в 100 стендов — это конечно напряг, нужны админы
Если сделать в одной большой БД — то их столько не надо. Значит если бы был владельцем, получил бы больше денег ;)
это же ECM-система
Надо же вам иметь статистику по кол-ву юзеров/документов во всех БД. Если бы я был вашим топ-менеджером, то спросил бы, на сколько мы выросли за год.
+1
Что касается статистики по количество документов-задач. Да, такая есть
0
Куча БД — не масштабируемое решение.
Если сделать в одной большой БД — то их столько не надо.
Окей. А как вы будите масштабировать одну большую БД?
+1
Реплики на чтения должны решить эту проблему, как мне сейчас видится.
Если и этого будет мало, то значит мы уже не маленькая компания на 30 человек, а значит сможем позволить себе специалистов которые подскажут-расскажут-сделают.
Вспомните что было с ОК.ру и как он тормозил. Они выросли, переписали все внутри, перенесли данные и сейчас всё у них хорошо. Мне кажется это правильным подходом.
Если и этого будет мало, то значит мы уже не маленькая компания на 30 человек, а значит сможем позволить себе специалистов которые подскажут-расскажут-сделают.
Вспомните что было с ОК.ру и как он тормозил. Они выросли, переписали все внутри, перенесли данные и сейчас всё у них хорошо. Мне кажется это правильным подходом.
0
Реплики на чтение, не решают проблему шумных соседей. Её можно решить только выносом этих клиентов на отдельные инстансы.
В место архитектуры в которой заложена запас прочности в виде выноса на отельные инстансы, вы предлагаете взять и всё переписать?
+1
запас прочности в виде выноса на отельные инстансы
Дело в том что подход с колонками tenantid — можно расширить на отдельные инстансы, путем вывода «жирных» клиентов по другим серверам.
А вот подход multyinstance множество мелких клиентов уже никак не объединить в один сервер.
Понимаете, я могу объяснить бизнесу, что клиент приносящий несколько тысяч долларов в месяц требует дополнительный сервер, но почему на каждого мелкого клиента с совокупным доходом несколько десятков долларов, мы должны поддерживать для него базу/инстанс — с трудом.
0
В место архитектуры в которой заложена запас прочности в виде выноса на отельные инстансы, вы предлагаете взять и всё переписать?
Закладывание этой прочности в архитектуру сейчас, когда там и так справляется одна машина, на мой взгляд лишнее.
Эта архитектура (СЕЙЧАС) лишь дополнительная уйма работы для DBA и DevOps. На ровном месте создали постоянные издержки для компании только из-за предположения что когда тенанты начнут сильно расти, мы легко с этим справимся.
Когда все тенанты в одной БД, то не сильно сложно склонировать схему, забить её только данными нагруженного тенанта и отправить эту отдельную БД на свою отдельную железку.
Вопрос лишь в деньгах.
+1
Не всегда архитектура предполагает возможность использовать реплики на чтение.
Шардинг как раз таки решает проблему когда один тенант больше остальных грузит инстанс БД
Шардинг как раз таки решает проблему когда один тенант больше остальных грузит инстанс БД
0
А теперь представь тысячи клиентов на одном бд сервере)
+1
У нас ~3000 тенантов и суммарно ~1млн юзеров. Все в одной БД.
Одна активная СУБД + два активных сервера приложений в пике держат до 400 запросов в секунду (в среднем 70-100).
Если бы у нас была мульти БД архитектура — я бы повешался.
Одна активная СУБД + два активных сервера приложений в пике держат до 400 запросов в секунду (в среднем 70-100).
Если бы у нас была мульти БД архитектура — я бы повешался.
+3
Когда все тенанты хранятся в одной БД возникает другая крайность — все клиенты оказывают нагрузку на одну и ту же БД.
Справедливо ли это? Когда у вас для каждого клиента своя БД, то вы можете этим управлять и выносить наиболее нагруженных клиентов на отдельные сервера.
Справедливо ли это? Когда у вас для каждого клиента своя БД, то вы можете этим управлять и выносить наиболее нагруженных клиентов на отдельные сервера.
0
все клиенты оказывают нагрузку на одну и ту же БД
Это сильно зависит от самого приложения и бизнес процессов. Если есть очень много мелких клиентов и несколько крупных, то проще — мелочь сложить в одну базу, а крупным выделить свой instance бд/сервисов/сайтов и т.д.
0
Надеюсь когда нибудь буду решать эту проблему :) Чем больше нагрузки — тем мы больше заработаем.
Если прямо завтра надо решать эту задачу, я сделаю бэкап базы, подниму новый сервер с клоном (со всем тенантами) и перенесу нагрузку на новую СУБД. Да, будет проблема назад всё это слить, но ведь нам надо бизнес делать, а не придумывать идеальные схемы :)
Если прямо завтра надо решать эту задачу, я сделаю бэкап базы, подниму новый сервер с клоном (со всем тенантами) и перенесу нагрузку на новую СУБД. Да, будет проблема назад всё это слить, но ведь нам надо бизнес делать, а не придумывать идеальные схемы :)
0
Такую нагрузку ~1млн юзеров не любое приложение потянет. Данные могут в терабайтах измеряться. А что у вас за приложение?
0
Почему в качестве конфигурации тенантов файл, а не отдельная общая бд + кеш? Это было бы проще чем распростронять файл по куче серверов
0
Гипотетически ведь можно не имя бд указывать, а весь connectionstring целиком? чтобы например еще и по разным SQL-серверам раскидывать, так?
0
100 таблиц? Насколько я помню Директум, почти всё в одной гигантской таблице лежит, с миллионом колонок.
0
Чем не понравился подход "schema per tenant"?
0
С подходом «БД на тенант» получалось проще администрирование (проще чем с «schema per tenant»). Админу проще перенести БД на другой облачный стенд (т.е. перераспределить тенанты по стендам), проще забэкапить и восстановить бэкап конкретной организации. Проще узнать объем памяти занимаемой БД. Т.е. такой единицей как БД манипулировать удобнее.
0
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Как сделать из не тенантного приложения мультитенантное