Распределение SQL-запросов между серверами в кластере
В web-проектах с большой посещаемостью рано или поздно возникает ситуация, когда мощности одного сервера недостаточно для обработки запросов. В этом случае создается кластер. И перед программистом встает вопрос: как корректно направлять разные запросы на разные серверы? На писать же везде условия. Да и передавать разные линки в mysql_query() не очень-то удобно. Именно поэтому я предлагаю простое решение этой проблемы.
В данном случае мы рассматриваем случай, когда кластер построен следующим образом: есть центральный master-сервер, на который идут запросы на запись, и есть slave-серверы, на которые происходит репликация с мастера и которые предназначены только для чтения.
-
-
-
function smart_sql_query($sql) {
-
-
$sql_cnt++;
-
} // запрос на чтение
-
else {
-
} // запрос на запись
-
} // smart_sql_query
-
-
$sql_cnt = 0;
-
-
$dbi = mysql_connect(db_host, db_user, db_pass, true) or die('ERROR: Sorry, master database is down.');
-
-
$dbi_slave = mysql_connect(db_host_slave, db_user_slave, db_pass_slave, true) or die('ERROR: Sorry, slave database is down.');
В коде же просто вызываем smart_sql_query(), который уже сам решит, куда слать запрос.
Понятное дело, что smart_sql_query() можно модифицировать таким образом, чтобы она разруливала запросы более сложным образом, показывала debug output и т.д.
Только хочу сразу предостеречь всех от наступания на те грабли, которые в свое время больно били меня. При такой схеме функцию mysql_insert_id() надо использовать крайне осторожно, так как если забыть передать ей линк, она вернет неверные данные.


March 23rd, 2007 at 12:49 Quote
ябы еще preg_match("/^SELECT/si", $sql) заменил на strposi($sql, 'SELECT')!==false :-)
March 23rd, 2007 at 13:49 Quote
1) stripos ;)
2) а ежели например в update-запросе будет фигурировать поле под названием select (или, например, selection)? это же не только ключевое слово...
March 23rd, 2007 at 13:57 Quote
1) ну естественно ;)
2) но там всеравнов начале строки проверяется, такчто это относится только к указанному случаю ;-)
March 23rd, 2007 at 14:00 Quote
а если придерживаться написания ключевых слов в SQL запросах в верхнем регистре, то букву i от strpos можно убрать, но эт уже совсем рискованно ;-)
March 23rd, 2007 at 14:03 Quote
d1pr3d @ 23.03.2007, 13:57 #
в смысле? проверяется просто вхождение подстроки в строку. а в данном случае необходимо, чтобы это слово было именно в самом начале строки и никак иначе. тогда уж надо проверять
stripos($sql, 'SELECT') === 0да, и еще. stripos - это только PHP5.
March 23rd, 2007 at 14:08 Quote
да, с нулём лоханулся, *раздолбай*, изначально написал правильно, вобщем обычно :))
stripos это только PHP5, и в этом для меня нет ничего плохого, я не сторонник писать код с уклоном на старые версии, если только не предусматривается хостится на устаревших серверах. Лучше с админом договориться :) Хотя сам использовал бы именно strpos, i добавил только дабы больше соответствовать регулярному выражению в примере.
March 23rd, 2007 at 15:03 Quote
}}#
define('db_host_slave', 'slave_host'); // скорее всего, это будет localhost
Вот это как раз таки неправильно! Если не хватает производительности первым делом надо разносить сервер приложений и БД по разным машинам!
А вообще самым первым делом внимательно изучить запросы, построить индексы, использовать для выполнения запросов prepared statement
Откровенно говоря за весь свой стаж DB-кластера использовал только failover а вот сервера приложений через NLB гоняли...
March 23rd, 2007 at 15:17 Quote
ну вот недавно делали большой проект, который давал серьезную нагрузку на mySQL. сейчас это все уже работает. стоит один master-сервер для DB и две ноды, на которых стоят slave-DB и web и между которыми балансируется нагрузка. при такой схеме при росте нагрузки легко и просто можно добавлять еще ноды, тем самым повышая производительность всего кластера.
March 23rd, 2007 at 19:50 Quote
А с самой БД "поиграть" не пробовали? В смысле оптимизации запросов и.т.п.
March 23rd, 2007 at 23:25 Quote
dimzon541 @ 23.03.2007, 19:50 #
пробовали. но планируется действительно большая нагрузка. серверы там тоже совсем не простые :)
May 24th, 2007 at 18:01 Quote
Мммм... Я, наверное, не так понял...
Если в одну базу идет запись/апдейт и пр., а из другой идет только чтение, то между этими базами должна быть какая-то синхронизация, так?
Если так, то как такое сделать-то? Если нет, то, м... откуда возьмутся данные в базе, из которой идет чтение, если вся запись идет в другую базу? о.О
В общем, как мне кажется, должна быть синхронизация, тогда, опять же, как такое сотворить? :-)
May 24th, 2007 at 18:02 Quote
Мдя, пора подвязывать кодить сутками :/ Уже в нике ошибку делаю :/
May 25th, 2007 at 06:45 Quote
Cosair @ 24.05.2007, 18:01 #
Конечно должна быть синхронизация. На это это и кластер.
В статье написано:
Filosoff @ 25.05.2007, 06:45 #
Другими словами, синхронизация (точнее - репликация) делается средствами, например, mySQL.
May 25th, 2007 at 13:56 Quote
2Filosoff, мм, то бишь просто какой-то отдельный скрипт, запущенный кроном, который копирует данные из одной базы в другую? ;-)
May 25th, 2007 at 14:01 Quote
Corsair @ 25.05.2007, 13:56 #
нет, что ты. все real time. я же говорю, средствами mySQL :)
May 25th, 2007 at 17:21 Quote
Filosoff @ 25.05.2007, 14:01 #
Тогда я вообще ничерта не понимаю, наверное рановато мне еще :))
May 25th, 2007 at 17:28 Quote
Corsair @ 25.05.2007, 17:21 #
http://www.onlamp.com/pub/a/onlamp/2005/06/16/MySQLian.html
December 4th, 2007 at 11:42 Quote
Спасибо! ;-)
Давно сюда не заглядывал, но т.к. нужно готовиться к XSSу (еще нужно и почитать с чего его едят и все такое) вспомнил про эту статью, double thank you за последнюю ссылку)