Упрощение шардинга с помощью Django

У меня есть проект Django , основанный на нескольких серверах PostgreSQL .

Я хочу, чтобы пользователи были сегментированы между этими серверами баз данных, используя ту же логику сегментирования, которая используется в Instagram :

. Идентификатор пользователя => идентификатор логического сегмента => идентификатор физического сегмента => сервер базы данных => схема => пользовательская таблица

  • Идентификатор логического сегмента вычисляется непосредственно из идентификатора пользователя (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's 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")

Чтобы еще больше усложнить ситуацию, я использую потоковую репликацию для репликации данных каждого сервера базы данных на несколько подчиненных серверов. Мастера должны использоваться для записи, а ведомые — для чтения.

Django обеспечивает поддержку автоматической маршрутизации базы данных , что, вероятно, достаточно для большинства из вышеперечисленных, но я застрял на User.objects.get(pk = user_id), потому что маршрутизатор не имеет доступа к параметрам запроса, поэтому он не знает, что идентификатор пользователя есть, он просто знает, что код пытается прочитать модель пользователя.

Я хорошо понимаю, что сегментирование, вероятно, следует использовать только в качестве крайней меры оптимизации, поскольку оно имеет ограничения и действительно делает вещи довольно сложными. Большинству людей не требуется сегментирование :, оптимизированная архитектура master/slave может иметь большое значение. Но давайте предположим, что мне нужно сегментирование.

Короче:как я могу максимально просто сегментировать данные в Django?

Большое спасибо за вашу помощь.

Примечание

Существует существующий вопрос , который очень похож, но ИМХО он слишком общий и не содержит точных примеров. Я хотел сузить круг вопросов до конкретной техники сегментирования, которая меня интересует (в стиле Instagram ).

21
задан Community 23 May 2017 в 12:01
поделиться