А ты придумал задачу для Яндекса?

3 октября (суббота) пройдёт конференция Яндекса “Я про бэкенд” – в Москве и онлайн. Участие бесплатное, но нужна регистрация. В программе – архитектура и эксплуатация систем вокруг AI, потоковая обработка данных и отказоустойчивость.

Меня особенно заинтересовала секция с архитектурной задачей. Зрители присылают свои кейсы, организаторы выбирают один, а backend-разработчики Яндекса разбирают его в прямом эфире. Причём решающий увидит условие впервые. Пожалуй, хороший повод посмотреть, как специалист из топовой компании и с большим опытом выясняет требования и ищет компромиссы.

Решил тоже подать заявку – с задачей поиска/фильтрации медицинских документов, о которой уже писал ранее. Если кратко:

25 млн пациентов, (уже) 7 млрд документов и ещё ~5 млн новых каждый день. В среднем у пациента всего 200 документов, и поиск по его медицинской карте должен укладываться в 200 мс на P99. Но тот же сервис должен искать по всей базе за <5 секунд на P99, поддерживать произвольные сочетания фильтров и учитывать изменения документов не позднее чем через 1 секунду после сохранения. Запросы почти всегда идут без ограничения по периоду создания, а хранить данные нужно десятилетиями.

Это вполне прикладная задача: поиск нужен врачам каждый день. Задача сложная, и мне было бы очень интересно посмотреть, насколько мои идеи близки или далеки от того, что могут предложить инженеры Яндекса.

Но помимо прочего хотелось бы посмотреть на ход доказательства.

Допустим, запрос, который за всю историю найдёт только два документа. Или вообще ничего. Как будет вести себя выбранная архитектура в таком случае, и сколько ресурсов потребуется по мере роста базы? Как совместить быстрый поиск по пациенту с поиском по всей истории? Как расширять хранилище и поддерживать актуальность индекса при непрерывной работе сервиса?

Для ответа на все эти вопросы недостаточно выстроить простую логическую цепочку, нужно спроектировать доказательную базу, по которой можно будет оценить корректность выбранной архитектуры. И это нужно сделать до начала разработки и тем более до внедрения.

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

Пока Яндекс думает, решать или не решать, анонсирую три ближайших события:

  • 24 сентября, 19:00-20:00 МСК – Открытая сессия “Нейроколлеги в SourceCraft: когда код пишут не только люди”. Тут ссылка на YouTube-трансляцию.
  • 25 сентября – LeTeam, фестиваль LentaTech в Санкт-Петербурге и онлайн. Участие бесплатное, по регистрации. Мероприятие больше для тех, кто в ретейле, но мне было бы интересно посмотреть на два доклада (в 15:00 МСК): “Трансформация платформы данных” и “Почему AI-фичи быстро прототипируются и долго доходят до продакшена”.
  • 28 сентября – 2 октября – Podlodka Techlead Crew, онлайн-неделя “Techlead в эпоху AI”. Про работу техлида, внедрение AI в разработку и оценку его пользы для команды. Это Подлодка, тут все доклады ожидаемы и хороши. :)

Ниже текст заявки:

Поиск по 5+ миллиардам медицинских документов

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

На первый взгляд задача выглядит достаточно простой: у одного пациента в среднем около 200 документов. Между тем, тот же сервис должен искать по всей базе из 5 млрд документов, поддерживать произвольные сочетания фильтров и учитывать изменения данных почти сразу после сохранения. Причём база продолжает расти, рост ускоряется, а запросы практически никогда не ограничены периодом времени.

Поиск производится по структурированным метаданным документов: ID пациента, дата создания/подписания, тип и состояние документа, медицинская организация и другие атрибуты. Нужна точная фильтрация по значениям этих атрибутов.

У документа до 20 общих атрибутов и до 50 дополнительных, зависящих от его типа; но обычно дополнительных не больше 5. Значения атрибутов - числа, строки и списки скаляров. Новые типы документов и атрибуты появляются во время работы системы, без повторного развёртывания. Документы могут ссылаться друг на друга: до 100 связей, но обычно не больше 2. В запросе можно проверить наличие связи, но переходить по ней и фильтровать содержимое связанного документа не требуется.

Есть два сценария поиска:

  1. По пациенту - подавляющая часть запросов. Например, “найти все обращения пациента к кардиологу”.
  2. По всей базе, без указания пациента - небольшая, но самая неприятная часть запросов. Например, “найти документы, подписанные выбранным врачом”; “найти все больничные листы, выданные указанной поликлиникой за прошедший месяц”. Такой поиск далее называю популяционным.

Фильтр - произвольная комбинация условий с AND, OR, NOT. Фильтр по времени создания документа указать можно, но в большинстве запросов его не передают. Выдача сортируется от новых документов к старым. Максимальный размер страницы - 2000 записей. Желательно предусмотреть постраничную выборку.

Документ может изменяться несколько раз подряд на протяжении своего жизненного цикла. После индексации изменений поиск должен учитывать только актуальную версию документа: в идеале предыдущая версия не должна попадать в выдачу.

Можно условиться, что у нас HTTP API: на входе - произвольный фильтр по атрибутам, включая необязательный ID пациента, номер и размер страницы; на выходе - список найденных документов (ID и небольшой набор общих атрибутов), отсортированный по дате создания в обратном порядке.

Исходные объёмы и целевые показатели:

  • 25 млн пациентов, прирост - около 120 тыс. в год.
  • 5 млрд документов, прирост - 5 млн новых документов в сутки.
  • Горизонт планирования - 10 лет: при сохранении темпа роста получится порядка 23 млрд документов. Старые документы остаются доступны для поиска, т.к. данные по каждому пациенту хранятся не менее 75 лет.
  • 1000 поисковых запросов в секунду суммарно по обоим сценариям на всю систему.
  • P99 поиска по пациенту - не более 200 мс; популяционного поиска - не более 5 с.
  • Задержка между сохранением изменения по документу и их доступностью в поиске - не более 1 с.
  • Размер метаданных одного документа - до 1.5 КБ до сжатия.

Нужно спроектировать сервис поиска, удовлетворяющий изложенным требованиям, включая выбор и организацию поискового хранилища. Также важны стоимость хранения, расход памяти и нагрузка на I/O при одновременном поиске и обновлении данных.

Как совместить быстрый поиск по пациенту с популяционными запросами? Как расширять хранилище и поддерживать актуальность индекса при непрерывной работе сервиса? Особенно интересно понять, какими нагрузочными экспериментами и метриками можно проверить корректность выбранной архитектуры до её внедрения.

Дополнительный контекст - в моей статье. Осторожно, спойлер: в статье предлагается примерное направление решения, пока не проверенное на практике. “Первичный анализ задачи поиска медицинских документов”.

P.s. Сейчас поиск работает на базе Oracle, системе уже более 15 лет. Текущее решение уже давно никого не устраивает.



Понравилась статья?

Посмею напомнить, что у меня есть Telegram-канал Архитектоника в ИТ, где я публикую материал на похожие темы примерно раз в неделю. Подписчики меня мотивируют, но ещё больше мотивируют живые дискуссии, ведь именно в них рождается истина. Поэтому подписывайтесь на канал и будем оставаться на связи! ;-)

Статьи из той же категории: