Pull to refresh

Comments 35

Т.е. у Вас репликация shard серверов отсутствует?
Да, пока в этом нет необходимости. Хотя с такой организацией ее не сложно внедрить.
Лучше сразу внедряйте. Например, вышло критическое обновление ОС, которое требует перезагрузки и что в этом случае делать? Останавливать все сервера на время перезагрузки? А при наличии реплик работа не остановится.
Еще вопрос.
А почему выбор пал на связку MySql + redis, а не на MongoDB например? У Mongo все это реализована на уровня ядра БД. Просто самому интересно, в одном проекте отказались от подобной связки в пользу Mongo, за счет чего повысилась отказоустойчивость и упростилась логика управления. На тестах фенсинга (отсечения) mongo проявило себя вообще великолепно, все на полном автомате.
Вообще монго так же имеет мастер, который уже определяет, на каком инстансе хранится запрашиваемый экземляр и в случае большой нагрузки ставить балансировщики на мастера все-равно придется. Еще в Yii нет такой удобной реализации интерфейса взаимодействия с Mongo, как, например, ActiveRecord для MySQL и тому подобных баз. За совет спасибо, репликация в любом случае будет прикручена на обычные таблицы. Вполне возможно, что сразу и на шард-таблицы поставим.
Спасибо за ссылку, видимо и правда хорошее решение.
Skype уже реализовал для PostgreSQL утилиты, реализующие шардинг на уровне сервера, так что, если кто-то еще в процессе выбора способа хранения данных, можете копнуть в этом направлении.
Как вы реализуете выборку массива записей из шардинг-таблиц?
Sphinx. Используем фильтры для сортировки записей и условного поиска, а так же как фулл-текст поисковик.
Т.е. добавить сервер вы в будущем не сможете?
Как решение — в том же редисе можно хранить на какой сервер положили.

Потом при добавлении — дальнейшие инсерты будут размазываться по всем серверам автоматом, а старые можно переразмазать.

Плюс чтобы меньше работы делать — можно консистентность реализовать интервалами от crc32, а не остатком от деления.
Спасибо, сэр :) Это мы и сделали. "… который теперь определяет сервер для сохранения новой записи (тот же остаток от деления UID на SERVER_QUANTITY) и сохраняет посчитанное значение в Redis,..."
Окей, в следующий раз буду читать внимательнее (в коде этого нет)(или я снова невнимательно читаю код?)

Но всё таки — подумайте таки насчёт консистентного хеширования вместо деления по модулю.
Да, это в коде есть, double fault мне :-(
На мой взгляд можно было вполне обойтись без редиса.
Задав в конфиге диапазоны хранения по PK, т.е. pk от 1000000000 до 1999999999 хранятся на шарде 1, а от 2000000000 до 2999999999, на шарде 2. Для БД реализовывается указанием начального автоинкримента. Записи добавлять через раундробин.

Еще хорошо бы предусмотреть настройку read-only, при установлении данного флажка говорим пользователю, что на данный момент не можем модифицировать данные. Будет весьма полезно для сервисного обслуживания.
Можно было бы обойтись, но ваш вариант не на столько гибок. Хотя я понимаю, что и наш вариант не претендует на место самого лучшего, так как возможностей хороших реализации очень много, а я описал лишь одну из них. Можно обойтись PostgreSQL или Mongo (которая все запросы, в т.ч. и на чтение, прогоняет через мастер), но воевать потом с настройками сервера балансировки я не умею, т.к. я не админ. Как придет время — админу тоже не поздоровится :)
остаеться вопрос как вы поступили с тем что CActiveRecord почти сразу читает схему из mysql
и простой вызов new Users делает запрос к базе, причем на этой стадии еще и не понятно какой?
и еще шардинг подразумевает ограниченное кол-во записей в шарде, но машины (сервера) все разной мощьности на одном шарде может быть уже предел нагрузки и данные подходящие под условие выбора сервера для сохранения вроде бы подходят под тот на котором уже затык, вы как то это решали?
у меня есть небольшое решение для yii но оно получилось сложно конфигурироемое.
//dbs1.Spot1.User1
$spot = array(
'1' => array(
'100',
'101',
'102',
...
),
'2' => array(
'201',
'202',
'203',
...
),
);


где сам файл конфиг определеннго шарда сервера, а 1,2 — номер базы данных, 100, 101… 201..203… номер шарда таблицы
т.е вид такой
server1.DB1.User100
но как я уже говорил сложно конфигурируемое дело.
У нас схемы присутствуют на каждом сервере. Класс CShardedActiveRecord содержит переопределенный метод getConnection, который определяет сервер для дальнейшей работы (в т.ч. для стягивания схемы). Если же это не выборка (условие не указано), а, например, new User(), то на этот случай в классе описано
 if (is_null($this->_pk)) {
            $serverName = Yii::app()->params->servers['serverNames'][0];

который берет соединение с первым из серверов.

Что касается балансировки между шардами — у нас скоро будет зарелизена задача, дающая возможность отключения сервера на вставку новых записей (соответственно, записи будут распределены по свободным). Чуть позже обновлю статью, если кому-то интересна наша реализация, хотя она достаточно простая.
в этом то и получаетсья основной затык, что если вы автризуете польщователя то выбираете его не по PK значить делаете два запоса минимум, один на схему у нулевого шарда, а другой на поиск авторизации в базе.
и тут вопрос как вы по логину\мыло + пароль опеределяете в каком шарде лежит пользователь?
у меня была схема где по мыло можно было найти шард пользователя.
В сфинксе есть поиск по точному совпадению. Составляем общий индекс со всех шардов, затем просто ищем id по введеному логину и забираем данные о пароле про findByPk() с передачей id от сфинкса.
ох. прошу прощение не внимательно прочитал. спасибо
Да, интересно. Ждем публикации.
Спасибо, интересная статья.

поиск по базе реализован при помощи Sphinx (для которого мы даже написали свой DataProvider, дабы можно было использовать интегрированные в Yii виджеты, работающие только с DataProvider)


Было бы очень интересно почитать и про эту часть Вашей работы.
Спасибо. По Sphinx как раз хотел написать отдельную статью.
Что вы планируете предпринимать при падении одного из шардов?
Что вы подразумеваете под падением? Если упала БД, то ничем особо удивительным в таких вещах не занимаются. Возможно прикрутим репликацию, или mysql прокси, для того, чтобы автоматически переключать запрос на активную копию шарда.
Спасибо. Будем ждать от вас нового релиза.
Не так понял. Оказывается, уже реализована регистрация автолоадеров. Переделаем :)
А как вы решили вопрос индексации новых записей для Sphinx. Например, если пользователь только зарегистрировался, он же не сразу в Sphinx индекс попадает, а только через определенный промежуток времени, когда произойдет индексация?
Sphinx RT-index позволяет нам иметь всегда актуальную информацию в индексе. Хотя мы периодически проводим полную переиндексацию.
А как вы выбираете часть (страницу) множества, если оно размазано по шардам? Скажем, пользователь хочет посмотреть на список юзеров (своих друзей, например) и надо вынуть из базы всех юзеров отсортированных по ИДешке или логину, а потом сделать срез LIMIT 100,100.
Постройте единый индек Sphinx или ElasticSearch по своим шардам и шлите запросы на выборку уже в поисковый движок. Он вернет id записей, которые уже не проблема выдернуть с шардов.
Sign up to leave a comment.

Articles