Я ведущий разработчик сайта с более чем 15 миллионами пользователей. У нас было очень мало проблем с масштабированием, потому что мы планировали это РАНЬШЕ и масштабировали вдумчиво. Вот некоторые из стратегий, которые я могу предложить из своего опыта.
SCHEMA
Во-первых, денормализуйте свои схемы. Это означает, что вместо нескольких реляционных таблиц вы должны выбрать одну большую таблицу. В общем, объединения - это пустая трата драгоценных ресурсов БД, потому что многократная подготовка и сопоставление записывают дисковые операции ввода-вывода. Избегайте их, когда можете.
Компромисс здесь заключается в том, что вы будете хранить / извлекать избыточные данные, но это приемлемо, потому что пропускная способность данных и внутриклеточная область очень дешевы (большие диски), тогда как операции ввода-вывода с множественной подготовкой на порядок дороже ( больше серверов).
INDEXING
Убедитесь, что в ваших запросах используется хотя бы один индекс. Но будьте осторожны, эти индексы будут стоить вам, если вы будете часто писать или обновлять. Есть несколько экспериментальных приемов, чтобы избежать этого.
Вы можете попробовать добавить дополнительные столбцы, которые не проиндексированы, и которые идут параллельно индексированным столбцам. Затем вы можете иметь автономный процесс, который записывает неиндексированные столбцы по индексированным столбцам в пакетном режиме. Таким образом, вы сможете лучше контролировать, когда mySQL потребуется пересчитать индекс.
Избегайте вычисляемых запросов, как чума. Если вам необходимо вычислить запрос, попробуйте сделать это один раз во время записи.
CACHING
Я очень рекомендую Memcached. Это было доказано крупнейшими игроками в стеке PHP (Facebook) и является очень гибким. Для этого есть два способа: один - кэширование на уровне вашей БД, другой - кэширование на уровне вашей бизнес-логики.
Параметр уровня БД потребует кэширования результатов запросов, извлеченных из БД. Вы можете хэшировать ваш SQL-запрос с помощью md5 () и использовать его в качестве ключа поиска перед переходом в базу данных. Плюс в том, что это довольно легко реализовать. Недостатком (в зависимости от реализации) является то, что вы теряете гибкость, потому что вы относитесь ко всему кэшированию одинаково в отношении срока действия кэша.
В магазине, в котором я работаю, мы используем кэширование на бизнес-уровне, что означает, что каждый конкретный класс в нашей системе контролирует свою собственную схему кэширования и время ожидания кэширования. Это хорошо сработало для нас, но учтите, что элементы, извлекаемые из БД, могут не совпадать с элементами из кеша, поэтому вам придется обновлять кеш и БД вместе.
ОХРАНА ДАННЫХ
Репликация только дает вам так далеко. Рано, чем вы ожидаете, ваши записи станут узким местом. Чтобы компенсировать это, необходимо как можно раньше поддерживать разделение данных. Вы, вероятно, захотите застрелиться позже, если вы этого не сделаете.
Это довольно просто реализовать. По сути, вы хотите отделить ключевой орган от хранилища данных. Используйте глобальную БД для хранения сопоставления между первичными ключами и идентификаторами кластера. Вы запрашиваете это отображение, чтобы получить кластер, а затем запрашиваете кластер, чтобы получить данные. Вы можете чертовски кэшировать эту операцию поиска, что сделает ее незначительной операцией.
Недостатком является то, что может быть трудно собрать воедино данные из нескольких шардов. Но вы также можете обойти это.
ОФФЛАЙН ОБРАБОТКА
Не заставляйте пользователя ждать вашего бэкэнда, если ему это не нужно. Создайте очередь заданий и переместите любую обработку, которую вы можете выполнять в автономном режиме, делая это отдельно от запроса пользователя.