Не получится создать кучу реплик, так как оверхед от репликаций когда-нибудь начнет превышать пользу от разгрузки и балансировки. Точно также не получится бесконечно улучшать железо, рано или поздно будет достигнут потолок. Поэтому, при разработке очередного фейсбука, вконтакта, evaphone используется техника под названием шардинг. (оно же партицированние)
Используется как в реляционных база данных, так и для mongoDb. Фактически это разбиение одной “таблицы” на несколько разных “таблиц”. Это может работать как на одном сервере, так и на разных инстантах. На одном сервере это делается для того, чтоб быстрее работала выборка, меньше времени тратилось на перестройку индекса и т.п. Т.е была одна таблица с 5 миллиона строк, стало 2 по 2.5 миллиона. На разных серверах, чтобы увеличит bandwith, I/O, etc.
Для того, чтобы приложение понимало, куда надо идти, используется некая hash функция, например, если userId % 2 == 0, то один сервер, в противном случае другой сервер. Часто это логика находится в самом приложение, чтобы приложение понимало, куда ему идти. Для реляционных баз данных, тут есть ряд проблем - добавление нового сервера (шарда), необходимо как-то менять хеш функцию, а иногда перебалансировать данные с одного сервера, на новый. Также очевидно, что не удаться писать какие-то сложные джойны или другие SQL запросы, вся выборка должна идти по FK. Очевидно, что в случае с реляционными базами данных, далеко не каждую таблицу можно разбить на партиции. Точнее разбить можно, но поиск по разным партициям придется писать самому. Например, есть таблица с объявлениями, селект с поиском по некому слову в одной таблице вернет результат сразу. В случае партицированния, придется отправить несколько запросов на разные сервера, а потом сложить результат. Хорошо для шардинга в реляционных базах данных подходят “изолированные” данные. Например, каждый пользователь, сохраняет что-то там у себя, и никому не интересно, что именно.
Предположим, что есть таблица, в которую пишутся пользовательские логи, в конце каждого месяца необходимо составлять отчет по этим логам. Таблица растет очень быстро и имеет миллионы, а то и миллиарды данных. Работа с такой таблицей сильно грузит базу, учитывая то, что нам нужны данные только за последний месяц, можно партицировать (разбить таблицу) на 2 части. Текущая (текущий месяц), всё остальное. Запись будет идти только в текущую таблицу, отчеты строятся тоже только по ней. А остальные данные хранятся для истории в другой таблицы. Многие базы данных предоставляют встроенные механизмы для партицированная. Писать код, который переносит данные не придется.
Шардинг в mongoDb
MongoDb лишен ограничений, которые есть у реляционных баз данных при использовании шардинга. MongoDb можно перенастроить таким образом, чтобы она автоматически использовала балансировку нагрузку с шардингом, при этом изменений в коде приложения не будет вообще или они будут минимальны.
MongoDb, настроенный для шардинга, может состоять из несколько реплик mongod процесса (сама база), несколько независимых между собой mongos процессов, и реплики config серверов. Код приложения обращается к одному из mongos процессу (их может быть сколько угодно, т.к у них нет ничего общего). Mongos процесс обращается к config серверу, чтоб определить, на какую шарду или к каким шардам ему идти за данными. На config сервере хранится диапазон ключей -> значений. Где диапазон ключей - это, например A-M, т.е первые буквы имен пользователей, а значение название шарды.
A-M -> shard1
N-U -> shard2
F-Z -> shard3
Mongos понимает к какой ноде ему идти, и обращается напрямую, возвращая данные клиенту. Обращения могут затрагивать как одну ноду (обращение по ключу для шардинга), так и несколько (обращение не по ключу или получение списка. Если заданы параметры сортировку, то mongos получает данные от нескольких нод, и сортирует данные у себя перед тем как отдать клиенту.
Все сущности mongos, mongod, config сервер могут быть запущены на разных серверах.
Выбор ключа для шардинга.
Необходимо выбрать ключ таким образом, чтобы данные можно было б легко равномерно распределить. Например, для пользователей - это может быть диапазон имен. С другой стороны, если придет много пользователей с одинаковыми именами, то на одной из шард сосредоточиться больше данных. Однако, это не характерно для имен пользователей.
Вся данные делятся на чанки (chunk), когда чанк достигает размера 64 мб, он делится на 2 по 32. Чанк - это набор смежных данных. Когда размер шарда превысит допустимый, чанки будут перемещены на другую шарду.
Используется как в реляционных база данных, так и для mongoDb. Фактически это разбиение одной “таблицы” на несколько разных “таблиц”. Это может работать как на одном сервере, так и на разных инстантах. На одном сервере это делается для того, чтоб быстрее работала выборка, меньше времени тратилось на перестройку индекса и т.п. Т.е была одна таблица с 5 миллиона строк, стало 2 по 2.5 миллиона. На разных серверах, чтобы увеличит bandwith, I/O, etc.
Для того, чтобы приложение понимало, куда надо идти, используется некая hash функция, например, если userId % 2 == 0, то один сервер, в противном случае другой сервер. Часто это логика находится в самом приложение, чтобы приложение понимало, куда ему идти. Для реляционных баз данных, тут есть ряд проблем - добавление нового сервера (шарда), необходимо как-то менять хеш функцию, а иногда перебалансировать данные с одного сервера, на новый. Также очевидно, что не удаться писать какие-то сложные джойны или другие SQL запросы, вся выборка должна идти по FK. Очевидно, что в случае с реляционными базами данных, далеко не каждую таблицу можно разбить на партиции. Точнее разбить можно, но поиск по разным партициям придется писать самому. Например, есть таблица с объявлениями, селект с поиском по некому слову в одной таблице вернет результат сразу. В случае партицированния, придется отправить несколько запросов на разные сервера, а потом сложить результат. Хорошо для шардинга в реляционных базах данных подходят “изолированные” данные. Например, каждый пользователь, сохраняет что-то там у себя, и никому не интересно, что именно.
Предположим, что есть таблица, в которую пишутся пользовательские логи, в конце каждого месяца необходимо составлять отчет по этим логам. Таблица растет очень быстро и имеет миллионы, а то и миллиарды данных. Работа с такой таблицей сильно грузит базу, учитывая то, что нам нужны данные только за последний месяц, можно партицировать (разбить таблицу) на 2 части. Текущая (текущий месяц), всё остальное. Запись будет идти только в текущую таблицу, отчеты строятся тоже только по ней. А остальные данные хранятся для истории в другой таблицы. Многие базы данных предоставляют встроенные механизмы для партицированная. Писать код, который переносит данные не придется.
Шардинг в mongoDb
MongoDb лишен ограничений, которые есть у реляционных баз данных при использовании шардинга. MongoDb можно перенастроить таким образом, чтобы она автоматически использовала балансировку нагрузку с шардингом, при этом изменений в коде приложения не будет вообще или они будут минимальны.
MongoDb, настроенный для шардинга, может состоять из несколько реплик mongod процесса (сама база), несколько независимых между собой mongos процессов, и реплики config серверов. Код приложения обращается к одному из mongos процессу (их может быть сколько угодно, т.к у них нет ничего общего). Mongos процесс обращается к config серверу, чтоб определить, на какую шарду или к каким шардам ему идти за данными. На config сервере хранится диапазон ключей -> значений. Где диапазон ключей - это, например A-M, т.е первые буквы имен пользователей, а значение название шарды.
A-M -> shard1
N-U -> shard2
F-Z -> shard3
Mongos понимает к какой ноде ему идти, и обращается напрямую, возвращая данные клиенту. Обращения могут затрагивать как одну ноду (обращение по ключу для шардинга), так и несколько (обращение не по ключу или получение списка. Если заданы параметры сортировку, то mongos получает данные от нескольких нод, и сортирует данные у себя перед тем как отдать клиенту.
Все сущности mongos, mongod, config сервер могут быть запущены на разных серверах.
Выбор ключа для шардинга.
Необходимо выбрать ключ таким образом, чтобы данные можно было б легко равномерно распределить. Например, для пользователей - это может быть диапазон имен. С другой стороны, если придет много пользователей с одинаковыми именами, то на одной из шард сосредоточиться больше данных. Однако, это не характерно для имен пользователей.
Вся данные делятся на чанки (chunk), когда чанк достигает размера 64 мб, он делится на 2 по 32. Чанк - это набор смежных данных. Когда размер шарда превысит допустимый, чанки будут перемещены на другую шарду.
Комментариев нет:
Отправить комментарий