Краткая версия
Если я разделю своих пользователей на сегменты, как мне предложить «поиск пользователей»? Очевидно, я не хочу, чтобы каждый поиск попадал в каждый осколок.
Длинная версия
Под осколком я имею в виду наличие нескольких баз данных, каждая из которых содержит часть общих данных. Для (наивного) примера базы данных UserA, UserB и т. д. могут содержать пользователей, чьи имена начинаются с «A», «B» и т. д. Когда новый пользователь регистрируется, я просто проверяю его имя и помещаю его в правильную база данных. Когда вернувшийся пользователь входит в систему, я снова смотрю на его имя, чтобы определить правильную базу данных, из которой нужно извлечь его информацию.
Преимущество сегментирования по сравнению с репликацией чтения заключается в том, что репликация чтения не масштабирует ваши записи. Все записи, которые идут к ведущему, должны идти к каждому ведомому. В некотором смысле, все они несут одинаковую нагрузку записи, хотя нагрузка чтения распределена.
Между тем, шарды не заботятся о записи друг друга. Если Брайан зарегистрируется в сегменте UserB, сегменту UserA не нужно об этом знать. Если Брайан отправит сообщение Алексу, я смогу записать этот факт как на осколках UserA, так и на UserB. Таким образом, когда Алекс или Брайан входят в систему, они могут получить все свои отправленные и полученные сообщения из своего собственного сегмента, не запрашивая все сегменты.
Все идет нормально. Что с поисками? В этом примере, если Брайан ищет «Алекс», я могу проверить UserA. Но что, если он будет искать Алекса по его фамилии «Смит»? В каждом осколке есть кузнецы. Отсюда я вижу два варианта:
- Пусть приложение ищет кузнецов на каждом осколке. Это можно сделать медленно (последовательный запрос каждого сегмента) или быстро (параллельный запрос каждого сегмента), но в любом случае каждый сегмент должен быть задействован в каждом поиске. Точно так же, как репликация чтения не масштабирует запись, поиск, попадающий в каждый сегмент, не масштабирует ваши поиски. Вы можете достичь момента, когда ваш объем поиска будет достаточно высок, чтобы перегрузить каждый сегмент, и добавление сегментов вам не поможет, поскольку все они получают одинаковый объем.
- Какая-то индексация, которая сама по себе терпима к шардингу. Например, допустим, у меня есть постоянное количество полей, по которым я хочу искать: имя и фамилия. В дополнение к UserA, UserB и т. д. у меня также есть IndexA, IndexB и т. д. Когда регистрируется новый пользователь, я прикрепляю его к каждому индексу, по которому я хочу, чтобы его можно было найти. Поэтому я поместил Алекса Смита и в IndexA, и в IndexS, и его можно найти либо в «Алексе», либо в «Смите», но не в подстроках. Таким образом, вам не нужно запрашивать каждый сегмент, поэтому поиск можно масштабировать.
Так можно ли масштабировать поиск? Если да, то является ли этот подход к индексации правильным? Есть ли другие?