У меня есть проект Django на основе нескольких PostgreSQL.
Я хочу, чтобы пользователи sharded на этих серверах баз данных использовали тот же логическая схема, используемая Instagram:
Идентификатор пользователя = > логический осколок ID = > идентификатор физической оболочки ID = > сервер базы данных = > схема = > таблица пользователей
- Идентификатор логического осколка вычисляется непосредственно из идентификатора пользователя (13 бит, встроенных в идентификатор пользователя).
- Отображение от логического к физическому идентификатору осколков жестко закодировано (в каком-либо файле конфигурации или в статической таблице).
- Отображение с идентификатора физического осколка на сервер базы данных также жестко закодировано. В этот момент Instagram использует Pgbouncer, чтобы получить соединение с объединенной базой данных на соответствующем сервере базы данных.
- Каждый логический осколок живет в своей схеме PostgreSQL (для тех, кто не знаком с PostgreSQL, это не схема таблицы, это скорее похоже на пространство имен, похожее на базы данных MySQL '). Схема просто называется чем-то вроде "shardNNNN", где NNNN является логическим идентификатором осколков.
- Наконец, запрашивается таблица пользователя в соответствующей схеме.
Как это можно сделать как можно проще в Django?
В идеале я хотел бы написать код Django, например:
Извлечение экземпляра
# this gets the user object on the appropriate server, in the appropriate schema:
user = User.objects.get(pk = user_id)
Получение связанных объектов
# this gets the user posted articles, located in the same logical shard:
articles = user.articles
Создание экземпляра
# this selects a random logical shard and creates the user there:
user = User.create(name = "Arthur", title = "King")
# or:
user = User(name = "Arthur", title = "King")
user.save()
Поиск пользователей по имени
# fetches all relevant users (kings) from all relevant logical shards
# - either by querying *all* database servers (not good)
# - or by querying a "name_to_user" table then querying just the
# relevant database servers.
users = User.objects.filter(title = "King")
Чтобы сделать вещи еще более сложными, я использую Streaming Replication для репликации данных каждого сервера базы данных на несколько подчиненных серверов. Мастера должны использоваться для записи, а ведомые должны использоваться для чтения.
Django поддерживает автоматическую маршрутизацию базы данных, которая, вероятно, достаточна для большей части вышеперечисленного, но я застрял с User.objects.get(pk = user_id)
, потому что маршрутизатор не имеет доступа к параметрам запроса, поэтому он не знает, что такое идентификатор пользователя, он просто знает, что код пытается прочитать модель пользователя.
Мне хорошо известно, что sharding, вероятно, следует использовать только как последнюю оптимизацию, поскольку имеет ограничения и действительно делает вещи довольно сложными. Большинство людей не нуждаются в осколке: оптимизированная архитектура master/slave может пройти очень долго. Но позвольте предположить, что мне нужно ошпаривание.
Вкратце: как я могу очертить данные в Django, как можно проще?
Большое спасибо за вашу любезную помощь.
Примечание
Существует существующий вопрос, который очень похож, но IMHO он слишком общий и не имеет точных примеров. Я хотел сузить все до конкретной техники осколков, которую меня интересует (путь Instagram).