Лучшая практика для записи большого количества попаданий в базу данных MySQL - PullRequest
40 голосов
/ 17 мая 2011

Ну, это вещь. Допустим, моя будущая PHP CMS должна ежедневно привлекать 500 тыс. Посетителей, и мне нужно записывать их все в базе данных MySQL (реферер, IP-адрес, время и т. Д.). Таким образом, мне нужно вставить 300-500 строк в минуту и ​​обновить еще 50. Основная проблема заключается в том, что скрипт вызывает базу данных каждый раз, когда я хочу вставить новую строку, то есть каждый раз, когда кто-то переходит на страницу.

Мой вопрос, есть ли способ сначала локально кэшировать входящие хиты (и каково лучшее решение для этого apc, csv ...?) И периодически отправлять их, например, каждые 10 минут в базу данных? Является ли это хорошим решением и какова наилучшая практика в этой ситуации?

Ответы [ 10 ]

22 голосов
/ 17 мая 2011

500 тыс. В день, это всего 5-7 запросов в секунду. Если каждый запрос будет обрабатываться в течение 0,2 с, то у вас будет почти 0 одновременных запросов, так что вам не о чем беспокоиться.
Даже если у вас будет в 5 раз больше пользователей - все должно работать нормально.
Вы можете просто использовать INSERT DELAYED и настроить MySQL.
По поводу тюнинга: http://www.day32.com/MySQL/ - есть очень полезный скрипт (ничего не изменится, просто покажу подсказки, как оптимизировать настройки).

Вы можете использовать memcache или APC, чтобы сначала записывать туда журнал, но с помощью INSERT DELAYED MySQL будет выполнять почти ту же работу и лучше :) :) 1010 *

Не используйте файлы для этого. БД будет обслуживать блокировки гораздо лучше, чем PHP. Написание эффективных мьютексов не так тривиально, так что пусть DB (или memcache, APC) выполнят эту работу.

18 голосов
/ 17 мая 2011

Часто используемое решение:

Вы можете добавить счетчик в memcached , который вы увеличиваете при посещении, и помещать обновление в базу данных для каждых 100 (или 1000) обращений.

4 голосов
/ 17 мая 2011

Мы делаем это, сохраняя локально на каждом сервере в CSV, а затем выполняем задание с небольшим временем для отправки записей в базу данных.Это сделано для того, чтобы больше не нуждаться в высокодоступной базе данных MySQL - база данных должна без проблем справляться с этим объемом вставок.

3 голосов
/ 17 мая 2011

Сохраните их в базу данных на основе каталогов (или простой файл, зависит) где-нибудь и в определенное время, используйте код PHP для вставки / обновления их в базу данных MySQL.Ваш php-код может периодически выполняться с использованием Cron, поэтому проверьте, есть ли на вашем сервере Cron, чтобы вы могли установить расписание для этого, скажем, каждые 10 минут.* Некоторые коды были написаны в облаке и готовы для использования:)

2 голосов
/ 17 мая 2011

Ранее я также видел систему, которая записывает данные в плоский файл на локальном диске на каждом веб-сервере (будьте осторожны, чтобы делать только атомарные добавления, если используется несколько процедур), и периодически асинхронно записывайте их в базу данных, используяпроцесс демона или задание cron.

Похоже, что это преобладающее решение Optimium;Ваше веб-приложение остается доступным, если база данных аудита не работает, и пользователи не страдают от низкой производительности, если база данных работает медленно по любой причине.

Единственное, что я могу сказать, это убедиться, что у вас есть мониторинг этихсгенерированные локально файлы - сборка определенно указывает на проблему, и ваши инженеры Ops могут и не заметить.

2 голосов
/ 17 мая 2011

Если вам абсолютно НЕОБХОДИМО войти в MySQL напрямую, рассмотрите возможность использования двух баз данных.Один оптимизирован для быстрой вставки, что означает отсутствие ключей, кроме, возможно, первичного ключа auto_increment.И еще один с ключами на все, что вы будете запрашивать, оптимизированный для быстрого поиска.Временное задание будет копировать попадания из базы данных только для вставки в базу данных только для чтения на регулярной основе, и вы получите лучшее из обоих миров.Единственным недостатком является то, что ваша доступная статистика будет такой же свежей, как и предыдущий прогон «копирования».

2 голосов
/ 17 мая 2011

Один из способов - использовать Apache access.log.Вы можете получить довольно хорошее ведение журнала, используя утилиту cronolog с apache.Cronolog будет обрабатывать хранение очень большого количества строк в файлах и может поворачивать его в зависимости от дня, года и т. Д. Использование этой утилиты предотвратит ваш Apache от записи журнала.

Тогда, как сказанодругими, используйте задание на основе cron для анализа этих журналов и помещайте любые обобщенные или необработанные данные в MySQL.

Вы можете подумать об использовании выделенной базы данных (или даже сервера базы данных) для заданий с интенсивной записью., с конкретными настройками.Например, вам может не понадобиться хранилище InnoDB и хранить простой MyIsam.И вы можете даже подумать о другом хранилище базы данных (как сказал @Riccardo Galli)

0 голосов
/ 19 октября 2013

вы можете использовать стратегию очереди, используя beanstalk или IronQ

0 голосов
/ 15 июня 2011

Поскольку INSERT DELAYED поддерживается только MyISAM, это не вариант для многих пользователей.

Мы используем MySQL Proxy , чтобы отложить выполнение запросов, соответствующих определенной подписи.

Для этого потребуется собственный скрипт Lua; примеры сценариев здесь , а некоторые учебники здесь .

Сценарий реализует структуру данных Queue для хранения строк запросов и сопоставления с образцом, чтобы определить, какие запросы следует отложить. Как только очередь достигает определенного размера, или по прошествии определенного времени, или любого события X, очередь запросов очищается при отправке каждого запроса на сервер.

0 голосов
/ 17 мая 2011

Для большого количества операций записи и такого рода данных вы можете найти более подходящие mongodb или couchdb

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...