Проектирование масштабируемого мессенджера с поддержкой 150 млн пользователей, 75 млн DAU, 225 млн MAU, 1.2M read / 300k write QPS, 5 млн одновременных пользователей, 60 PB новых данных в год, рост 30% в год, P99 <200 мс для чтения, <300 мс для записи, SLA 99.95%. КОНТЕКСТ Необходимо спроектировать распределённую систему мессенджера, аналогичную WhatsApp, которая поддерживает как 1:1, так и групповые чаты, обеспечивает доставку сообщений, отображение online-статусов пользователей и передачу мультимедийных файлов (фото, видео, аудио). Система должна обеспечивать высокую доступность и низкую задержку, выдерживать высокий параллелизм и масштабироваться на глобальном уровне. ФУНКЦИОНАЛЬНЫЕ ТРЕБОВАНИЯ - Поддержка личных (1:1) и групповых чатов с возможностью добавления/удаления участников - Отправка и получение текстовых сообщений и мультимедийных файлов Нефункциональные требования: - Нет явной реализации механизма end-to-end шифрования на уровне сервисов или клиентов, кроме общей аннотации. - Отсутствует явное описание шардингов и репликации баз данных по chat_id или user_id для масштабируемости и отказоустойчивости. - Нет явного компонента или механизма для обработки офлайн-синхронизации сообщений и delivery receipts. - Не прослеживается, как реализуется балансировка нагрузки между базами данных и сервисами, особенно при пиковых нагрузках. **Узкие места, на которые стоит обратить внимание:** (Далее в диаграмме показана архитектура с Load Balancer, API Gateway, Message Queue, Service, Cache, Database, Object Storage и CDN)
Расскажи про чистую архитектуру и луковую архитектуру
Почему ушли из [компания]? Какая была мотивация?
Чем отличается slice от array в Go и как работает append?
Писал ли документацию?
Почему вы сейчас решили искать новое место работы и уйти из [компания]?
Какие плюсы и минусы ты видишь в использовании в библиотеке fmt.Print?
Как вы планируете использовать две готовые модели (например, модель 1 и модель 2) для морфинга?
Что такое индексы в базах данных, какие виды бывают и с какими вы работали?
Расскажи про проектирование шины/оркестратора модерации — как проектировали, какие решения принимали?
/ * * Дан массив целых чисел и число X, * требуется найти самый длинный непустой подотрезок, минимум на котором равен X. * Верните длину такого подотрезка или -1, если таких подотрезков нет. * /
// Задача 4 // У "типичного" CRUD сервиса - в какой-то момент некоторые методы стали работать медленно и сервис начал таймаутить. // сервис состоит из: // * Application Load Balancer (L7) - прием входящих запросов и терминрование tls // * Backend (rest, java/kotlin или golang) - обработка входящих запросов и бизнес логика // * Database (postgres) - хранение и обработка sql запросов // Как правильно действовать чтобы понять причину проблем и выработать решения для улучшения ситуации?
Всегда ли kill убивает процесс?
/ * Нам нужно передать данные из некоторого источника некоторому потребителю. При этом источник отдает данные небольшими пачками (~ десятки записей), а потребитель оптимальнее работает с крупными батчами (~тысячи записей). Реальный пример - поставка данных из очередей типа Kafka в базу Clickhouse. Источник: - Условно бесконечный. - Источник никогда не возвращает более MaxItems записей за один вызов Next. - В рамках одной "сессии" (одного вызова функции Pipe) источник каждый раз возвращает новые данные на каждый вызов Next. - Однако, после перезапуска источник начнет с прошлой "подтвержденной" позиции, задаваемой cookie. Поэтому *каждое* значение cookie, которое вернул вызов Next, после сохранения данных в приемнике, должно быть фиксировано вызовом Commit, причем строго в той же последовательности, в которой их вернул Next Приемник: - Не может обработать более MaxItems за один раз. Базовый уровень: Требуется реализовать функцию func Pipe(p Producer, c Consumer) error которая читает данные из источника, группирует их в буфер размером не более MaxItems и сохраняет в приёмник, после чего фиксирует прогресс в источнике. Усложнение: Методы Next, Process и Commit связаны с сетевыми вызовами и могут работать довольно долго. Для ускорения процесса передачи нужно распараллелить процессы чтения, записи и подтверждения прогресса. Так, чтобы при вызове Process или Commit продолжалось чтение из источника и формирование нового буфера. * / const MaxItems = 9999 type Producer interface { // Next returns: // - batch of items to be processed // - cookie to be commited when processing is done // - error Next() (items []any, cookie int, err error) // Commit is used to mark data batch as processed Commit(cookie int) error } type Consumer interface { Process(items []any) error } func Pipe(p Producer, c Consumer) error { // TODO }
На что смотришь в EXPLAIN при анализе запроса?
Зачем нужен канал в небуферизированной передаче, если данные идут из стека в стек? Какую роль выполняет канал?
Чем конкурентность отличается от параллельности?
Что такое пессимистическая блокировка?
Как распараллелить обработку логов с использованием worker pool? Как получать результаты из горутин?
Почему ушли с предыдущего места?