Как справиться с множественными подключениями к БД

1. Дмитрий (23.10.2011 / 09:26)
Нужен совет.

Работаю над проектом наподобие Твиттера. Программная часть почти готова, и 1 ноября я собирался запустить его в работу, но решил повременить с этим, т.к. думаю перекроить архитектуру БД, и разнести все основные сервисы по отдельным базам. То есть чтобы на каждый сервис (профили юзеров, фотоаватары юзеров, блоги юзеров, форумы юзеров, чаты юзеров, конференции юзеров) была своя база данных.

Ни разу не пробовал реализовать это, вот советуюсь, как правильно это сделать. Все БД по идее будут располагаться на разных серверах, а пока денег нет на это - все будет на одном сервере. Насколько трудно для одного сервера будет, если на одной странице будет подключаться сразу 5-6 баз данных? Возможно, какие-то мануалы на русском языке почитать, или видео посмотреть какого-то умного докладчика...

Заранее хочу уточнить, что данные я кеширую в мемкеш на очень длительный срок, и запросы на чтение (SELECT) производятся крайне редко. Нагрузка происходит только при записи/перезаписи данных. Меня интересует проблемность единовременного множественного подключения и, желательно, снижение нагрузки с записи/перезаписи посредством очередей запросов.

Проект должен быть по дефолту крайне высоконагруженным. Работаю над подобным первый раз, поэтому по голове сильно не бейте.

Разносить БД на несколько суб-БД я, наверное, буду в любом случае, ибо считаю, что если, к примеру, в данный момент, происходит большая нагрузка на сервис блогов (очень много пишут и голосуют), и БД этого сервиса дошла до критической нагрузки, я искусственно притормаживаю этот сервис "Мы перегружены, подождите пару минут", а все остальные сервисы, БД которых чувствуют себя нормально, должны функционировать в обычном режиме.

Это для того, чтобы если вдруг один сервис перегружен, сайт продолжал работать и без него, а не отдавал полностью 404. Возможно, я ошибаюсь.

К тому же, даже если ставить лимит запросов на сервере 200 тыс/мин, для шести сервисов, это очень и очень мало, даже с учетом горизонтальной масштабируемости (не более 1 млн записей в каждой таблице). А так выходит, по 200 тыс запросов в минуту на каждый из 6 сервисов, что в 6 раз снижает нагрузку.

Это сугубо мое мнение. Я просто высказал свое видение реализации этого проекта. Еще раз повторяюсь, я в этом ***юга. Поправьте меня.

2. KOZZ (23.10.2011 / 12:31)
дим,до конца не дочитал,но с самого начала возник вопрос:ЗАЧЕМ?
Делай таблицы с префиксами,и всё.
dimalondon_fotoalbum_files
dimalondon_fotoalbum_settings
dimalondon_fotoalbum_something
dimalondon_posts_list
dimalondon_posts_comment
итд итп
если это ради снижения нагрузки,то имхо создание нескольких подключений куда более ресурсоёмко.

3. Дмитрий (23.10.2011 / 12:52)
2. eGo Ржавчина в Зубах, если бы ты дочитал до конца 1 пост, там внизу написано, зачем. Меня больше интересует техническая часть, как правильно сделать это.

По сути, у меня, к примеру, в страницу/шаблон личной страницы аяксом вытягиваются данные из разных точек. В блок блога подтягивается кеш блога (соответственно, там же и будет соединение с БД блогов), в блок фотоаватара вытягиваются данные о фотках (там же и будет соединение с БД фотографий), и так далее по списку. Всего на этой странице выбираются данные от 4 модулей. Соответственно, будет 4 соединения. Вот вопрос, разумно ли...

4. ктулху (23.10.2011 / 13:17)
А ещё попробуй спланировать что у каждого "сервиса" будет не одна БД, а несколько.
Хотя помоему тут уже изначально неправильный подход.
Надо что-бы скрипт сам изначально знал что записи с 1 до 10000 лежат на первом сервере, с 10001 по 20000 на втором и т.д.
И уже обращался к нужным (этакий шардинг). Только продумывать это всё надо хитро

