Алексей @fuCtor
Backend developer
Information
- Rating
- Does not participate
- Location
- Санкт-Петербург, Санкт-Петербург и область, Россия
- Date of birth
- Registered
- Activity
Specialization
Backend Developer
Lead
Scala
Git
Docker
Redis
High-loaded systems
Designing application architecture
PostgreSQL
В таком случае хоть правым пользоваться можно. У меня стал так садится правый, а без него левый не хочет работать :/.
Прочитайте про STUN сервер, один из вариантов обхода NAT.
Т.е. вы предлагаете:
получаем запрос на один из N инстов и открываем транзакцию
держим эту транзакцию до завершения
при обработке все действия с этим платежом роутим на этот же инст где транзакция, иначе как мы ее закроем
получили оплату, закрываем транзакцию
PROFIT
Если верно понял схему то сходу возникают задачи, которые нужно решать:
sticky session
таймаут на транзакцию все равно нужен, т.к. (если коговорим про web) пользователь может закрыть/обновить страницу, потерять соединение и это нормально, но в итоге у нас разорвется соединение, как следствие клиент типо ушел, транзакция висит, но он же не ушел никуда. Да и вообще процессы оплаты бывают очень разные
как перезапустить сервис, чтобы не сбросить пользователей, которые в процессе оплаты (прервать happy path)
Видится мне, что это не сильно проще чем просто временная блокировка, а поддержка возможно и сложнее.
это вот этот пример?
судя по всему callback синхронный, для репликации во внешнее хранилище минус, так же не вижу как прервать транзакцию внутри этого метода или такой возможности нет или нужно исключение кидать?
И код приложен zip архивом, а не в публичной репке о_О?
А это прям так плохо и ужасно? Могу конечно ошибаться, но транзакция живет, пока живо соединение с БД, получается, если мы решим перезапустить инстанс приложения, то все наши транзакции (брони) слетают? Иначе наши сервисы из stateless превращаются в statefull.
Что значит блокировать, не дать другому купить его? Зачем для этого длинная транзакция? Добавляем поле status (и другие если надо), помечаем что забронировано, все, теперь хоть через 1с, хоть через 10, хоть через сутки другие не смогут его забронировать и это будет работать на любой БД с транзакциями достаточными для выполнения простого обновления.
Если очень хочется, можете поднять лимит, но зачем?
В остальном он предлагает аналогичную концепцию создания структур второго порядка на базе мамы и транзакций.
То что описано у вас хорошо, но как это использовать в реальной жизни? Если говорим про сервис, то нужно минимум 2 экземпляра, следовательно надо решать проблемы синхронизации и тд.
Какие пессимистичные блокировки в распределенных системах о_О? Если они вам нужны, транзакции вам в помощь, реализуем распределенную блокировку + подписка на ключ и вот вам "оптимистичная блокировка" хоть на сутки.
Есть примитивы, достаточно надёжные, далее из них строим все что нужно на уровне приложения.
Посмотрите на FoundationDB. Все что описано у вас, там и используется, только в большом масштабе.
Судя по тексту, вы использовали не чистый NATS, а его компонент JetStream.
Почему Kafka? Почему не отказались от JetStream и остались на Nats + DB?
В Сириус ещё можно на экскурсии сходить. Там покажут расскажут чем занимаются, покажут лаборатории, стенды, все, куда можно зайти будет. Ещё столовая хорошая с демократичным ценником)
https://antithesis.com/docs/using_antithesis/sdk/go/overview.html вот SDK, тут видно, что они предоставляют замену random и другие вспомогательные пакеты, которые позволяют интегрировать код в платформу. Технические подробности того что легло в основу можно глянуть в исходниках FoundationDB.
Статика хорошо, но не принципиально, зависимости всегда можно доставить, а в Docker это вообще пофиг.
В мониторинге хотя бы базовые RED метрики, чтобы видеть что и как работает. А отдавать их можно по классике, в формате prometheus на /metrics ручке.
Как pet project хорошо. Но вот по протоколу для клиентов рекомендовал бы выбрать что-то стандартное. Сейчас только для PHP есть клиент, другие попробовать не смогут. Взяли бы gRPC, под любой язык готовый клиент из коробки.
Так же, не заметил метрик, любых средств мониторинга.
Для корректной работы circuit breaker нужно отказаться от промежуточных балансировщиков, либо перенести circuit breaker на них. В случае клиентской балансировки, клиент видит все хосты и может выкидывать их точечно, а не весь балансер разом.
Тут вопрос, а нужны ли они, если исходить из описанных пунктов, то:
Есть атомарные операции https://apple.github.io/foundationdb/developer-guide.html#atomic-operations
И если нам нужно писать сообщения, то получаем следующую структуру:
префикс/<channel>/<version>/<ts>/<user> = <payload>
version - может проставляться самой БД в момент коммита, что гарантирует всегда растущую последовательность
тогда чтение лога будет выглядеть как getRange(префикс/<channel>/<last_version>, префикс/<channel>/\xff)
В целом, не обязательно использовать CAS, если можно использовать особенности и возможности самой БД.
А смотрели для БД на что-нибудь ещё? По описанию не плохо подходит сюда FoundationDB, есть и сортировка, и внутренние "часы", она же версия, и полностью асинхронный.
Пробовали, но значимых различий не получили, на синтетике тоже не заметил, возможно синтетика была не подходящая или не выполнил требуемые условия, надо будет повторить. Больше понравился вариант с aperture, так как снизу было большое количество хостов и по метрикам сразу был заметен эффект от уменьшения активного множества.
Neo4j хорош, пока не надо на нем строить прод. С этого момента надо готовить кошелек, так как в бесплатной версии, можно сказать, для этого ничего нет. В текущих реалиях, даже будучи готовым заплатить не факт что их возьмут.
По описанию warden, вобрал некоторые идеи от linkerd, он кстати уже на go+rust переписан, и Twitter (Finagle), на котором тот базировался.
Как стартовая точка сойдёт, но теперь нужно провести к более преемлему виду. Класс Game смешивает и логику и данные, так делать не хорошо. Вынесите в отдельный класс, который будет выполнять это. В остальных классах тоже бы вынести. Case class без атрибутов лучше заменить на case object.