Собес в 2ГИС · Golang-разработчик в команду CDP
Материал Эйч · Опубликовано 27 октября 2026
Обзор
Подготовка к отбору в Customer Data Platform: highload на Go, Kafka, ClickHouse и распределённые сервисы
Фишка: CDP — «стартап внутри 2ГИС»: влияние на формирующийся стек (Go, gRPC, Kafka, ClickHouse, K8s) и архитектуру под real-time персонализацию и рекламу.
| Этап | Длительность | Что проверяют |
|---|---|---|
| Скрининг / HR | 30–45 мин | Опыт бэкенда, мотивация к 2ГИС и CDP, формат работы, ожидания по грейду и срокам |
| Техническое интервью | 60–90 мин | Go (каналы, синхронизация, типичные ошибки), БД и транзакции, Kafka/очереди, разбор прошлых задач и кода |
| Углубление / команда | 60–90 мин | Архитектура под миллиарды событий, интеграции CDP, код-ревью mindset, совместимость с аналитиками и продактами |
| Оффер | — | Условия, удалёнка, команда Новосибирск / распределённая работа |
Стек и темы
Обязательный минимум
- Go 3+ лет бэкенд (или сильный переход с другого языка)
- Микросервисы и распределённые системы
- HTTP/gRPC API, код-ревью, декомпозиция задач
- SQL/PostgreSQL, базовые транзакции и изоляция
- Очереди/стриминг (Kafka или аналог)
- Понимание highload: объём событий, надёжность, идемпотентность
Плюсом будет
- ClickHouse или колоночные OLAP
- Spark, Airflow, ETL/витрины
- Elasticsearch
- Kubernetes
- Персонализация, сегментация, CDP/маркетинговые данные
- Склейка идентификаторов, real-time агрегации
Go: конкурентность
Какие знаешь примитивы синхронизации?
Mutex/RWMutex, WaitGroup, Once, Cond, atomic; плюс каналы как средство координации. Когда mutex, когда channel.
Что такое канал?
Типизированная очередь для goroutine; буферизованный vs небуферизованный; закрытие, range, select; deadlock при неправильной паре send/receive.
Что такое Mutex?
Взаимное исключение для shared state; Lock/Unlock, RWMutex для read-heavy; не держать lock при I/O; sync.Mutex не копировать после первого use.
Что такое sync.Map?
Concurrent map с sharded locks; удобна при много читателей/редких записей; для сложной логики часто лучше map+mutex или отдельный сервис состояния.
Ловушка: Путать «всё через каналы» и «всё через mutex» — на собесе ждут аргументацию под задачу (ownership vs shared memory).
Совет: Приведи пример race condition и как ты его ловил: -race, тесты, code review.
Базы данных и транзакции
Какие типы БД знаешь?
OLTP (PostgreSQL), OLAP (ClickHouse), KV, document, search (Elasticsearch); когда реляционная модель, когда колоночник и eventual consistency.
Что такое ACID?
Atomicity, Consistency, Isolation, Durability; что гарантирует RDBMS; что ослабляют в распределённых и аналитических системах.
Для чего нужны уровни изоляции транзакций?
Баланс консистентности и параллелизма; dirty/non-repeatable/phantom reads; READ COMMITTED vs SERIALIZABLE; аномалии в highload.
Фишка: CDP сочетает PostgreSQL (операционные данные) и ClickHouse (события и метрики) — полезно проговорить разделение write path и analytics path.
Kafka и потоки данных
Что такое Kafka?
Distributed log: topics, partitions, consumer groups, offset commit; at-least-once vs exactly-once; ключ партиционирования для порядка.
Какие плюсы и минусы Elasticsearch?
Полнотекст и агрегации, горизонтальное масштабирование; дорогой RAM, сложность кластера, не замена OLTP; CDP может использовать search рядом с профилями.
Совет: Свяжи Kafka с задачами CDP: ingestion событий, backpressure, replay, dead-letter, идемпотентные consumer.
Архитектура сервиса на Go
Как правильно структурировать архитектуру сервиса: где хранить команды, доменные сущности, ошибки?
domain (сущности, правила без инфраструктуры), usecase/service, adapters (HTTP, gRPC, repo); typed errors; dependency injection через интерфейсы.
Почему в API-хендлере везде возвращается статус 500? Что с этим не так?
500 только для неожиданных сбоев; 400 валидация, 404 not found, 409 conflict, 422 semantics; маппинг domain errors → HTTP; не светить внутренности в body.
Как проверить корректность временного диапазона бронирования (from < to)?
time.Time, Before/After; timezone и monotonic clock; граничные случаи equal, zero value, UTC vs local.
Что такое флоу задачи?
Жизненный цикл задачи/события: intake → validate → process → persist → side effects; state machine, retries, observability.
Какие знаешь паттерны проектирования?
Repository, Outbox, Saga/CQRS в контексте данных; не перечислять все GOF — привязать к сервисам и интеграциям.
Ловушка: Толстые хендлеры с SQL и бизнес-логикой — на собесе часто просят разнести слои и объяснить тестируемость.
Практика и soft skills
Расскажи о своем опыте
2–3 проекта: масштаб, твоя роль, стек, метрики (RPS, объём данных), что улучшил; ближе к CDP — события, пайплайны, интеграции.
Приведи пример выполнения сложной задачи
STAR без воды: проблема → ограничения → решение → измеримый результат; упомяни trade-offs.
Совет: Подчеркни проактивность: как предлагал улучшения архитектуры или процесса, а не только закрывал тикеты.
Задачи
Валидация интервала времени
Даны два момента времени from и to (time.Time). Реализуй функцию, которая возвращает true, если интервал корректен для бронирования: from строго раньше to, оба не в прошлом относительно «сейчас» (опционально — не длиннее N дней).
func ValidBooking(from, to, now time.Time, maxDuration time.Duration) bool {
if !from.Before(to) { return false }
if from.Before(now) { return false }
if maxDuration > 0 && to.Sub(from) > maxDuration { return false }
return true
}Сложность: O(1)
Ограничение параллелизма (worker pool)
Есть поток задач (chan int) и N воркеров. Обработай все задачи, не создавая неограниченное число goroutine. Верни сумму результатов или ошибку первого сбоя.
ctx, cancel := context.WithCancel(parent)
defer cancel()
var wg sync.WaitGroup
errCh := make(chan error, 1)
jobs := make(chan int)
for i := 0; i < N; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := range jobs {
if err := process(ctx, j); err != nil {
select { case errCh <- err: default: }
cancel()
return
}
}
}()
}
// feed jobs, close(jobs), wg.Wait(), check errChСложность: O(tasks)
Merge двух отсортированных слайсов
Даны два отсортированных по возрастанию слайса int. Верни новый отсортированный слайс без полной сортировки merge-ом (как в merge sort).
func Merge(a, b []int) []int {
out := make([]int, 0, len(a)+len(b))
i, j := 0, 0
for i < len(a) && j < len(b) {
if a[i] <= b[j] { out = append(out, a[i]); i++ } else { out = append(out, b[j]); j++ }
}
out = append(out, a[i:]...)
out = append(out, b[j:]...)
return out
}Сложность: O(n+m)
System Design
- Пайплайн ingestion: миллиарды событий с мобильных и веб-клиентов 2ГИС в CDP (Kafka → обработка → ClickHouse/витрины)
- Склейка идентификаторов пользователя (device id, account id, cookie) в единый профиль с учётом задержек и дублей
- Real-time агрегация метрик и интересов для персонализации в продукте: latency, консистентность, fallback
- Сервис сегментов: как хранить правила, пересчитывать аудитории и отдавать их в рекламные/коммуникационные системы
Каркас ответа
- Уточни объём, SLA (latency, durability), источники и потребители данных
- Нарисуй data flow: producers → bus (Kafka) → processors → storage (PG vs CH)
- Раздели hot path (online) и cold path (batch/Spark/Airflow)
- Обсуди идемпотентность, ключи партиций, backfill и replay
- Надёжность: retries, DLQ, мониторинг lag и consumer health
- Эволюция схемы событий (versioning), privacy и retention
Поведенческое
- Почему решил пообщаться с 2ГИС? Чем тебя привлекла компания или конкретная вакансия?
- На что будешь обращать внимание при выборе компании?
- На что обращаешь внимание при выборе команды?
- Насколько у тебя активный поиск работы: много ли собеседований и компаний, с которыми общаешься?
- Как проводишь код-ревью и что для тебя важно в качестве кода?
- Пример, когда предложил улучшение архитектуры или процесса без прямой постановки
План подготовки
3 дня
- Повторить каналы, mutex, WaitGroup, context; решить 2 задачи на конкурентность
- Проговорить вслух ответы на Kafka, ACID, уровни изоляции
- Подготовить 3-минутный питч опыта с упором на бэкенд и данные
- Прочитать описание CDP и сформулировать 5 вопросов к команде
7 дней
- Разобрать слоистую структуру Go-сервиса и маппинг HTTP-кодов
- Набросать на бумаге ingestion pipeline для CDP (system design)
- Освежить ClickHouse: MergeTree, партиции, отличие от PostgreSQL
- Пройтись по своим проектам: цифры, ошибки в проде, что бы сделал иначе
14 дней
- Углубить distributed systems: consistency, outbox, saga на уровне собеса
- Практика live coding: слайсы, strings, простой HTTP handler с валидацией
- Mock-интервью с коллегой: Go + один design prompt
- Изучить публичные материалы 2ГИС про данные и продукт (карты, реклама, персонализация)
| Блок | Готов, если... |
|---|---|
| Go: конкурентность | можешь объяснить deadlock, выбрать mutex vs channel и написать worker pool |
| БД и транзакции | различаешь OLTP/OLAP и называешь уровни изоляции с примерами аномалий |
| Kafka | объясняешь partitions, consumer groups и стратегию идемпотентной обработки |
| Архитектура | рисуешь слои Go-сервиса и правильные HTTP-статусы для типовых ошибок |
| System design | за 25 мин набросаешь event pipeline с Kafka и хранилищами под аналитику |
| Мотивация | чётко объясняешь интерес к CDP и 2ГИС без общих фраз |
В день собеседования
- Проверить связь, IDE/доску если нужен live coding
- Держать под рукой примеры масштаба из своего опыта
- На мотивационные вопросы — связка с CDP и влиянием на продукт
- В конце задать вопросы про стек, on-call, roadmap CDP