5. KOZZ (23.10.2011 / 13:20)
4,вот это более грамотно klass

6. Дмитрий (23.10.2011 / 13:22)
4. ShiftBHT, дык, я же говорил, что думаю разбивать таблицы по 1 миллиону записей на каждый сервер. Я не делал этого пока, потому что пока не припекло (до первого миллиона пока далеко, до полумиллиона тоже, это можно сделать позже, в процесе). А вот разбивать БД на несколько Суб-БД в процессе работы уже намного сложнее, поэтому спроектировать это надо заранее.

7. Алексей (23.10.2011 / 13:23)
4. ShiftBHT, "скрипт" может и не знать что записи с 1 по 100000 лежат на первом сервере другие на втором и так далее, достаточно создать избыточность данных, но помоему серавно подход изначально какойто не правильный

8. KOZZ (23.10.2011 / 13:36)
7,так скрипт надо научить узнавать.

9. Алексей (23.10.2011 / 13:43)
8. eGo Ржавчина в Зубах, с избыточностью данных на серверах ты хоть лишаешся проблемы если первый сервер не доступен и например на нем первый миллион записей, то мы его уже не получим а так может запросить со второго сервера немного увеличив нагрузку

10. Дмитрий (23.10.2011 / 13:48)
9. МегабиТ, недоступность определенных серверов решает репликация. Если недоступен какой-либо из серверов, в замен его обязан вступить в работу реплицирующий его сервер.

11. ктулху (23.10.2011 / 13:49)
Да, но... больше записей на серверах (если например на первом сервере хранить второй миллион в качестве избыточности) обязывают использовать больше кэша под БД.

9. Как вообще реализуется шардинг на уровне серверов? Я как понимаю есть какой-то прозрачный механизм для этого

Добавлено через 01:28 сек.
10, тут всё сложнее чем ты думаешь...
Если он будет только на чтение, то проблем особых нет, а если он ещё и запросы на запись будет принимать, то возникнет рассинхронизация.
А связка master-master (взаимная синхронизация) не очень хорошо работает...

12. Алексей (23.10.2011 / 13:51)
10. dima.london, а избыточность данных на серверах != реплекациям на серверах разве? и что мешает также брать данные с n по M на одном сервере (main), а с M по X брать с (slave) на который происходит репликация?

Добавлено через 02:44 сек.
php и mysql вобще под high-load не катят

13. Дмитрий (23.10.2011 / 13:56)
11. ShiftBHT, я считаю, что при записи первого сообщения юзера, ID этого сообщения надо запоминать. Кроме того надо хранить в памяти ID последнего сообщения юзера. И от него отталкиваться при выборке всех его сообщений.

К примеру,
- первый ID=1250004 - значит выбор надо начинать со второго сервера (1250004/1млн = 1,25 что значит второй сервер)

- последний ID=2275404 - значит выбор надо заканчивать на третьем сервере (2275404/1млн = 2,27 что значит третий сервер)

Исходя их этого, данные надо выбирать из 2 и 3 сервера.

как-то так

14. Алексей (23.10.2011 / 13:57)
13. dima.london, постоянно пересчитывать записи?

15. Дмитрий (23.10.2011 / 14:02)
14. МегабиТ, почему? Только при выборе данных из БД. К примеру, срок кеша закончился, и его надо перекешировать. Я вынимаю из определенного места памяти IDы первого и последнего сообщения, подсчитываю, с какого по какой серверы хранятся данные, и выбираю. Чтобы не дергать ненужные сервера. К примеру, серверов 10, а после подсчета получается, что данные хранятся с 3 по 7 сервера. Вот из этих 5 и делать выборку и формировать кеш из массива полученных данных.
Все просто.

16. Алексей (23.10.2011 / 14:04)
15. dima.london, мне кажется что в реальных условиях твое решения окажется либо не эффективным либо не работо способным вобще

