Пять различных хранилищ данных, каждое из которых отвечает на вопрос, на который другие отвечают плохо: распределенный SQL для транзакционных бизнес-данных, ширококолонная телеметрия с высокой скоростью записи, хранилище в памяти для эфемерных состояний, объектное хранилище для файлов и векторная база данных для семантического поиска. Правильный выбор — это большая часть инженерии данных, и он почти всегда осуществляется инерцией.
| Мера | Стоимость | Источник | Измеряемые |
|---|---|---|---|
| Отдельные хранилища данных в производственной среде | 5 (YugabyteDB, ScyllaDB, Redis/Valkey, MinIO, Qdrant) | kubectl get statefulsets,deployments --all-namespaces | |
| Распределённая топология SQL | yb-master and yb-tserver as separate stateful sets | kubectl get statefulsets -n kamo | |
| Файлы миграции SQL под управлением версиями | 90 | find . -name '*.sql' across all service repositories | |
| Завершение перехода на рабочий модуль базы данных | 1 (CockroachDB to YugabyteDB, live data) | service configuration history; port 26257 retired in favour of 5433 |
Чему здание нас научило
По умолчанию ответ на вопрос, куда идут данные, зависит от того, какой проект использовался в последний раз. Таким образом, бизнес в конечном итоге запускает аналитические агрегации с базой данных, принимающей заказы клиентов, или хранит тридцать гигабайт загруженных файлов в строках таблиц. Мы выбрали каждый магазин с учетом рабочей нагрузки, и мы переместили его, когда мы ошиблись — платформа ранее работала на другом распределенном SQL-движке и переместилась с него, что действительно сложно делать с производственными данными и стоит больше, чем любое количество обсуждений архитектуры.
Распределенный SQL не является заменой для одноузловой базы данных, и его отличия являются существенными. Транзакция видит один момент на протяжении всего своего жизненного цикла даже в режиме закрепления чтения, так что второе чтение строки внутри одной транзакции не наблюдает за записью другой транзакции, закрепленной между ними — код, который был правильным на одном узле, здесь неправилен. Конфликты чтения и записи появляются как повторяемые ошибки в транзакциях, которые никогда ничего не записывали. Это не экзотические крайние случаи; они являются вторничными, и именно поэтому мы осторожны с тем, что обещаем в работе с данными.
Объектное хранилище переносит каждый загруженный файл, с дедупликацией по содержимому, и это имеет свой урок: неудачная загрузка может оставить строку, которую позднее повторная попытка дедупликации может использовать, создавая файл, который система считает существующим и не может обслуживать. Мы обнаружили это в производственной среде. Теперь мы проверяем это в любой системе, которую мы создаем, которая дедупликирует что-либо.
Построен с
- YugabyteDB
- ScyllaDB
- Redis
- Valkey
- MinIO
- Qdrant
- PostgreSQL wire protocol
- Hibernate
Для чего это нас квалифицирует
Расскажите нам, что вы пытаетесь сделать
Обычно достаточно короткого разговора, чтобы узнать, являемся ли мы подходящими людьми. Если нет, мы скажем вам об этом и покажем вам куда-нибудь лучше.
