Доменно специфичные базы данных и рассылка Aviasales Базы данных, системы хранения
Тезисы
Я расскажу о том как создать базу данных под задачу не решающуюся средствами SQL и как не влипнуть в велосипедостроение и долгострой :) Решение о котором я расскажу было разработано и вышло в продакшн за пару месяцев и окупилось ещё за пару месяцев.
Описание проблемы
1. Нужно отослать пользователю уведомление о том, что появились билеты, соответствующие его параметрам.
2. У Aviasales очередь с результатами поисков, и каждый совершённый поиск авиабилетов добавляет в эту очередь json-документ размером 200-800 Кб, который содержит тысячи билетов и довольно сложно структурирован.
3. В базе подписок - миллионы записей, при этом одна подписка состоит из нескольких предикатов.
В итоге мы имеем поток огромных документов, каждый из которых нужно проверять на соответствие миллионам предикатов. Предикаты бывают как простые (вроде пункт_вылета = Москва), так и сложные (количество_пересадок < 2). Кроме того, некоторые сочетания предикатов проверяют ответ не на полное, а на частичное соответствие (например, цена < 100 && количество_пересадок < 2). В этом случае предикатам будет соответствовать только часть билетов в документе, и именно о них надо уведомить пользователя.
На github и в остальном Интернете не нашлось решения, позволяющего за допустимо короткий промежуток времени (<50 мс) сопоставлять большой сложноструктурированный документ с миллионами предикатов, поэтому мы в Aviasales создали специфичную базу данных, которая справляется с этой задачей.
На данный момент это уникальное решение на рынке. У наших конкурентов вы можете подписаться на информирование с чёткими датами и без требований к времени в пути, цене и других, более сложных условий. То есть у конкурентов просто берётся самый дешевый билет на направление, из базы выбираются соответствующие подписки строгим соответствием по 4-м параметрам (что-то вроде "select * from subscription where origin = 'MOW' and destination = 'LED' and depart_date = '2015-01-01' and return_date = '2015-02-01';").
Да, если очень постараться, можно положить нужную нам логику на SQL, и мы даже делали это перед тем, как заняться собственной разработкой. Даже при полной загрузке данных в память поиск средствами SQL занимал секунды и реализовывался довольно адской генерацией серии SQL-запросов. Под такое решение для обработки нашего потока данных действительно требовался мощный кластер. При этом, как вы понимаете, ни о каком частичном соответствии речи не идёт.