Всем привет!
Сегодняшний пост начну издалека. Распределенные системы обмениваются сообщениями. Каждое сообщение можно рассматривать как событие, требующее какой-то обработки и передачи дальше - в другую подобную систему или для хранения в БД. Т.об. мы получаем распределенную цепочку микросервисов, через которые проходит событие. Существуют т.наз. семантики доставки сообщений:
- at-most-once
- at-least-once
- exactly-once
at-most-once - максимум один раз, т.е. 0 или 1. Т.е. есть вероятность потерять и не обработать сообщение. Подходит для случаев, когда поток сообщений большой, используется для сбора статистики и потеря одного сообщения не критична. Например - статистика по кликам на сайте.
at-least-once - минимум один раз, т.е. 1 или более. Т.е. есть вероятность повторно отправить какое-то сообщение и, соответственно, обработать его дважды. Подходит для систем, где важно знать последнее значение. Пример: стоимость акции на сайте брокера. Или для систем, идемпотентно обрабатывающих входящие сообщения - https://habr.com/ru/companies/domclick/articles/779872/
exactly-once - строго один раз. Идеальный случай.
Да, система может поддерживать сразу несколько семантик, т.е. по сути иметь несколько режимов работы.
Самый интересный и сложный - это конечно exactly-once. Как с ним обстоят дела?
Например, его поддерживает Kafka - самая распространённая система потоковой передачи сообщений - https://docs.confluent.io/kafka/design/delivery-semantics.html
А также самые распространенные системы потоковой обработки данных:
Kafka Streams - https://kafka.apache.org/33/documentation/streams/core-concepts
Flink - https://flink.apache.org/2018/02/28/an-overview-of-end-to-end-exactly-once-processing-in-apache-flink-with-apache-kafka-too/
Spark - https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html
Кажется, что все хорошо. Но не совсем)
Если прочитать внимательнее, что пишут, например, создатели Kafka, то выяснится что exactly-once гарантируется на участке Producer - Kafka, но далее все зависит от того, как организована работа в Consumer-е. Вот неплохая переводная статья на эту тему от одного из создателей Kafka: https://habr.com/ru/companies/badoo/articles/333046/ // в статье detected american style самореклама, но все равно она неплохая)))
Создатели Flink тоже говорят, что
а) мы даем механизм для exactly-once - в случае сбоя мы откатим ваш обрабатывающий процесс на конкретное состояние (checkpoint), и вы четко будете знать, что это за состояние - его метку времени, что было до и после него, но
б) что делать уже обработанными записями, находящимися после восстановленного состояния - разбирайтесь сами
в) возможность вернуться к сообщениям, на которые указывает checkpoint - тоже на стороне разработчика. В случае Kafka это чаще всего элементарно - сообщения не удаляются сразу после чтения из топика, а если это MQ или сетевой сокет...
г) а еще можно рассмотреть кейс, если кто-то обновил хранилище, где хранится состояние
д) или если в функции потоковой обработки используются какие-то внешние вызовы, которые сломаются на повторах после отката...
Но по большому счету это частности. Основная проблема - системы типа Kafka или Flink могут обеспечить exactly-once на какой-то небольшой части вашей микросервисной системы. Как обеспечить ее на всей системе - в любом случае задача архитектора и разработчика.
Подсказка: наличие operationId (traceId), идемпотентность, транзакции там где это возможно, докаты и наконец админка для ручного разбора инцидентов если не помогли все предыдущие варианты.
#streaming #kafka #flink #arch #microservices #exactly_once
Сегодняшний пост начну издалека. Распределенные системы обмениваются сообщениями. Каждое сообщение можно рассматривать как событие, требующее какой-то обработки и передачи дальше - в другую подобную систему или для хранения в БД. Т.об. мы получаем распределенную цепочку микросервисов, через которые проходит событие. Существуют т.наз. семантики доставки сообщений:
- at-most-once
- at-least-once
- exactly-once
at-most-once - максимум один раз, т.е. 0 или 1. Т.е. есть вероятность потерять и не обработать сообщение. Подходит для случаев, когда поток сообщений большой, используется для сбора статистики и потеря одного сообщения не критична. Например - статистика по кликам на сайте.
at-least-once - минимум один раз, т.е. 1 или более. Т.е. есть вероятность повторно отправить какое-то сообщение и, соответственно, обработать его дважды. Подходит для систем, где важно знать последнее значение. Пример: стоимость акции на сайте брокера. Или для систем, идемпотентно обрабатывающих входящие сообщения - https://habr.com/ru/companies/domclick/articles/779872/
exactly-once - строго один раз. Идеальный случай.
Да, система может поддерживать сразу несколько семантик, т.е. по сути иметь несколько режимов работы.
Самый интересный и сложный - это конечно exactly-once. Как с ним обстоят дела?
Например, его поддерживает Kafka - самая распространённая система потоковой передачи сообщений - https://docs.confluent.io/kafka/design/delivery-semantics.html
А также самые распространенные системы потоковой обработки данных:
Kafka Streams - https://kafka.apache.org/33/documentation/streams/core-concepts
Flink - https://flink.apache.org/2018/02/28/an-overview-of-end-to-end-exactly-once-processing-in-apache-flink-with-apache-kafka-too/
Spark - https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html
Кажется, что все хорошо. Но не совсем)
Если прочитать внимательнее, что пишут, например, создатели Kafka, то выяснится что exactly-once гарантируется на участке Producer - Kafka, но далее все зависит от того, как организована работа в Consumer-е. Вот неплохая переводная статья на эту тему от одного из создателей Kafka: https://habr.com/ru/companies/badoo/articles/333046/ // в статье detected american style самореклама, но все равно она неплохая)))
Создатели Flink тоже говорят, что
а) мы даем механизм для exactly-once - в случае сбоя мы откатим ваш обрабатывающий процесс на конкретное состояние (checkpoint), и вы четко будете знать, что это за состояние - его метку времени, что было до и после него, но
б) что делать уже обработанными записями, находящимися после восстановленного состояния - разбирайтесь сами
в) возможность вернуться к сообщениям, на которые указывает checkpoint - тоже на стороне разработчика. В случае Kafka это чаще всего элементарно - сообщения не удаляются сразу после чтения из топика, а если это MQ или сетевой сокет...
г) а еще можно рассмотреть кейс, если кто-то обновил хранилище, где хранится состояние
д) или если в функции потоковой обработки используются какие-то внешние вызовы, которые сломаются на повторах после отката...
Но по большому счету это частности. Основная проблема - системы типа Kafka или Flink могут обеспечить exactly-once на какой-то небольшой части вашей микросервисной системы. Как обеспечить ее на всей системе - в любом случае задача архитектора и разработчика.
Подсказка: наличие operationId (traceId), идемпотентность, транзакции там где это возможно, докаты и наконец админка для ручного разбора инцидентов если не помогли все предыдущие варианты.
#streaming #kafka #flink #arch #microservices #exactly_once
Хабр
Идемпотентность: больше, чем кажется
Друзья, всем привет! Идемпотентность в проектировании API — не просто формальность. Это свойство, часто рассматриваемое как способ получения одинакового ответа на повторяющийся запрос, на самом деле...