open atlas
↑ К треку
Разборы System Design SDC · 02 · 07

02-social-feed: чтение конфигов и кода

Читай реальный конфиг и код четырёх кейсов, затем выбирай сеньорную починку: цикл ретраев без дедупа, лента на offset, чат-хендлер с ack до персиста и автодополнение, ранжирующее на пути чтения.

SDC Senior ◷ 14 min
Уровень
ОсновыJuniorMiddleSenior

Баги соцсистем прячутся в нескольких строках: ретрай без проверки дедупа, OFFSET в запросе ленты, ack до записи, вызов базы на пути чтения. Читай каждый сниппет, прослеживай, что происходит на масштабе, и выбирай изменение, которое закоммитит сеньор.

Отрабатывай цикл дизайн-ревью: находи несущую строку, рассуждай, что она делает на миллионах событий, и выбирай починку, что адресует режим отказа, а не замазывает его.

Сниппет 1 — цикл ретраев уведомлений

def deliver(msg):
    for attempt in range(5):
        try:
            provider.send(msg)          # может таймаутить / 429
            return
        except Retryable:
            sleep(2 ** attempt)         # экспоненциальный backoff
    dead_letter.put(msg)
Викторина

Здесь есть ограниченные ретраи, backoff и DLQ. После восстановления провайдера пользователи всё ещё получают дубли push. Чего не хватает?

Сниппет 2 — запрос ленты

SELECT post_id FROM feed
WHERE user_id = :uid
ORDER BY created_at DESC
LIMIT 20 OFFSET :n;     -- n растёт по мере прокрутки
Викторина

Глубокие прокрутки медленны, и пользователи сообщают, что посты появляются дважды или пропускаются. В чём причина и починка?

Сниппет 3 — чат-хендлер отправки

def on_message(ws, msg):
    ack(ws, msg.client_id)              # сказать отправителю: доставлено ✓
    seq = persist(msg)                  # назначить seq, сохранить
    route_to_recipient(msg, seq)
Викторина

В чём баг корректности и как переупорядочить хендлер?

Сниппет 4 — эндпойнт автодополнения

def suggest(prefix):
    rows = db.query(
      "SELECT q FROM search_log WHERE q LIKE %s GROUP BY q ORDER BY count(*) DESC LIMIT 10",
      prefix + "%")            # бежит на каждое нажатие
    return [r.q for r in rows]
Викторина

Это ранжирует совпадающие запросы вживую на каждое нажатие. Тормозит на 600 мс и перегружает кластер. В чём починка?

Вспомните перед уходом
  1. 01
    Почему цикл ретраев с backoff и DLQ всё равно дублирует и почему OFFSET неверен для ленты?
  2. 02
    Почему чат-хендлер обязан персистить до ack и почему автодополнение не может ранжировать на пути чтения?
Итог

Четыре сниппета прячут по однострочному отказу. Цикл ретраев уведомлений имеет backoff и DLQ, но нет ключа идемпотентности, так что повторно хлынувший бэклог дублирует — ретраи at-least-once, дедуп обязан сторожить отправку. Запрос ленты использует OFFSET, что сканирует n строк (медленно на глубине) и сдвигается при вставках (пропуски/дубли); починка — курсорная пагинация. Хендлер чата подтверждает до персиста, так что крах теряет сообщение под уверенной галочкой; сначала персист (и назначь seq), затем ack. Эндпойнт автодополнения ранжирует вживую на нажатие по логу, что не уместит бюджет или нагрузку; предвычисли top-k на узле trie офлайн и отдавай O(1) чтение. Сеньорная привычка: найди несущую строку, рассуди о ней на масштабе и приложи починку, которой требует режим отказа.

Связанные уроки

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.