Ответ
В последнем проекте мы реализовали гарантию exactly-once для критически важных финансовых транзакций, обрабатываемых через Apache Kafka.
Реализация:
- Идемпотентный продюсер: Настройка продюсера с
enable.idempotence=trueгарантирует, что сообщение будет отправлено в партицию ровно один раз, даже при повторных попытках.// Пример настройки на Java Properties props = new Properties(); props.put("bootstrap.servers", "kafka-broker:9092"); props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("enable.idempotence", true); // Ключевая настройка props.put("acks", "all"); props.put("retries", Integer.MAX_VALUE); - Транзакции Kafka: Использовали транзакционное API для атомарной записи consumed-processed-produced в рамках одной транзакции. Это предотвращает дублирование или потерю данных при сбоях в консьюмере.
- Дедупликация на стороне приложения: Для дополнительной надежности в целевую базу данных (PostgreSQL) запись производилась с проверкой уникальности по бизнес-ключу (например,
transaction_id).
Итог: Комбинация идемпотентности Kafka, транзакций и бизнес-дедупликации позволила достичь семантики exactly-once, что было необходимо для корректного учета платежей.
Ответ 18+ 🔞
А, слушай, вот тут на днях такой пердел разбирали — про гарантию exactly-once для денежных переводов через Кафку. Ёпта, это ж святое, там каждый цент на счету, потерять или задвоить — волнение ебать, сразу хиросима и нигерсраки начнутся.
В общем, пришлось нам эту штуку на три кита поставить, чтобы ни один платеж не сбежал и не задвоился. Сделали так, что даже если всё накрылось медным тазом, система как ни в чём не бывало восстановится.
Как мы это провернули:
-
Идемпотентный продюсер — основа основ. Включаешь одну волшебную настройку
enable.idempotence=true, и Кафка сама начинает следить, чтобы в партицию одно и то же сообщение не улетело дважды, даже если продюсер от нервов будет его пятьсот раз переотправлять. Просто красота.// Вот так это выглядит, ничего сложного Properties props = new Properties(); props.put("bootstrap.servers", "kafka-broker:9092"); props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("enable.idempotence", true); // Вот этот самый волшебный пендель props.put("acks", "all"); props.put("retries", Integer.MAX_VALUE);Без этого — доверия ебать ноль, как будто хуй с горы пускаешь и надеешься, что он куда надо прилетит.
-
Транзакции Кафки. Это уже для консьюмеров, которые эти сообщения жрут и обрабатывают. Суть в том, чтобы «прочитал — обработал — записал результат» было одним неделимым куском. Если на любом этапе пиздец, вся транзакция откатывается, как будто ничего и не было. Это чтобы не получилось, что деньги списались, а в отчётность не попали — такой сценарий просто пиздопроебибна.
-
Дедупликация на своей стороне. Ну а это уже наш, родной, последний рубеж обороны. Даже если Кафка где-то чихнёт (хотя она не должна), мы в свою PostgreSQL лезем с проверкой: «А такой
transaction_idу нас уже есть, чувак?» Если есть — просто игнорируем, типа «спасибо, кэп». Бизнес-логика, ёбана.
Что в сухом остатке: Сложили эти три штуки как пазл — идемпотентность, транзакции и свой контроль. Получилась такая броня, что можно спать спокойно. Платежи теперь летают ровно по одному разу, ни хуя себе лишнего. Вроде и овердохуища работы, но зато спим хорошо, не бздим, что утром клиенты с вилами придут.