17. Дмитрий (23.10.2011 / 14:11)
16. МегабиТ, а как те еще предлагаешь? При каждом перекешировании перебирать все сервера? Посмотри на фейсбук. У них 4 датацентра. Это рехнуться можно, пока выберешь данные со всех серверов.
Ну, максимум - это можно у каждого юзера хранить массив серверов (типа 1, 2, 5, 17, 24), и при записи нового сообщения узнавать, в какой сервер пишется сообщение и перебирать массив серверов. Если сервер в массиве не найден - дописывать его туда. А при выборе сообщений просто перебирать этот массив и брать данные из тех серверов, что записаны в массив. Хз.

18. Алексей (23.10.2011 / 14:11)
15. dima.london, http://habrahabr.ru/blogs/mysql/130999/

19. Дмитрий (23.10.2011 / 14:14)
18. МегабиТ, гг Я на ютьюбе сегодня смотрел доклад этого Зайцева. Ущербный тип. Много воды льет не по делу.

20. Алексей (23.10.2011 / 14:20)
17. dima.london, над таким вопросом нужно посидеть не день и не неделю, попробывать не один вариант, для себя как реализацию я вижу примерно такую, перенсти часть нагрузки на клиента, негенерировать никаких страниц вобще на сервере а только массивы данных, статику вынести на отдельный сервер, часть данных(до состояния изменения) хранить у пользователя в Storage(HTML5 DOM Storage или SQLLite), только придется отказаться от старых браузеров IE < 9, ну и собрать всю страницу у клиента по кускам

21. Дмитрий (23.10.2011 / 14:24)
в итоге это все не по делу. В данный момент меня больше интересуют множественные коннекты к различным БД и варианты организации очередей запросов.

1) Насколько оправданно подключаться одновременно к нескольком БД.

2) Как поступить в том случае, когда одна из БД загибается и нужно притормозить ее работу? Я думаю писать определенный лог очереди запросов и когда загибающаяся БД раздуплится, выполнять в первыю очередь запросы, записанные в очередь, но с уже нужной мне скоростью (максимально приемлемой). Все новые запросы, поступающие в этот момент дописывать в конец очереди. Когда вся очередь выполнена - выполнять запросы напрямую в БД.

Как это реализовать? Куда писать лог (журнал) очереди? В отдельную БД?

22. Алексей (23.10.2011 / 14:26)
19. dima.london, из коментов на хабре

http://www.amazon.com/gp/aw/d/0596101716/ref=redir_mdp_mobile (High Performance MySQL: Optimization, Backups, Replication, and More (Paperback))
http://www.mysqlperformanceblog.com/ MySQL Performance Blog

Добавлено через 01:09 сек.
21. dima.london, не задумывался о смени яп серверной части?) треды в php это слишком

23. Дмитрий (23.10.2011 / 14:28)
не знаю я буржуйского языка... cry

Добавлено через 00:49 сек.
МегабиТ (23 Октября 2011 / 13:26)
21. dima.london, не задумывался о смени яп серверной части?) треды в php это слишком
Задумавылся. Но только в отдельных компонентах приложения.

24. Андрей (24.10.2011 / 00:01)
Я не знаю ни PHP ни MySQL=)
Но идея такова:
Имеем например 5млн записей и 7 БД, а лучше серверов.
Далее эти записи расскидываем по БД. Т.е. просто делим.
Далее, если пользователю нужны будут старые записи то отдаем их подгружая. Если сервер с начальными данными недоступен выдаем уведомление, надеясь что он не обидится=)

25. Дмитрий (24.10.2011 / 12:59)
Если сервер с начальными данными недоступен выдаем уведомление, надеясь что он не обидится=)
Это решается репликацией.

З.Ы. Все же, как на счет очередей запросов? Есть какие-то готовые проверенные способы, или в каждом отдельном случае надо городить свой забор? У меня есть пару идей на примете, но для этого нужен как минимум доп-сервер, выступающий в роли журнала очереди.

26. ктулху (24.10.2011 / 13:38)
> надеясь что он не обидится=)

зачем тогда кластер? D просто при перегрузке серверов выдаём табличку с "техработами" и надеемся что он не обидится D

27. Алексей (24.10.2011 / 14:23)
25. dima.london, cколько там тебе серверов то уже нужно? 8-10?

URL: https://visavi.net/topics/25896