Паттерн Outbox - теория и практика | Архитектура Микросервисов

Поділитися
Вставка
  • Опубліковано 22 гру 2024

КОМЕНТАРІ • 110

  • @nikolay_tuzov
    @nikolay_tuzov  6 місяців тому +3

    Мой канал в Telegram: t.me/ntuzov
    Пишу там новости, анонсы своих активностей, небольшие текстовые гайды и просто интересные мысли.
    Также через него я получаю от вас оперативный фидбэк по роликам - что нравится, что не нравится, какой ролик делать следующим и т.п.

  • @VladislavNovikov-g4u
    @VladislavNovikov-g4u Місяць тому +1

    Николай, спасибо за видео очень интересное и полезное видео. Благодарю тебя за твой контент бро.

  • @nosipov.h
    @nosipov.h 5 місяців тому +2

    Отличное видео! Я как-то о самом названии Outbox не слышал. Поэтому не знал, что меня ожидает и на первой же минуте приостановил видео и пошел в рассуждения что может пойти не так и какие проблемы будем решать (и как). Радости, после того, как видео было снято с паузы, было столько же, как когда впервые получил оффер :) Круто, что про гарантию доставки тоже было упомянуто. В общем, чувство как-будто вместе поработали - спасибо, с меня лайк :)

  • @КириллАпанасюк-п9м
    @КириллАпанасюк-п9м 5 місяців тому +1

    Спасибо за видос! Смотрю вас периодически. Классно объясняеете. Будет круто, если сделаете видос по inbox)

    • @nikolay_tuzov
      @nikolay_tuzov  5 місяців тому

      Про inbox будет, скорее всего)

  • @vitaliikutovoi9981
    @vitaliikutovoi9981 3 місяці тому +1

    Спасибо большое, было очень познавательно, учусь по твоим видео!

  • @johnb7657
    @johnb7657 6 місяців тому +4

    Всегда ставлю лайк, смотрю с удовольствием, потом скачиваю и пересматриваю часиенько.
    Благодарю

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому +4

      Спасибо, но лучше пересматривать на ютубе, чтобы статистика учитывала это. Если ролики часто пересматривают, то их лучше будут рекомендовать другим людям =)

  • @yoloprotector3159
    @yoloprotector3159 5 місяців тому +2

    О! Класс, спасибо!
    Было бы супер увидеть видео про Сагу

  • @АндрейПальчиков-ф1б
    @АндрейПальчиков-ф1б 6 місяців тому +1

    Николай, спасибо за очередное супер видео
    Очень помогаешь

  • @DWGFragaed
    @DWGFragaed 6 місяців тому +1

    Николай внатуре легенда!

  • @leonscander1431
    @leonscander1431 3 місяці тому

    Спасибо за ролик. Хотел бы заметить: ты создал отдельную модель в слое storage, чтобы сканить из БД сразу в структуру и не писать отдельно скан в каждое поле. Но после скана в структуру ты маппишь ее в структуру доменной модели отдельно прописывая каждое поле, т.е. ничего особо не изменилось.

  • @saintcorporation-t1h
    @saintcorporation-t1h 6 місяців тому

    отличный формат видео ! я трейни go могу сказать что ощутил себя в качестве стажера в первом коммерческом прожэкте ) очень интересная необычная подача !

  • @dmitryd1572
    @dmitryd1572 5 місяців тому

    Толковый и интересный материал, спасибо !

  • @RussiaRedNick
    @RussiaRedNick 6 місяців тому +2

    Пока не смотрел, но для продвижения сразу поставил лайк, успехов автору!)

  • @Artemh1994
    @Artemh1994 6 місяців тому +1

    Николай, спасибо!
    Как обычно очень полезно!

  • @man0xff
    @man0xff 6 місяців тому +1

    Супер! Спасибо за отличный материал 👍

  • @ironbondar
    @ironbondar 6 місяців тому +2

    четко объяснил, спасибо!

  • @Levelord92
    @Levelord92 Місяць тому

    Мне эта тема чем-то event sourcing напомнила. Все события кладутся в dynamodb табличку например, на котором по триггеру работает лямбда, которая уже может отправить в какой-то sqs/sns

  • @Dantesik1
    @Dantesik1 6 місяців тому +2

    Здравствуйте Николай! Спасибо за видео! Как обычно - все понятно даже дурочку!

    • @FerelUltra
      @FerelUltra 6 місяців тому

      Лол. Не ожидал тут дбд ютубера увидеть)))
      Ютуб не кормит?

    • @Dantesik1
      @Dantesik1 6 місяців тому

      @@FerelUltra Меня с руки кормит лично Николай

  • @emotional_stuff
    @emotional_stuff 3 місяці тому

    Николай спасибо огромное

  • @петяпетров-ч6с
    @петяпетров-ч6с 5 місяців тому +5

    на фразе "пардон - не та картинка" пришла жена из соседней комнаты и стала спрашивать чего со мной случилось что я так ржу

    • @nikolay_tuzov
      @nikolay_tuzov  5 місяців тому +2

      Ну хоть кто-то оценил шутку, спасибо

  • @shinsh8436
    @shinsh8436 5 місяців тому +1

    По поводу транзакции. Разве нельзя сразу писать defer tx.Rollback() ? То есть если код дошел до tx.Commit(), Rollback выполнится но уже ни на что влиять не будет

  • @littledrongo5469
    @littledrongo5469 6 місяців тому

    Николай, спасибо что живой ❤

  • @СамвелСаргисян-с7н
    @СамвелСаргисян-с7н 6 місяців тому +4

    Вижу видос на канале - ставлю лайк заранее

  • @aidarark5558
    @aidarark5558 6 місяців тому +3

    Очень круто, хочется с такой же подачей материал посложнее

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Скоро будет ролик посложнее)

    • @ninshu1138
      @ninshu1138 6 місяців тому

      🤓🤓🤓

  • @ГеоргийПлиев-р4ц
    @ГеоргийПлиев-р4ц 4 місяці тому

    а нельзя в рамках БДшной транзакции отправлять сообщение в очередь просто? т.е. создали транзакцию, сделали инсерт в БД, отправили сообщение в очерель и сделали коммит. И если мы получили ошибку очереди, то просто сделать роллбэк транзакции. Есть конечно недостаток: если у нас упадет очередь, то пользователь не сможет делать переводы. Но есть ли еще какие-то подводные камни в таком подходе?

    • @xz8928
      @xz8928 3 місяці тому

      Конечно есть, сообщение отправится, а транзакция может ролбекнуть. В итоге сообщение уже в очереди и возможно обрабатывается, а по факту в бд ничего не произошло

  • @ЭмильСадыгов
    @ЭмильСадыгов 6 місяців тому

    Николай, спасибо за очередной опыт.
    Есть один вопрос, почему мы не прописали логику отправки сообщения внутри case блока тикера ?

  • @КириллКозырь-л9л
    @КириллКозырь-л9л 6 місяців тому +3

    очень полезно. спасибо

  • @ИванИванов-я5э9к
    @ИванИванов-я5э9к 6 місяців тому +6

    Просто забить на все это и работать в монолите. Хочешь транзакшн фид? Ну создай в бд еще табличку, будет тебе транзакшн фид. )))) Есть мнение, что микросервисы для надувания щек перед инвесторами. По крайней мере - это одно из главных назначений этого подхода.

    • @БанинЕгор
      @БанинЕгор 5 місяців тому +4

      Возможно пример с фидом неудачный. В общем случае как только есть две системы, между которыми невозможна транзакция, то возникает эта проблема. И одно из решений это аутбокс. В вашем монолите наверняка есть подобная проблема. Например пользователь зарегался, ему надо отправить письмо. В бд записали, письмо не отправили. Или письмо отправили, а транзакция упала. Часто на это просто забивают, и алгоритм аутбокса выполняет сотрудник поддержки :-)

    • @semenivanoff8615
      @semenivanoff8615 5 місяців тому

      Ага, а потом нагрузка на монолит вырастет в 100 раз, а монолит уже не вырастет.
      Или в 100 раз и в 5ти странах.

    • @ИванИванов-я5э9к
      @ИванИванов-я5э9к 5 місяців тому

      @@БанинЕгор Будьте добры, перечислите еще 10 случаев аутбокса в монолите. Кроме письма. Что-то мне подсказывает, что не наберется. А вот в микросервисах они будут на каждый чих и о всех помнить не будешь. В один прекрасный пятничный вечер руководство донесет, что надо восстанавливать какие-то данные, потому что оно где-то скрыто и очень давно работало не так из за того, что в такой сложной системе кто-то что-то когда-то проглядел. У меня на работе монолит и куча интеграций. У нас так бизнес процесс устроен, что если интеграция не ответила, то все, до свидания, смысла развлекать пользователя нет. Эксепшн, обращайтесь завтра после обеда.

    • @buginsystem8925
      @buginsystem8925 4 місяці тому +1

      Сервисы могут быть написаны на разных языках и их легче масштабировать.

    • @ИванИванов-я5э9к
      @ИванИванов-я5э9к 4 місяці тому

      @@buginsystem8925 в чем прикол? Эти все языки об одном и том же. Чем golang лучше C#? Решает те же задачи. Выглядит по другому. Ну и что. Языкодрочка - онанизм. И последнее, что хочет нормальный бизнес - это зоопарк языков на своем борту.

  • @eminshakh
    @eminshakh 6 місяців тому +1

    Воркеры не должны брать записи из базы с блокировкой? for update skip locked. Чтобы несколько воркеров не взяли одно и тоже сообщение.

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Да, всё верно, если воркеров больше одного, то так и нужно. Я здесь немного упрощал, чтобы не затягивать, и чтобы было проще для понимания.

  • @alexalex-f8f
    @alexalex-f8f 2 місяці тому

    Кажется есть очень простое решение проблемы - танзакшн менеджер. Просто оборачиваем в транзакцию на сервисном уровне сохранение в бд и вывоз продьюса.
    Если гдето по дороге падаем - транзакция не комитится и все останется консистентно

  • @MadMaxxx77
    @MadMaxxx77 6 місяців тому

    Очень жду ролик о тестировании!

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      А расскажи подробней, что ты хотел бы увидеть в этом ролике?

    • @ValentynKhoroshilov
      @ValentynKhoroshilov 5 місяців тому

      @@nikolay_tuzov можно уже на существующие проекты накидать юнит-тестов и мок (ну тот минимум базы, которую ждут от твердого джуна)
      Понятно, что уже есть таких много примеров, но ты пожалуй один из лучших лекторов по Го (в снг-сегменте так точно)

  • @Artem.Alalykin
    @Artem.Alalykin 6 місяців тому

    Спасибо за видео! Николай, вопрос не по теме: не подскажешь, что за кресло используешь?

  • @НиколайВикторович-х3г
    @НиколайВикторович-х3г 6 місяців тому

    35:12 а почему бы не написать внутри второго case ?

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому +1

      Потому что "плоский" код легче читается. Я этот select воспринимаю как Guard Expression

  • @vadimbondarenko7416
    @vadimbondarenko7416 6 місяців тому

    Спасибо за видео! А валидно ли архитектурное решение, когда отправляем сообщения в кафку, а воркер уже считывает с кафки и пишет в базу. В то же время другой сервис тоже может считывать с кафки.

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Нет, не решает. Допустим, все сервисы узнали о новом переводе, а что дальше? Наш Transfer Manager начинает этот перевод обрабатывать. В процессе его статус будет меняться: initial -> processing -> done / failed. Как другие сервисы будут узнавать о смене статуса? Ну и дальше та же логика - мы обновляем статус платежа в БД и отправляем сообщение об этом. По сути, Transfer Manager здесь является исходным источником информации.
      В общем, это не решает текущую проблему, ты просто смещаешь угол обзора. В моём рассказе не принципиально, по какому каналу Transfer Manager получил инфу о новом переводе - по grpc, из кафки и т.п. Суть не меняется.
      Если хочешь обсудить подробней, приходи в наш чат Gopher Club, обсудим.

    • @vadimbondarenko7416
      @vadimbondarenko7416 6 місяців тому

      @@nikolay_tuzov Да, все верно. Спасибо за объяснение!

  • @ПавелШведко-ч8г
    @ПавелШведко-ч8г 6 місяців тому

    на 25:00 метод tx.Commit() выплняется только и тогда (!) когда err == nil, то есть когда ошибок на выходе не было до выполнения коммита, то есть нет никакого либо либо и переменная commitErr не нужна, можно сразу записывать выхлоп в err = tx.Commit()

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Да, вы правы, спасибо за замечание. Немного запутался в этом месте)

  • @janari_dev
    @janari_dev 25 днів тому

    ждем сагу ))

  • @AlexZapped
    @AlexZapped 5 місяців тому

    здорово, что говорится про graceful shutdown, но жаль, что только говорится, ибо код в main не имеет признаков graceful shutdown

    • @nikolay_tuzov
      @nikolay_tuzov  5 місяців тому

      Так ролик не о нём. Да и сам URL Shortener во многих местах упрощён, т.к. был написан в течении нескольких часов, для учебного видео.

  • @alexanderkuznetsov634
    @alexanderkuznetsov634 6 місяців тому

    Вот они проблемы event driven architecture. Я бы взял оркестратор например Temporal, который бы делал retry

  • @eminshakh
    @eminshakh 6 місяців тому +1

    Как всегда супер видос) подскажи модель кресла

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      DxRacer Air но мне оно не очень понравилось, неудобное. Хотя, дизайн крутой

  • @sadstill
    @sadstill 6 місяців тому

    Хотел уточнить, вот кейс когда говорится в начале что сервер упадет, не могу понять одно. У нас же сохранение в бд и отправка сообщения в кафку происходит в рамках одной транзакции? Просто если так, то по-идее при перезагрузке сервера, у нас не получится запродюсить сообщение в кафку и транзакция откатится, нет? Как тогда произойдет неконсистентность?

    • @wildegor
      @wildegor 6 місяців тому

      Не факт. А если получилось запродюсить данные в брокер? Тогда данные есть в брокере (и потенциально в консьюмере), а в БД их нет и наоборот. Идея паттерна в том и заключается, чтобы исключить момент когда в рамках транзакции пишем в разные места (бд и брокер).

    • @sadstill
      @sadstill 6 місяців тому

      То есть ты говоришь про кейс. Что сохранили в базу, запродюсили, а потом упал сервер и транзакция откатилась? И вот типо будет неконсистентность?

    • @MrLotrus
      @MrLotrus 6 місяців тому +1

      Если открыть транзакцию, добавить запись, отправить сообщение в кафку и только потом закоммитить транзакцию, то это существенно замедлит работу с базой.

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому +1

      У тебя тут главная ошибка в этом месте: "сохранение в бд и отправка сообщения в кафку происходит в рамках одной транзакции". Транзакции обеспечивают атомарность в рамках одной только БД, а кафка сама по себе. Поэтому, не очень понимаю, что ты имеешь ввиду.
      Да, бывают распределнные транзакции, например 2-phase commit, о котором я упоминал, но это более сложная штука.
      В любом случае, приходи лучше к нам в Gopher Club, и там обсудим. В комментах неудобно вести долгие дискуссии.

    • @sadstill
      @sadstill 3 місяці тому

      @@nikolay_tuzovизвиняюсь, я просто из-за того, что на спринге пишу, привык что у нас можно транзакции ролбэкать не только при ошибках связанных с бд. То есть я могу в рамках одной spring transactional сделать сохранение в бд и продюсить в кафку. И например первым делом я сохраню в бд, а брокер мог отвалится, то у меня при попытке запродюсить выбросится исключение и транзакция не отработает.

  • @evgeniykanovalov3372
    @evgeniykanovalov3372 6 місяців тому

    Вопрос: а разве сообщение об ошибке, которое возвращается в saveEvent, не будет перезаписано в SaveURL
    Потеряется же op из saveEvent?

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Нет, ничего не потеряется, мы просто будем врапить одно в другое. В итоге, получится цепочка из всех ошибок, что мы успели завернуть. Попробуй вернуть ошибку из saveEvent, и посмотри что получтся.

    • @evgeniykanovalov3372
      @evgeniykanovalov3372 6 місяців тому

      @@nikolay_tuzov понял, спасибо

  • @СергейБевзенко-и8с
    @СергейБевзенко-и8с 6 місяців тому +1

    А видео про garbage collector будет))

  • @asylbek_miizamov
    @asylbek_miizamov 6 місяців тому +1

    well done )

  • @Alones-c3b
    @Alones-c3b 6 місяців тому

    Спасибо за видео! Ты упомянул двухфазный коммит, про него будет ролик?

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Вряд ли, это уже не моя тема

  • @megasuperlexa2
    @megasuperlexa2 6 місяців тому

    так если сервис отваливается по панике, транзакция зависает?

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Если мы откатываем транзакцию через defer, то не зависнет. Потому что defer выполняется даже в случае паники. Но тут надо быть осторожным, т.к. он не выполнится, к примеру, в случае os.Exit() или log.Fatal(). Или если сам сервер перезагрузился.

  • @VladA-sj9xb
    @VladA-sj9xb 6 місяців тому

    В идеале бы еще сделать sender на основе чтения wal из слота репликации)

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Я похожим в Ламоде занимался, но тот проект так и не запустили(
      Но вообще, это надо в сторону Debezium смотреть, например.

    • @VladA-sj9xb
      @VladA-sj9xb 6 місяців тому

      @@nikolay_tuzov да, если есть возможность им воспользоваться, оптимальный вариант чтобы свои костыли не делать!

  • @kirillbdev
    @kirillbdev 6 місяців тому +10

    говорят он все еще пытается написать все сам, а copilot все еще мешает..

  • @firefizik9307
    @firefizik9307 6 місяців тому

    Брат ты в казахстан переехал ?

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Я в Казахстан вернулся)

    • @firefizik9307
      @firefizik9307 6 місяців тому

      @@nikolay_tuzov а ты в Алмате или в Астане?

  • @profered
    @profered 6 місяців тому

    Было бы круто если бы выложил код или ссылку на репо

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      URL Shortener давно уже выложен на гитхабе, а вот ссылка конкретно на ветку с изменениями из этого ролика: github.com/GolangLessons/url-shortener/tree/outbox

  • @travisbickle7260
    @travisbickle7260 5 місяців тому +2

    У меня точно такой же маленький флаг висит над столом 🔵🟡

  • @pocketpodpopcorn
    @pocketpodpopcorn Місяць тому +1

    шутка про Кафку засчитана

  • @НиколайВикторович-х3г
    @НиколайВикторович-х3г 6 місяців тому +1

    Микросеврвисов *

  • @dimayudin6945
    @dimayudin6945 6 місяців тому

    Капец ты похож на маскота GO 😂

  • @ИванКозлов-ь8ъ
    @ИванКозлов-ь8ъ 6 місяців тому

    И зачем тут 30 сервисов с кафкой. Почему сервис истории не может просто опираться на таблицу транзакций, в которую пишется уже что зачислили, а что списали. Ну слать туда poll-select банальный. То есть быть асинхронным.
    А то получается, хотим писать данные в 2 таблицы двух разных микросервисов. Чтобы первый через кафку во второй сервис пулял сообщения. И о ужас у нас несогласованная транзакция. Надо срочно пойти исправиться, и сделать 3й сервис, который лечит проблемы первого и второго.
    Выкидываем отсюда кафку. Даём доступ второго сервиса до бд первого и нет проблем.
    Они нам рассказывают что микро- сервисы не должны знать про данные друг друга. Мол на то они и микросервисы. Зато потом как манну небесную впаривают "паттерны проектирования", которые возникли просто потому что как костыль на костыль из-за парадигмы микросервисов

  • @AndreiM-x5h
    @AndreiM-x5h 6 місяців тому

    это все классно, но каков шанс, что это принесет больше пользы, чем вреда? 99% вам нужен монолит

  • @slavanikulin8069
    @slavanikulin8069 6 місяців тому

    проблема воркера на тикере в том, что он увеличивает задержку обработки сообщения. Конкретно в вашем примере клиент будет зря триггерить поддержку: он отправил деньги, а в ленту сообщение попадает не сразу. Поэтому он сразу бежит жаловаться.
    В данном случае что делать? Меньше интервал в тикере делать? Тогда база заспамится. Плюс будут лишние запросы в базу скорее всего

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому

      Меньше интервал, плюс обрабатывать батчами. База выдержит, это не проблема.

    • @НиколайВикторович-х3г
      @НиколайВикторович-х3г 6 місяців тому

      ​@@nikolay_tuzovв ролике ты сказал, что у батча свои проблемы, что это за проблемы и как их решить.

    • @nikolay_tuzov
      @nikolay_tuzov  6 місяців тому +1

      Я имел ввиду, что это чуть сложнее в реализации, но не критично. Просто чуть сложнее код получится, и его бует сложнее поддерживать.

    • @xz8928
      @xz8928 3 місяці тому

      Как вариант использовать cdc вместо поллинга

  • @def-any
    @def-any 6 місяців тому +2

  • @Almas-2002
    @Almas-2002 6 місяців тому +3

    Лайк за флаг и годное знание❤