Задавайте вопросы, мы ответим
Вы не зашли.
Приветствую, Коллеги,
поделитесь пожалуйста идеями по сабжу.
Постановка задачи:
Есть таблица, содержащая данные для закладочного сервиса.
Таблица содержит древесные структуры в виде "Cписок соседства" (то есть каждая строка содержит ссылку parent_id на отцовский элемент, находящийся в этой же таблице, у корней parent_id равен null). Глубина дерева - максимум пять элементов, среднее дерево содержит не больше 50 элементов.
В архитектуру базы нужно заложить возможность горизонтального шардинга (эта таблица самая большая в системе), то есть разбить эту таблицу на несколько БД-серверов.
То есть если одного сервера начинает не хватать, чтобы можно было поставить еще один. Если потребуется - еще один. и. т. д.
И вот тут возникают вопросы.
1) По какому критерию можно было бы лучше всего организовать разбиение по шардам?
Сами элементы закладочного сервиса ссылаются на пользователя, который владелец закладки,
иногда содержат в себе ссылки, имеют название и описание, имеют время создания/модификации. Единственное хорошее, что приходит в голову - шардировать по времени.
2) Как добиться уникальности ключа в условиях распределенной БД?
Рассматриваю пока следующие варианты:
1) Решение в виде разбить диапазон значений на поддиапазоны и назначить каждый шард отвечать за свой диапазон (допустим по миллиону или по 10 миллионов на каждый шард). То есть в этом случае шард определяется просто порядковым номером ID.
2) Решение от Instagram.
Выглядит очень изящно, но непонятно - в какой шард, допустим, вставлять следующее дерево сервиса.
Как-то так. У кого есть идеи или наработки грамотной реализации - поделитесь плиз.
Неактивен
1. Шардировать, видимо, лучше всего по пользователю. Тогда и ID распределенные не нужны будут.
2. Если шардировать другим способом, то тебе всё равно не нужно сохранение временно́й последова-
тельности в id, поэтому можно придумать какое-то простое решение типа <shard_id>:<autoinc на шарде>.
Неактивен
paulus, спасибо за ответ.
1) Имеется в виду, что деревья, принадлежащие первой, допустим, тысяче пользователей кладутся на первый сервер, потом, если сервер начинает "загибаться" - начинаем класть деревья, принадлежащие второй тысяче пользователей (порядковый номер пользователя определяется через автоинкрементный ID) на второй шард, и так далее, пока не кончатся деньги на новые шарды ?
Неактивен
Пусть uid - номер пользователя. N - число серверов в конфигурации. Вычисляем остаток от деления uid на N. m = uid%N. m - номер сервера, на котором нужно хранить все деревья данного пользователя.
Неактивен
Мм, давай вот для примера...
Начинаем, конечно, с одного сервера.
Образовалась у нас, допустим, тысяча юзеров, каждый хранит свои деревья, в какой-то момент сервер перестаёт справляться, на уровне софта все отлажено, упираемся в железо.
Ставим второй сервер, то есть N становится равно двум.
Пришёл юзер №1001, пользуемся формулой, получаем 1001%2=1, то есть опять пишем данные на первый и так уже перегруженный сервер. Юзер №1002 попадёт куда надо, но 1003 - опять на первый. То есть у нас равномерно будет повышаться нагрузка на два сервера при том, что первый уже перегружен, а второй - пустой почти.
Или нужно после добавления каждого нового сервера сделать перераспределение записей по ним (то есть перекинуть 500 записей с первого сервера на второй)?
Неактивен
Тут возможны варианты.
1. Действительно так, как ты описал, но это сложно для перешардирования.
2. Вариант с делением пополам. Софт знает «список шардов», при этом шарды
нумеруются хитрым образом:
а. один шард — номер 1.
б. два шарда — 11 и 12 (при этом они получаются делением шарда 1 пополам).
в. три шарда — 11, 121 и 122 (вторые получились делением 12 пополам).
по списку номеров шардов видна история деления и всегда очевидно, куда
попадает пользователь хэшированием.
3. Метабаза. Делим пользователей сразу на много шардов (i.e. 1024), при этом
записываем в метабазе (или конфиге), на какой физической машинке живут
шарды. В самом начале все шарды живут на одной машинке, потом часть из них
увозится в сторону. Для простоты можно в этом случае хранить их в разных
логических БД в пределах одной СУБД.
Неактивен
Ага, проясняется.
Автоматически возникают еще два вопроса:
а) Как в этом случае хранить те данные, которые по своей сущности ссылаются на наши искомые элементы деревьев?
Например, если появилась потребность завести таблицу комментариев к ссылкам (ссылки - это элементы дерева), то как будут размещаться таблицы (или таблица) с ссылками в обоих вариантах шардирования?
б) Вопрос больше относится к варианту с метабазой (где мы заводим 1024 базы, а потом по необходимости увозим часть на другой шард). Получается, что по сути вместо одной большой таблицы мы имеем 1024 маленьких.
Как в этом случае осуществлять работу с таблицами, если требуется осуществить тот же самый поиск не по юзеру, а глобально? Например, если хотим найти ссылку с таким-то текстом внутри. Будем подряд перебирать 1024 таблички? Или есть какие-то механизмы?
Неактивен
а) ты в любом случае будешь эти таблицы шардировать, а шарды у тебя уже есть...
в чем проблема? )
б) шардирование и глобальное — это всегда противоположные вещи. как правило,
ты не хочешь глобального, когда у тебя есть шардирование
Если тебя интересует конкретно «поиск по всем пользователям» — смотри в сторону
независимого индекса. sphinx / lucene / etc. Можно бегать и по всем шардам, но это
будет, разумеется, огромный overhead.
Неактивен