Дизайн архитектуры API для быстрого чтения текстового файла с уникальными метками длиной 150 м
Предположим, текстовый файл со 150 м уникальными записями.
Каждая запись имеет два столбца: (1) строку и (2) целое число.
Строка - это уникальная метка, а целое число - это значение метки.
Единственный запрос вернет целочисленное значение для данной метки.
Мы изучаем несколько архитектур для представления этого текстового файла в виде API.
Этот текстовый файл обновляется каждые 72 часа. ~ 90% данных остаются неизменными при регенерации, но эта регенерация контролируется третьей стороной. Мы просто получаем новый текстовый файл каждые 72 часа.
Мы стремимся к скорости выполнения запросов от 100 до 500 мс на чтение.
Архитектура 1
- Сохраните текстовый файл на диске. Запросите текстовый файл. Кешировать запросы в памяти.
- Плюсы: Простая реализация. Легко обновлять данные.
- Минусы: неэлегантно. Некэшированные запросы чтения выполняются медленно.
Архитектура 2
- Разберите текстовый файл в традиционной базе данных / NoSQL, при этом каждая строка обрабатывается как запись / документ базы данных. Запустите запросы к базе данных.
- Плюсы: Похоже на стандартную архитектуру.
- Минусы: Обновление 150 миллионов записей базы данных происходит медленно и кажется расточительным, тем более что ~ 90% записей остаются прежними.
Архитектура 3
- Используйте Redis или базу данных в памяти для хранения текстового файла размером 5 ГБ. Выполнять запросы к базе данных в памяти.
- Плюсы: быстрые запросы. Легко обновлять данные.
- Минусы: Дорого.
Архитектура 4
- Используйте ElasticSearch для запроса записей.
- Плюсы: ElasticSearch предназначен для поиска.
- Минусы: ES может оказаться излишним для таких простых запросов.
Вопросов:
Стоит ли рассматривать другие архитектуры, или есть плюсы / минусы, которые мы упустили?
Эта инженерная задача кажется обычным явлением: какая самая «стандартная» архитектура для балансировки затрат и производительности при попытке произвести быстрое чтение с хранилищем данных из 150 миллионов изменяющихся записей?
Ответы
Вообще говоря, это выглядит как классический случай для потока ETL: получить новый файл, извлечь данные, преобразовать их в свой формат и загрузить в базу данных. Некоторые примечания:
Важно помнить, что загрузка и запросы относятся к разным и совершенно не связанным операциям. Один вопрос - «как мне эффективно загружать 150-метровый файл записей в день в хранилище данных, когда 90% записей являются дубликатами», а другой - «как мне эффективно запрашивать 150-метровый файл записи ключей / значений». Ответьте на эти два вопроса по отдельности, потому что они независимы.
Что касается вашего первого вопроса, вас беспокоит, что загрузка 90% идентичных записей - пустая трата. Вы измерили время? Чтение 150 миллионов записей из текстового файла должно занять секунды , а хорошее хранилище ключей / значений должно быть в состоянии оптимизировать избыточные операции UPDATE. Либо сравните новый файл с предыдущим, чтобы создать фактический список изменений как часть вашего потока ETL, а затем перейдите к загрузке. Определите показатели для этого решения (общее время чтения, сравнения, загрузки, прерывания операции запроса при загрузке и т. Д.), Чтобы вы могли оценить свое решение.
Что касается вопроса №2, избегайте реализации нестандартных решений, когда есть готовые варианты. ElasticSearch может быть излишним, потому что вы просто храните целые числа с ключами, но существует множество хранилищ ключей / значений, которые обеспечат вам хорошую производительность при чтении, включая кэширование памяти с резервным копированием, кэширование MRU или различные стратегии кэширования в зависимости от вашего использования, возможно, вышеупомянутая операция без операции UPDATE и многое другое. Опять же, как и в вопросе №1, определите показатели успеха. Вы сказали, что «загрузка 5 ГБ в ОЗУ - это дорого. Не так ли? Сколько ОЗУ у вашего сервера? Вы рассматриваете возможность кэширования общих запросов. Требуется ли это? Какова скорость некэшированного чтения? Измерьте! Нужна ли вам индивидуальная стратегия кэширования, например предварительное кэширование связанных записей • Изучите свою модель использования.
Я не могу сказать вам, каков лучший подход. Слишком много переменных, о которых известно только вам - ваш бюджет и модель использования, планы на будущее для системы и потенциал расширяемости, отношения со сторонним источником данных (например, можно ли убедить их создать только различия или добавить метки времени / теги версий для записей и т. д.). Все, что я могу сделать, это предложить основные шаблоны: отделить потоки приема от потоков запросов, использовать проверенные инструменты и, прежде всего, измерить, измерить, измерить.
Вы можете рассмотреть подход, принятый cdb DJBernstein , а именно:
cdb - это быстрый, надежный и простой пакет для создания и чтения постоянных баз данных. Его структура базы данных предоставляет несколько функций:
Быстрый поиск: для успешного поиска в большой базе данных обычно требуется всего два обращения к диску. Неудачный поиск требует только одного.
Низкие накладные расходы: база данных использует 2048 байтов, плюс 24 байта на запись, плюс пространство для ключей и данных.
Никаких случайных ограничений: cdb может обрабатывать любую базу данных размером до 4 гигабайт. Других ограничений нет; записи даже не должны помещаться в память. Базы данных хранятся в машинно-независимом формате.
Быстрая атомарная замена базы данных: cdbmake может перезаписать всю базу данных на два порядка быстрее, чем другие пакеты хеширования.
Быстрые дампы базы данных: cdbdump печатает содержимое базы данных в формате, совместимом с cdbmake.
cdb разработан для использования в критически важных приложениях, таких как электронная почта. Замена базы данных безопасна от сбоев системы. Читателям не нужно делать паузы во время перезаписи.
Вероятно, вам понадобится более современная реализация, не имеющая ограничения в 4 ГБ, например эта .