Какое хранилище выбрать для сервиса переводов с учетом транзакционной нагрузки и скорости
Что проверяют
Умеете ли вы начинать с требований, а не с названия модной базы. Сначала уточните, о каких переводах речь. Обычно о денежных, и тогда главное это корректность: деньги не должны теряться или списываться дважды. Следом спрашивают, как вы защититесь от повторного запроса и что будет при росте нагрузки.
Как отвечать
Для денежных переводов основа это реляционная база с ACID, на практике PostgreSQL. Скорость важна, но вторична: быстрый, но неконсистентный перевод никому не нужен.
Каркас решения:
- модель данных: двойная запись и неизменяемый журнал проводок, где перевод это пара записей на списание и зачисление. Сумма в целых копейках (
bigint) илиnumeric, но никогда неfloat; - транзакция: списание, зачисление и запись в журнал в одной транзакции. Строки счетов блокируют через
SELECT ... FOR UPDATEв фиксированном порядке, чтобы не ловить deadlock. По умолчанию в PostgreSQL уровеньREAD COMMITTED, приSERIALIZABLEнужен повтор транзакции после ошибки сериализации; - идемпотентность: клиент присылает ключ, в базе на него уникальный индекс, повторный запрос получает прежний результат;
- события: уведомления и аналитика уходят в Kafka через паттерн outbox, а не прямой отправкой рядом с коммитом;
- скорость: Redis для кешей и лимитов, но не как источник правды по балансу, реплики для истории операций, секционирование журнала по дате.
Со стороны Python: SQLAlchemy 2.0 или asyncpg, пул соединений, PgBouncer в режиме транзакций. Один хорошо настроенный PostgreSQL выдерживает тысячи простых транзакций в секунду, поэтому CockroachDB или YugabyteDB стоит обсуждать, когда этого требуют цифры, и с оговоркой про задержку распределённого коммита.
Где спотыкаются
Выбирают NoSQL «потому что быстрее». В Cassandra нет ACID-транзакций между разделами, и баланс на ней превращается в отдельный проект.
Не думают про горячие счета. Если на один счёт мерчанта идут сотни зачислений в секунду, все они ждут одну блокировку. Помогают субсчета и пакетное зачисление.
Забывают про повторы: сеть оборвалась, клиент прислал запрос ещё раз, и без ключа идемпотентности деньги ушли дважды.