Re[42]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.02.26 04:30
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, Sinclair, Вы писали:


S>>>>Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual.

S>>·>Т.е. в одной транзакции будут roundtrips между субд и приложением для каждого товара?
S>>Нет, это всё можно записать двумя стейтментами на весь заказ, вообще без раундтрипов.
·>Интересно, как это выглядит?
Примерно так:
BEGIN TRANSACTION;

WITH
-- 1) Лочим заказ и одновременно проверяем, что он в draft
ord AS (
  SELECT o.orderId
  FROM orders o
  WHERE o.orderId = @orderId
    AND o.state = 'draft'
  FOR UPDATE
),

-- Позиции заказа (orderId уже фиксируем через join на ord)
req AS (
  SELECT oi.productId, oi.quantity
  FROM orderItem oi
  JOIN ord ON ord.orderId = oi.orderId
),

-- 2) Лочим строки stock в фиксированном порядке (anti-deadlock)
locked AS (
  SELECT s.productId, s.available
  FROM stock s
  JOIN req r ON r.productId = s.productId
  ORDER BY s.productId
  FOR UPDATE
),

-- 2b) Проверка all-or-nothing:
--  - заказ был draft (ord существует)
--  - для каждой позиции есть строка stock
--  - available хватает для каждой позиции
chk AS (
  SELECT
    (SELECT COUNT(*) FROM ord) AS ord_cnt,
    (SELECT COUNT(*) FROM req) AS need_cnt,
    (SELECT COUNT(*) FROM locked) AS locked_cnt,
    (SELECT COUNT(*)
       FROM locked l
       JOIN req r USING (productId)
      WHERE l.available >= r.quantity
    ) AS ok_cnt
),

-- 3) Обновляем stock только если ВСЁ ОК
upd_stock AS (
  UPDATE stock s
  SET available = s.available - r.quantity,
      reserved  = s.reserved  + r.quantity
  FROM req r, chk
  WHERE s.productId = r.productId
    AND chk.ord_cnt = 1
    AND chk.need_cnt > 0
    AND chk.need_cnt = chk.locked_cnt
    AND chk.need_cnt = chk.ok_cnt
  RETURNING 1
),

-- 4) Меняем статус заказа только если stock реально обновился
upd_order AS (
  UPDATE orders o
  SET state = 'reserved'
  WHERE o.orderId = @orderId
    AND EXISTS (SELECT 1 FROM upd_stock)
  RETURNING o.orderId, o.state
)

SELECT * FROM upd_order;

COMMIT;

·>И что если кто-то закинет заказ на тысячу позиций?
Будет попытка зарезервировать заказ на тысячу позиций.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[43]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 20.02.26 09:41
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>>>Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual.

S>>>·>Т.е. в одной транзакции будут roundtrips между субд и приложением для каждого товара?
S>>>Нет, это всё можно записать двумя стейтментами на весь заказ, вообще без раундтрипов.
S>·>Интересно, как это выглядит?
S>Примерно так:
Ок. Выглядит совсем не так, как в предыдущем примере И вроде нету "заказ распадается на reserved и residual".

S>ORDER BY s.productId
S>FOR UPDATE

S>  UPDATE orders o
S>  RETURNING o.orderId, o.state

Понятно, я безнадёжно отстал от современного sql. Последний раз с sql серьёзно работал лет 10 назад...

S>·>И что если кто-то закинет заказ на тысячу позиций?

S>Будет попытка зарезервировать заказ на тысячу позиций.
Ну вроде речь о МСА шла, а у тебя тут orders и stock в одной транзакции. В МСА же будет некий условный json на резервацию. И тут начнутся проблемы с передачей массивных объектов целиком. Скажем, в kafka размер сообщения жестко ограничивается.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 20.02.2026 10:57 · . Предыдущая версия . Еще …
Отредактировано 20.02.2026 9:52 · . Предыдущая версия .
Re[44]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.02.26 15:36
Оценка:
Здравствуйте, ·, Вы писали:

·>Ок. Выглядит совсем не так, как в предыдущем примере И вроде нету "заказ распадается на reserved и residual".

Простите. Это я что-то начал подтупливать — тяжёлая неделя.
Это у нас код all or nothing и в монолите. Распиливание пополам выглядит в деталях по-другому, но принцип тот же.
·>Понятно, я безнадёжно отстал от современного sql. Последний раз с sql серьёзно работал лет 10 назад...
Это postgres-specific расширение SQL. У MS есть аналог, но с другим синтаксисом.

·>Ну вроде речь о МСА шла, а у тебя тут orders и stock в одной транзакции. В МСА же будет некий условный json на резервацию. И тут начнутся проблемы с передачей массивных объектов целиком. Скажем, в kafka размер сообщения жестко ограничивается.

А, если в MCA то всё ещё проще. Просто отдаём JSON и получаем обратно не такой же объект, как был — и уже при обработке респонса пилим свой order на reserved часть и всё остальное.
Опять же, это распиливание мы можем сделать безо всяких раундтрипов, передав в СУБД список успешно зарезервированных позиций в удобном для неё виде.

Размеры сообщений — это какая-то надуманная проблема. Если кафка не может передать сообщение нужного размера, то нужно выкинуть кафку. Описанный мной способ не полагается на внешние exactly-once системы доставки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[45]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 20.02.26 15:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Ок. Выглядит совсем не так, как в предыдущем примере И вроде нету "заказ распадается на reserved и residual".

S>Простите. Это я что-то начал подтупливать — тяжёлая неделя.
S>Это у нас код all or nothing и в монолите. Распиливание пополам выглядит в деталях по-другому, но принцип тот же.
Да, ты похоже, не на тот вопрос ответил
Я тут речь завёл о том, чтобы распилить транзакцию произвольного размера на множество мелких транзакций фиксированного размера. Тут: https://rsdn.org/forum/design/9057463
Автор: ·
Дата: 17.02 19:55


S>·>Ну вроде речь о МСА шла, а у тебя тут orders и stock в одной транзакции. В МСА же будет некий условный json на резервацию. И тут начнутся проблемы с передачей массивных объектов целиком. Скажем, в kafka размер сообщения жестко ограничивается.

S>А, если в MCA то всё ещё проще. Просто отдаём JSON и получаем обратно не такой же объект, как был — и уже при обработке респонса пилим свой order на reserved часть и всё остальное.
Вопрос о том, как сервис резервации будет взаимодейтсвовать с субд. Получил сервис резервации гигантский объект и пока его жуёт — все остальные должны ждать на блокировках.
Представь себе, есть куча заказов одной популярной сковородки. И большинство заказов из одной позиции именно на эту сковородку. И тут кто-то запулливает гигантский ордер, среди позиций есть эта сковородка. Придётся ждать всем!
Да и вообще неясно в чём преимущество заталкивать всё в одну транзакцию.

S>Опять же, это распиливание мы можем сделать безо всяких раундтрипов, передав в СУБД список успешно зарезервированных позиций в удобном для неё виде.

Как без раундрипов резервировать с успехом/неуспехом каждую позицию?

S>Размеры сообщений — это какая-то надуманная проблема. Если кафка не может передать сообщение нужного размера, то нужно выкинуть кафку.

Тут дело принципиальное — чтобы система была responsive, надо гонять мелкие сообщения. Пока кафка передаёт гигантское сообщение — другим сообщениям придётся ждать своей очереди. Ждут все! А если большое сообщение разбить на мелкие части, то ждать будет только тот, кому надо много.

S> Описанный мной способ не полагается на внешние exactly-once системы доставки.

Тут нужен at-least-once. Да, и при redelivery тоже придётся гигантское сообщение дублировать.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[46]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.02.26 03:41
Оценка:
Здравствуйте, ·, Вы писали:

S>>А, если в MCA то всё ещё проще. Просто отдаём JSON и получаем обратно не такой же объект, как был — и уже при обработке респонса пилим свой order на reserved часть и всё остальное.

·>Вопрос о том, как сервис резервации будет взаимодейтсвовать с субд. Получил сервис резервации гигантский объект и пока его жуёт — все остальные должны ждать на блокировках.
Представления о гигантскости объектов сильно искажены идиотскими реализациями hibernate-based приложений.
Вот в кровавом рич DDD это действительно может стать проблемой: мы начали транзакцию, в которой мееееееееееееееееееедленно такаем складские остатки из базы в апп-сервер, потом их обновляем и меееееееееееееееееееееееееедленно записываем обратно.
Когда код пишется прямыми запросами к СУБД, заказ в тыщу позиций обработается примерно мгновенно. Особенно если данные лежат на современном SSD диске.
Я уже неоднократно сталкивался с тем, что у людей сдвинута интуиция относительно быстродействия СУБД на современном железе. Лет несколько тому кто-то меня уверял, что реляционка захлебнётся на обходе графа из миллиона элементов. Оказалось — нет, даже у лаптопа пред-предыдущего поколения вполне хватает дури обрабатывать такое незаметно для пользователя.

·>Представь себе, есть куча заказов одной популярной сковородки. И большинство заказов из одной позиции именно на эту сковородку. И тут кто-то запулливает гигантский ордер, среди позиций есть эта сковородка. Придётся ждать всем!

О да. Двадцать миллисекунд придётся подождать.
·>Да и вообще неясно в чём преимущество заталкивать всё в одну транзакцию.
Преимущества транзакций — в согласованности. Мы вот взяли и придумали какие-то инварианты, отражающие ограничения бизнеса. Транзакции — единственный способ обеспечить распределённые инварианты (то есть несводимые к ограничениям на 1 элемент данных. Проверки типа "возраст не может быть отрицательным" можно сделать и без транзакций).
Вот есть, к примеру, инвариант "статус относится ко всему заказу — черновик, зарезервирован, оплачен, отгружен, получен и т.п." На этот инвариант полагается масса кода, включая отчёты.
Если мы отменяем этот инвариант, придётся переделывать примерно всё.

S>>Опять же, это распиливание мы можем сделать безо всяких раундтрипов, передав в СУБД список успешно зарезервированных позиций в удобном для неё виде.

·>Как без раундрипов резервировать с успехом/неуспехом каждую позицию?
Язык SQL много чем плох, а вот прекрасен он батч-операциями. Можно отдать ему стейтмент, который поменяет сразу много позиций.
В моём предыдущем примере позиции либо менялись, либо не менялись все разом; небольшое изменение предиката приведёт к тому, что позиции будут резервироваться частично.

·>Тут дело принципиальное — чтобы система была responsive, надо гонять мелкие сообщения. Пока кафка передаёт гигантское сообщение — другим сообщениям придётся ждать своей очереди. Ждут все! А если большое сообщение разбить на мелкие части, то ждать будет только тот, кому надо много.

Повторюсь: если Кафка становится узким местом, нужно выкинуть кафку. В рассматриваемом мной примере никакой Кафки нет, и ждут только те, кто ждёт. Ну и, опять же, в современных сетях всё происходит достаточно шустро. Главное — минимизировать количество раунд-трипов.
·>Тут нужен at-least-once. Да, и при redelivery тоже придётся гигантское сообщение дублировать.
Редчайший случай, заказ на тысячу позиций. Какого характерного размера это "гигантское" сообщение? В непожатом JSON оно будет занимать полсотни килобайт. Семечки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[47]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 22.02.26 11:52
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Вопрос о том, как сервис резервации будет взаимодейтсвовать с субд. Получил сервис резервации гигантский объект и пока его жуёт — все остальные должны ждать на блокировках.

S>Представления о гигантскости объектов сильно искажены идиотскими реализациями hibernate-based приложений.
S>Вот в кровавом рич DDD это действительно может стать проблемой: мы начали транзакцию, в которой мееееееееееееееееееедленно такаем складские остатки из базы в апп-сервер, потом их обновляем и меееееееееееееееееееееееееедленно записываем обратно.
S>Когда код пишется прямыми запросами к СУБД, заказ в тыщу позиций обработается примерно мгновенно. Особенно если данные лежат на современном SSD диске.
S>Я уже неоднократно сталкивался с тем, что у людей сдвинута интуиция относительно быстродействия СУБД на современном железе. Лет несколько тому кто-то меня уверял, что реляционка захлебнётся на обходе графа из миллиона элементов. Оказалось — нет, даже у лаптопа пред-предыдущего поколения вполне хватает дури обрабатывать такое незаметно для пользователя.
Возможно, что мои знания устарели...

S>·>Представь себе, есть куча заказов одной популярной сковородки. И большинство заказов из одной позиции именно на эту сковородку. И тут кто-то запулливает гигантский ордер, среди позиций есть эта сковородка. Придётся ждать всем!

S>О да. Двадцать миллисекунд придётся подождать.
Для FX-трейдинга — задержка 20мс — это production issue. Типичная latency — 0.3мс.

S>·>Да и вообще неясно в чём преимущество заталкивать всё в одну транзакцию.

S>Преимущества транзакций — в согласованности. Мы вот взяли и придумали какие-то инварианты, отражающие ограничения бизнеса. Транзакции — единственный способ обеспечить распределённые инварианты (то есть несводимые к ограничениям на 1 элемент данных. Проверки типа "возраст не может быть отрицательным" можно сделать и без транзакций).
S>Вот есть, к примеру, инвариант "статус относится ко всему заказу — черновик, зарезервирован, оплачен, отгружен, получен и т.п." На этот инвариант полагается масса кода, включая отчёты.
S>Если мы отменяем этот инвариант, придётся переделывать примерно всё.
Так ведь у нас уже есть бизнес-сущность "частично зарезервированный заказ". Поэтому уже неважно — на 99.9% или на 0.1% зарезервированный. Алгоритмы будут те же.

S>>>Опять же, это распиливание мы можем сделать безо всяких раундтрипов, передав в СУБД список успешно зарезервированных позиций в удобном для неё виде.

S>·>Как без раундрипов резервировать с успехом/неуспехом каждую позицию?
S>Язык SQL много чем плох, а вот прекрасен он батч-операциями. Можно отдать ему стейтмент, который поменяет сразу много позиций.
S>В моём предыдущем примере позиции либо менялись, либо не менялись все разом; небольшое изменение предиката приведёт к тому, что позиции будут резервироваться частично.
Батчинг — это уже ортогонально бизнес-требованиям, это нефункциональное требование. Можно батчами обрабатывать входные заявки на резервацию. Они мелкие, зафигачивай сразу кусками по 100 штук (или сколько намерим оптимально, параметр в конфиге). Опять же — суть в том, что размер транзакции фиксированный, а не зависит от данных идущих от юзеров. Это, кстати, сразу бесплатно даёт более эффективную обработку мелких заказов. Ломанулась куча народа покупать по скидке одну сковородку — фигня, будут обработаны пачками максимально быстро.

S>·>Тут дело принципиальное — чтобы система была responsive, надо гонять мелкие сообщения. Пока кафка передаёт гигантское сообщение — другим сообщениям придётся ждать своей очереди. Ждут все! А если большое сообщение разбить на мелкие части, то ждать будет только тот, кому надо много.

S>Повторюсь: если Кафка становится узким местом, нужно выкинуть кафку. В рассматриваемом мной примере никакой Кафки нет, и ждут только те, кто ждёт. Ну и, опять же, в современных сетях всё происходит достаточно шустро. Главное — минимизировать количество раунд-трипов.
Это скорее про поточную, конвеерную обработку. Когда идут потоки сообщений туда-сюда, друг друга не мешая, с минимальными блокировками.

S>·>Тут нужен at-least-once. Да, и при redelivery тоже придётся гигантское сообщение дублировать.

S>Редчайший случай, заказ на тысячу позиций. Какого характерного размера это "гигантское" сообщение? В непожатом JSON оно будет занимать полсотни килобайт. Семечки.
В высокопроизводительных системах — порядка сотен байт.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 22.02.2026 11:53 · . Предыдущая версия .
Re[48]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.02.26 13:13
Оценка:
Здравствуйте, ·, Вы писали:

S>>О да. Двадцать миллисекунд придётся подождать.

·>Для FX-трейдинга — задержка 20мс — это production issue. Типичная latency — 0.3мс.
К счастью, FX-трейдинг — нишевая штука. Нафиг не нужен никому, кроме спекулянтов.
Поэтому рассматривать его требования как основу архитектуры типичного бизнес-приложения не нужно.

S>>Если мы отменяем этот инвариант, придётся переделывать примерно всё.

·>Так ведь у нас уже есть бизнес-сущность "частично зарезервированный заказ". Поэтому уже неважно — на 99.9% или на 0.1% зарезервированный. Алгоритмы будут те же.
Не факт. У нас рассуждения дошли до того, что мы можем разделить заказ на два заказа, одновременно сохраняя базовый инвариант, и обходя ограничения строго-атомарного резервирования.

·>Батчинг — это уже ортогонально бизнес-требованиям, это нефункциональное требование. Можно батчами обрабатывать входные заявки на резервацию.

Нет, вы не поняли. Батчинг тут не про несколько заявок, а про то, что одним стейтментом можно поменять произвольное количество "строк".

·>Это скорее про поточную, конвеерную обработку. Когда идут потоки сообщений туда-сюда, друг друга не мешая, с минимальными блокировками.

Я не умею работать с потоками сообщений. Что такое state мне понятно; вместе со всеми производными понятиями — когерентность, распространение, согласованность, несогласованность.
Что можно сказать про систему на потоках сообщений — да хз. Какие-то сообщения куда-то едут. Соответствует ли такая система каким-нибудь требованиям? Может и соответствует. Как это доказать — непонятно.

S>>Редчайший случай, заказ на тысячу позиций. Какого характерного размера это "гигантское" сообщение? В непожатом JSON оно будет занимать полсотни килобайт. Семечки.

·>В высокопроизводительных системах — порядка сотен байт.
Вы говорите о системах, в которых производительность возведена в кумиры, и ей в жертву приносят всё, включая здравый смысл.
Нет, я не против — мне самому очень нравится архитектура LMAX Disruptor. Но не как задача, которую решают пацаны, а как способ посмотреть на задачу под другим углом.

А в традиционном бизнесе нет нужды опередить соперника на долю наносекунды. Зато важно, чтобы инварианты не разъехались.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 22.02.26 15:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>О да. Двадцать миллисекунд придётся подождать.

S>·>Для FX-трейдинга — задержка 20мс — это production issue. Типичная latency — 0.3мс.
S>К счастью, FX-трейдинг — нишевая штука. Нафиг не нужен никому, кроме спекулянтов.
S>Поэтому рассматривать его требования как основу архитектуры типичного бизнес-приложения не нужно.
Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

S>>>Если мы отменяем этот инвариант, придётся переделывать примерно всё.

S>·>Так ведь у нас уже есть бизнес-сущность "частично зарезервированный заказ". Поэтому уже неважно — на 99.9% или на 0.1% зарезервированный. Алгоритмы будут те же.
S>Не факт. У нас рассуждения дошли до того, что мы можем разделить заказ на два заказа, одновременно сохраняя базовый инвариант, и обходя ограничения строго-атомарного резервирования.
Не понял, что именно "не факт".

S>·>Батчинг — это уже ортогонально бизнес-требованиям, это нефункциональное требование. Можно батчами обрабатывать входные заявки на резервацию.

S>Нет, вы не поняли. Батчинг тут не про несколько заявок, а про то, что одним стейтментом можно поменять произвольное количество "строк".
Это я плохо объяснил. Батчинг — это не требование бизнеса, а механизм повышения перформанса. Это когда запрос в субд на резервацию одной строки и ста строк занимает примерно одно и то же время, т.к. бОльшая часть времени уходит на всякие накладные расходы взаимодействия сервиса резервации и субд.
Следовательно, выгоднее отправлять стейтменты всегда по 100 штук, вне зависимости от того, разные это заказы или один большой.
Т.е. 1000 заказов с 1й позицией и 1 заказ на 1000 позиций потребует 10 батчей с запросами в субд и будет выполняться одинаковое время.
Т.е. вначале разеделяем заказы на мелкие сообщения резервации, сообщения (возможно батчами) засылаем в очередь. Эта очередь потом разгребается (возможно батчами) и ответы отсылаются таким же способом. Ответы резервации аггрерируются в суммарный статус заказа.

S>·>Это скорее про поточную, конвеерную обработку. Когда идут потоки сообщений туда-сюда, друг друга не мешая, с минимальными блокировками.

S>Я не умею работать с потоками сообщений. Что такое state мне понятно; вместе со всеми производными понятиями — когерентность, распространение, согласованность, несогласованность.
S>Что можно сказать про систему на потоках сообщений — да хз. Какие-то сообщения куда-то едут. Соответствует ли такая система каким-нибудь требованиям? Может и соответствует. Как это доказать — непонятно.
Что-то вроде многопоточки, асинхронное программирование?.. Акторы?..

S>>>Редчайший случай, заказ на тысячу позиций. Какого характерного размера это "гигантское" сообщение? В непожатом JSON оно будет занимать полсотни килобайт. Семечки.

S>·>В высокопроизводительных системах — порядка сотен байт.
S>Вы говорите о системах, в которых производительность возведена в кумиры, и ей в жертву приносят всё, включая здравый смысл.
S>Нет, я не против — мне самому очень нравится архитектура LMAX Disruptor. Но не как задача, которую решают пацаны, а как способ посмотреть на задачу под другим углом.
Это по сути как реальность работает на низком уровне. REST-запрос — это два коррелированных сообщения запрос-ответ. А если не ограничиваться этим, то можно слать сообщения куда-то, и как-то реагировать на ответы откуда-то.

S>А в традиционном бизнесе нет нужды опередить соперника на долю наносекунды. Зато важно, чтобы инварианты не разъехались.

Ну в трейдинге тоже ничего разъезжаться не должно. Если разъедится — дело дрянь и серьёзные убытки.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[50]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.02.26 07:01
Оценка:
Здравствуйте, ·, Вы писали:

·>Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

Разработка — она и в африке разработка. А вот проектирование...

·>Не понял, что именно "не факт".

Не факт, что мы смирились с заказами в "смешанном статусе" как с первоклассным состоянием системы.

·>Это я плохо объяснил. Батчинг — это не требование бизнеса, а механизм повышения перформанса. Это когда запрос в субд на резервацию одной строки и ста строк занимает примерно одно и то же время, т.к. бОльшая часть времени уходит на всякие накладные расходы взаимодействия сервиса резервации и субд.

Про этот батчинг я ничего не говорил. Я говорил про семантику объединения операций в ACID-группу и техническую реализацию такой семантики.

·>Следовательно, выгоднее отправлять стейтменты всегда по 100 штук, вне зависимости от того, разные это заказы или один большой.

Не совсем. Если вы попробуете сделать 1 коммит на пачку заказов, то в случае неудачи откатится вся транзакция, включая и те заказы, которым всего хватает.

·>Т.е. вначале разеделяем заказы на мелкие сообщения резервации, сообщения (возможно батчами) засылаем в очередь. Эта очередь потом разгребается (возможно батчами) и ответы отсылаются таким же способом. Ответы резервации аггрерируются в суммарный статус заказа.

Увеличиваем латентность, уменьшаем throughput.

·>Что-то вроде многопоточки, асинхронное программирование?.. Акторы?..

Ага. Вот мы сейчас изобретаем некоторый способ проектировать подобные системы так, чтобы потенциальные лайвлоки ловить не в продакшне, а в дизайн-тайме.
Что-то мне подсказывает, что у вас такого способа нет

·>Это по сути как реальность работает на низком уровне. REST-запрос — это два коррелированных сообщения запрос-ответ. А если не ограничиваться этим, то можно слать сообщения куда-то, и как-то реагировать на ответы откуда-то.

Ну так как только мы перестаём "ограничиваться", так сразу теряем всю привычную REST-семантику с её гарантиями.
·>Ну в трейдинге тоже ничего разъезжаться не должно. Если разъедится — дело дрянь и серьёзные убытки.
В трейдинге инварианты значительно более простые.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[50]: Помогите правильно спроектировать микросервисное при
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 23.02.26 08:19
Оценка: +1
Здравствуйте, ·, Вы писали:

·>Здравствуйте, Sinclair, Вы писали:


S>>>>О да. Двадцать миллисекунд придётся подождать.

S>>·>Для FX-трейдинга — задержка 20мс — это production issue. Типичная latency — 0.3мс.
S>>К счастью, FX-трейдинг — нишевая штука. Нафиг не нужен никому, кроме спекулянтов.
S>>Поэтому рассматривать его требования как основу архитектуры типичного бизнес-приложения не нужно.
·>Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

Разница огромная.
В бизнес-приложениях:
— ключевую роль играет стоимость разработки. Никому не нужно бизнес-приложение, которое стоит дороже самого бизнеса, какое бы крутое это приложение не было. Это линейный фактор.
— не надо соревноваться по скорости с другими системами. Поэтому перформанс в них — гигиенический фактор. Достигая определенного уровня он перестает давать ценность. Зато стоимость каждого следующего улучшения перформанса растет геометрически. Если разницу между 100мс и 20мс никто глазами не заметит, то нет смысла делать даже 20 мс.
— высокие требования к консистентности данных. потерять изменения в бизнес-приложении можно один максимум раз, после второго раза будет уже другой исполнитель. Это must-фактор. Нельзя иметь надежность ниже определенного уровня, в сценариях, которые встречаются на практике.

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

Ну и количество сценариев в бизнес-приложении примерно на порядок или на два меньше, чем в трейдинге. В трейинге по сути один сценарий — приход информации от биржи, а в результате надо выдать пачку ордеров
Re[51]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 23.02.26 10:52
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

S>Разработка — она и в африке разработка. А вот проектирование...
... часть разработки.

S>·>Не понял, что именно "не факт".

S>Не факт, что мы смирились с заказами в "смешанном статусе" как с первоклассным состоянием системы.
Что за смешанный статус? Есть "начали резервацию", "закончили резервацию".

S>·>Это я плохо объяснил. Батчинг — это не требование бизнеса, а механизм повышения перформанса. Это когда запрос в субд на резервацию одной строки и ста строк занимает примерно одно и то же время, т.к. бОльшая часть времени уходит на всякие накладные расходы взаимодействия сервиса резервации и субд.

S>Про этот батчинг я ничего не говорил. Я говорил про семантику объединения операций в ACID-группу и техническую реализацию такой семантики.
Не понятно тогда зачем тебе именно надо в данной задаче объединять операции в одну ACID-группу. Из обоснований я пока заметил лишь: "SQL прекрасен батч-операциями".

S>·>Следовательно, выгоднее отправлять стейтменты всегда по 100 штук, вне зависимости от того, разные это заказы или один большой.

S>Не совсем. Если вы попробуете сделать 1 коммит на пачку заказов, то в случае неудачи откатится вся транзакция, включая и те заказы, которым всего хватает.
Мы вроде рассматриваем вариант "просто добавляется ещё один предикат во where". Неудача и откат тут будет лишь в случае системной ошибки.

S>·>Т.е. вначале разеделяем заказы на мелкие сообщения резервации, сообщения (возможно батчами) засылаем в очередь. Эта очередь потом разгребается (возможно батчами) и ответы отсылаются таким же способом. Ответы резервации аггрерируются в суммарный статус заказа.

S>Увеличиваем латентность, уменьшаем throughput.
Почему уменьшаем?? Для мелких ордеров throughput увеличится засчёт уменьшения числа раундтрипов.

S>·>Что-то вроде многопоточки, асинхронное программирование?.. Акторы?..

S>Ага. Вот мы сейчас изобретаем некоторый способ проектировать подобные системы так, чтобы потенциальные лайвлоки ловить не в продакшне, а в дизайн-тайме.
S>Что-то мне подсказывает, что у вас такого способа нет
Ах, вспомнил. Ты же говорил — workflow, который у тебя уже есть всё равно. Вот его и достаточно. Машина состояний, реагирует на сообщения, меняет внутреннее состояние, посылает сообщения.

S>·>Это по сути как реальность работает на низком уровне. REST-запрос — это два коррелированных сообщения запрос-ответ. А если не ограничиваться этим, то можно слать сообщения куда-то, и как-то реагировать на ответы откуда-то.

S>Ну так как только мы перестаём "ограничиваться", так сразу теряем всю привычную REST-семантику с её гарантиями.
"привычную" — ключевое слово.

S>·>Ну в трейдинге тоже ничего разъезжаться не должно. Если разъедится — дело дрянь и серьёзные убытки.

S>В трейдинге инварианты значительно более простые.
Трейдинг он разный..
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[51]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 23.02.26 11:02
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>·>Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

G>Разница огромная.
G>В бизнес-приложениях:
G>- ключевую роль играет стоимость разработки. Никому не нужно бизнес-приложение, которое стоит дороже самого бизнеса, какое бы крутое это приложение не было. Это линейный фактор.
G>- не надо соревноваться по скорости с другими системами. Поэтому перформанс в них — гигиенический фактор. Достигая определенного уровня он перестает давать ценность. Зато стоимость каждого следующего улучшения перформанса растет геометрически. Если разницу между 100мс и 20мс никто глазами не заметит, то нет смысла делать даже 20 мс.
Пока ВНЕЗАПНО не наступает какая-нибдуь чёрная пятница или новогодние распродажи.

G>- высокие требования к консистентности данных. потерять изменения в бизнес-приложении можно один максимум раз, после второго раза будет уже другой исполнитель. Это must-фактор. Нельзя иметь надежность ниже определенного уровня, в сценариях, которые встречаются на практике.

В трейдинге плюс к этому ещё и штрафы влепят от всяких FCA.

G>В трейдинге другие факторы:

G>- перформанс это must фактор, так как если ты работаешь медленее конкурентов, то ты просто не достигаешь целей.
G>- консистентность вообще можно не учитывать, так как все денные в программе уже устарели
G>- стоимость разработки программы на фоне размера счета — погрешность округления
Ээ, так ещё есть трейдинг по другую сторону баррикады. Например, сама биржа по сути те же заказы (orders) и склад (биржевой стакан). И продать больше — никак нельзя.

G>Ну и количество сценариев в бизнес-приложении примерно на порядок или на два меньше, чем в трейдинге.

"меньше"? Ты хотел сказать "больше"?

G> В трейинге по сути один сценарий — приход информации от биржи, а в результате надо выдать пачку ордеров

Ну вот по обсуждаемой теме есть ещё например portfolio/index трейдинг, где ордера бывают на десяток тысяч позиций. И сложные сценарии price negotiation, споттинг, букинг и т.п.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 23.02.2026 11:04 · . Предыдущая версия .
Re[52]: Помогите правильно спроектировать микросервисное при
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 23.02.26 16:11
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, gandjustas, Вы писали:


G>>·>Так ведь по большому счёту разница невелика с т.з. усилий на разработку. А перформанс, он и в африке перформанс.

G>>Разница огромная.
G>>В бизнес-приложениях:
G>>- ключевую роль играет стоимость разработки. Никому не нужно бизнес-приложение, которое стоит дороже самого бизнеса, какое бы крутое это приложение не было. Это линейный фактор.
G>>- не надо соревноваться по скорости с другими системами. Поэтому перформанс в них — гигиенический фактор. Достигая определенного уровня он перестает давать ценность. Зато стоимость каждого следующего улучшения перформанса растет геометрически. Если разницу между 100мс и 20мс никто глазами не заметит, то нет смысла делать даже 20 мс.
·>Пока ВНЕЗАПНО не наступает какая-нибдуь чёрная пятница или новогодние распродажи.
ВНЕЗАПНО длительность транзакции напрямую не влияет на масштабируемость систем. По сути все распределенные транзакции длительность увеличивают, но также увеличивают и пропускную способность.


G>>- высокие требования к консистентности данных. потерять изменения в бизнес-приложении можно один максимум раз, после второго раза будет уже другой исполнитель. Это must-фактор. Нельзя иметь надежность ниже определенного уровня, в сценариях, которые встречаются на практике.

·>В трейдинге плюс к этому ещё и штрафы влепят от всяких FCA.
За что?

G>>В трейдинге другие факторы:

G>>- перформанс это must фактор, так как если ты работаешь медленее конкурентов, то ты просто не достигаешь целей.
G>>- консистентность вообще можно не учитывать, так как все денные в программе уже устарели
G>>- стоимость разработки программы на фоне размера счета — погрешность округления
·>Ээ, так ещё есть трейдинг по другую сторону баррикады. Например, сама биржа по сути те же заказы (orders) и склад (биржевой стакан). И продать больше — никак нельзя.
В на бирже чуть проще, там же ордеры по одному инструменту по сути уже сериализованы этим самым "стаканом". остается только инженерная задача распределения "стаканов" по сервакам так, чтобы максимизировать надежность и скорость записи (шардирование)

G>>Ну и количество сценариев в бизнес-приложении примерно на порядок или на два меньше, чем в трейдинге.

·>"меньше"? Ты хотел сказать "больше"?
Да, не исправил при переписывании

G>> В трейинге по сути один сценарий — приход информации от биржи, а в результате надо выдать пачку ордеров

·>Ну вот по обсуждаемой теме есть ещё например portfolio/index трейдинг, где ордера бывают на десяток тысяч позиций. И сложные сценарии price negotiation, споттинг, букинг и т.п.
Что из этого не укладывается в сценарий: получить данные от биржи и выдать ордеры?
Re[53]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 23.02.26 16:48
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>·>Пока ВНЕЗАПНО не наступает какая-нибдуь чёрная пятница или новогодние распродажи.

G>ВНЕЗАПНО длительность транзакции напрямую не влияет на масштабируемость систем. По сути все распределенные транзакции длительность увеличивают, но также увеличивают и пропускную способность.
А я и не предлагал распределённые транзакции.

G>>>- высокие требования к консистентности данных. потерять изменения в бизнес-приложении можно один максимум раз, после второго раза будет уже другой исполнитель. Это must-фактор. Нельзя иметь надежность ниже определенного уровня, в сценариях, которые встречаются на практике.

G>·>В трейдинге плюс к этому ещё и штрафы влепят от всяких FCA.
G>За что?
За неимение надёжности определённого уровня при предоставлении финансовых услуг.

G>·>Ээ, так ещё есть трейдинг по другую сторону баррикады. Например, сама биржа по сути те же заказы (orders) и склад (биржевой стакан). И продать больше — никак нельзя.

G>В на бирже чуть проще, там же ордеры по одному инструменту по сути уже сериализованы этим самым "стаканом".
Есть ещё mass order cancel/replace которые валят от market makers.

G>остается только инженерная задача распределения "стаканов" по сервакам так, чтобы максимизировать надежность и скорость записи (шардирование)

Круто наверное это твоё шардирование, особенно когда 95% трафика сыплет на какую-нибудь одну особо популярную сковородку типа EURUSD в первые секунды какого-нибудь очередного market event.

G>>> В трейинге по сути один сценарий — приход информации от биржи, а в результате надо выдать пачку ордеров

G>·>Ну вот по обсуждаемой теме есть ещё например portfolio/index трейдинг, где ордера бывают на десяток тысяч позиций. И сложные сценарии price negotiation, споттинг, букинг и т.п.
G>Что из этого не укладывается в сценарий: получить данные от биржи и выдать ордеры?
Получаем RFQ, прогоняем разные pre-trade проверки, check fail approvals, шлём запрос прайсерам, выбираем лучшую цену, запускаем проверки цены, публикуем цену, обрабатываем client counter, dealer counter, manual intervention, выполняем last-look, выполняем вычисление spot-цены, отсылаем heding, отсылаем booking.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[52]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.02.26 05:35
Оценка:
Здравствуйте, ·, Вы писали:

·>... часть разработки.

Ну, ок
·>Что за смешанный статус? Есть "начали резервацию", "закончили резервацию".
А что у нас между первым и вторым? Когда половина позиций зарезервирована, а половина — нет.
Оплату мы тоже берём по частям?

·>Не понятно тогда зачем тебе именно надо в данной задаче объединять операции в одну ACID-группу. Из обоснований я пока заметил лишь: "SQL прекрасен батч-операциями".

Прекрасность SQL играет тогда, когда мы приняли решение объединять операции. Во время обработки этой ACID-группы нам противопоказаны любые коммуникации, т.к. они ведут к неограниченным задержкам.

·>Мы вроде рассматриваем вариант "просто добавляется ещё один предикат во where". Неудача и откат тут будет лишь в случае системной ошибки.

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

S>>Увеличиваем латентность, уменьшаем throughput.

·>Почему уменьшаем?? Для мелких ордеров throughput увеличится засчёт уменьшения числа раундтрипов.
За счёт накладных расходов на "переоркестрацию" заказов.

·>Ах, вспомнил. Ты же говорил — workflow, который у тебя уже есть всё равно. Вот его и достаточно. Машина состояний, реагирует на сообщения, меняет внутреннее состояние, посылает сообщения.

Набор гарантий для такой машины очень небольшой. Доказать, что в такой системе любой заказ рано или поздно станет либо "отказанным", либо "зарезервированным" — то ещё упражнение.
Даже если отказаться от гарантий liveness и сосредоточиться на safety — что мы никогда не получим дедлок — это представляет собой крайне сложную задачу, для которой нет общего решения.

S>>Ну так как только мы перестаём "ограничиваться", так сразу теряем всю привычную REST-семантику с её гарантиями.

·>"привычную" — ключевое слово.
Именно.

·>Трейдинг он разный..

Ну, когда в руках молоток — всё кажется гвоздями. И это, к сожалению, работает для любого подхода.
Когда в руках reader_writer_lock, то кажется, что невозможно обойтись без захвата/отпускания N*M блокировок, где N — количество позиций заказов в системе, а M — количество стадий конвеера обработки заказа.
Когда в руках — LMAX Disruptor, то кажется, что любую деятельность можно представить как цепочку очередей событий.
И гарантии, которые в одном подходе легко и элегантно обеспечиваются "по построению", в другом подходе представляют собой нетривиально доказываемую (если вообще доказуемую) теорему.
И, соответственно, наоборот.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[53]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 24.02.26 12:16
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Что за смешанный статус? Есть "начали резервацию", "закончили резервацию".

S>А что у нас между первым и вторым? Когда половина позиций зарезервирована, а половина — нет.
S>Оплату мы тоже берём по частям?
Продолжаем резервацию до победного конца. Ты ж сам тут всё описывал: https://rsdn.org/forum/design/9057018
Автор: Sinclair
Дата: 16.02 19:51
. Мой поинт был лишь в том, что нет никакой нужды при таком подходе пытаться всё заталкивать в одну транзакцию произвольного размера.

S>·>Не понятно тогда зачем тебе именно надо в данной задаче объединять операции в одну ACID-группу. Из обоснований я пока заметил лишь: "SQL прекрасен батч-операциями".

S>Прекрасность SQL играет тогда, когда мы приняли решение объединять операции. Во время обработки этой ACID-группы нам противопоказаны любые коммуникации, т.к. они ведут к неограниченным задержкам.
А зачем мы приняли такое решение?

S>·>Мы вроде рассматриваем вариант "просто добавляется ещё один предикат во where". Неудача и откат тут будет лишь в случае системной ошибки.

S>Да, это способ развернуть задачу задом наперёд — когда мы, к примеру, резервируем за одно обращение группу позиций по одному и тому же товару для ряда заказов.
Именно. Когда мы не принимаем такие решения на пустом месте, у нас появляется свобода выбора и простор для различных оптимизаций.

S>>>Увеличиваем латентность, уменьшаем throughput.

S>·>Почему уменьшаем?? Для мелких ордеров throughput увеличится засчёт уменьшения числа раундтрипов.
S>За счёт накладных расходов на "переоркестрацию" заказов.
Эти накладные расходы не требуют сетевых операций или блокировок. А значит практически нулевые, наносекундного диапазона.

S>·>Ах, вспомнил. Ты же говорил — workflow, который у тебя уже есть всё равно. Вот его и достаточно. Машина состояний, реагирует на сообщения, меняет внутреннее состояние, посылает сообщения.

S>Набор гарантий для такой машины очень небольшой. Доказать, что в такой системе любой заказ рано или поздно станет либо "отказанным", либо "зарезервированным" — то ещё упражнение.
S>Даже если отказаться от гарантий liveness и сосредоточиться на safety — что мы никогда не получим дедлок — это представляет собой крайне сложную задачу, для которой нет общего решения.
Почему? Чем это будет отличаться от того, что ты там выше по пунктам расписывал?

S>·>"привычную" — ключевое слово.

S>Именно.

S>·>Трейдинг он разный..

S>Ну, когда в руках молоток — всё кажется гвоздями. И это, к сожалению, работает для любого подхода.
S>Когда в руках reader_writer_lock, то кажется, что невозможно обойтись без захвата/отпускания N*M блокировок, где N — количество позиций заказов в системе, а M — количество стадий конвеера обработки заказа.
S>Когда в руках — LMAX Disruptor, то кажется, что любую деятельность можно представить как цепочку очередей событий.
S>И гарантии, которые в одном подходе легко и элегантно обеспечиваются "по построению", в другом подходе представляют собой нетривиально доказываемую (если вообще доказуемую) теорему.
S>И, соответственно, наоборот.
Как раз не молоток. "Это другое". Если вспомнить историю, то этот подход популяризировался на базе Mechanical Sympathy. То есть не построили красивую абстрактность из мира идей того что "нам привычно" и пошли размахивать как молотком, мол, все наши пользователи пойдут в один сервер, или пусть идут нафик. Вот и HTTP, REST у нас, а потом совершенно ВНЕЗАПНО появились Keep Alive, pipelining, WebSocket, QUIC.
А Mechanical Sympathy — это как раз шаг к тому, как реально работают реальные системы в физическом мире. Потому это и есть дорога к сабж.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 24.02.2026 12:17 · . Предыдущая версия .
Re[54]: Помогите правильно спроектировать микросервисное при
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.02.26 01:53
Оценка:
Здравствуйте, ·, Вы писали:

·>Продолжаем резервацию до победного конца.

Это как раз и означает, что у заказа появляется статус "частично зарезервирован", который нужно учитывать во всех смежных системах.

·>А зачем мы приняли такое решение?

Затем, чтобы обеспечить инварианты, принятые в бизнес-домене.
·>Именно. Когда мы не принимаем такие решения на пустом месте, у нас появляется свобода выбора и простор для различных оптимизаций.
Простор для оптимизаций появляется обычно там, где есть хорошо обоснованная эквивалентность. Вот, в частности, именно за это полюбили реляционную алгебру — она даёт дешёвую возможность строго доказать эквивалентность различных планов запросов, что и открывает простор оптимизациям, недостижимым для альтернативных моделей.

·>Эти накладные расходы не требуют сетевых операций или блокировок. А значит практически нулевые, наносекундного диапазона.

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

·>Почему? Чем это будет отличаться от того, что ты там выше по пунктам расписывал?

Потому что один процесс у вас копает ямы, другой — закапывает. А тот, который должен был сажать деревья, сообщение не получил. Каждый процесс пашет в соответствии со своим ТЗ, и все юнит-тесты проходят, а результата нет.

·>Как раз не молоток. "Это другое". Если вспомнить историю, то этот подход популяризировался на базе Mechanical Sympathy. То есть не построили красивую абстрактность из мира идей того что "нам привычно" и пошли размахивать как молотком, мол, все наши пользователи пойдут в один сервер, или пусть идут нафик. Вот и HTTP, REST у нас, а потом совершенно ВНЕЗАПНО появились Keep Alive, pipelining, WebSocket, QUIC.

·>А Mechanical Sympathy — это как раз шаг к тому, как реально работают реальные системы в физическом мире. Потому это и есть дорога к сабж.
Всякий раз, как я вижу упоминание "как реально работают реальные системы в реальном мире", я чую булшит. Это и про ООП говорили, и даже немножко про фп.
Нам не особо нужно моделировать физический мир. Нам нужно моделировать решение задачи И какой формализм выбрать — state propagation или communicating automata — зависит от того, какие конкретно цели мы преследуем.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[55]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 25.02.26 10:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Продолжаем резервацию до победного конца.

S>Это как раз и означает, что у заказа появляется статус "частично зарезервирован", который нужно учитывать во всех смежных системах.
Не понял где и откуда и зачем.

S>·>А зачем мы приняли такое решение?

S>Затем, чтобы обеспечить инварианты, принятые в бизнес-домене.
Давай конкретно. Вот у тебя там был процесс из 11 пунктов. Что конкретно не будет обеспечиваться, если мы резервацию будем делать построчно?
Вот там у тебя было: "Конкретный SQL тут не так важен — важна его атомарность. Если мы всё же довели транзакцию до конца и получили в сервисе А положительный ответ от СУБД". С этим я не спорю. Я лишь уточнил, что тебе важна атомарность изменения одной строки stock и соответствующей ей строки reservationItems. Но нам не важна атомарность между всеми позициями заказа. Мы просто загоняем каждую позицию в отдельную независимую транзакцию в тупом for-цикле.

S>·>Именно. Когда мы не принимаем такие решения на пустом месте, у нас появляется свобода выбора и простор для различных оптимизаций.

S>Простор для оптимизаций появляется обычно там, где есть хорошо обоснованная эквивалентность. Вот, в частности, именно за это полюбили реляционную алгебру — она даёт дешёвую возможность строго доказать эквивалентность различных планов запросов, что и открывает простор оптимизациям, недостижимым для альтернативных моделей.
Неясно эквивалентность чего к чему подразумеваешь в контексте этого обсуждения.

S>·>Эти накладные расходы не требуют сетевых операций или блокировок. А значит практически нулевые, наносекундного диапазона.

S>Вообще-то требуют, т.к. нам нужно обеспечить какие-то простейшие вещи — например, что кто-то не пытается изменить состав заказа одновременно с тем, как отрабатывает наш код резервирования.
В твоём решении с одной транзакцией это тоже надо делать. Впрочем, это делается просто — изменять состав заказа можно только в определённых статусах заказа. Если статус "резервируется" — менять нельзя, ни в моём случае, ни в твоём. Та же песня.

S>И если для одиночного заказа это "точечная" блокировка, которая не влияет на обработку остальных заказов, то "перегруппировка позиций" уже затрагивает пачку заказов.

Не вижу как именно затрагивает.

S>·>Почему? Чем это будет отличаться от того, что ты там выше по пунктам расписывал?

S>Потому что один процесс у вас копает ямы, другой — закапывает. А тот, который должен был сажать деревья, сообщение не получил. Каждый процесс пашет в соответствии со своим ТЗ, и все юнит-тесты проходят, а результата нет.
По ТЗ процесс закапывающий ямы получает сообщения от процесса-сажателя. С какого бодуна закапыватель чего-то начнёт делать до отсылки сообщения ему?

S>·>Как раз не молоток. "Это другое". Если вспомнить историю, то этот подход популяризировался на базе Mechanical Sympathy. То есть не построили красивую абстрактность из мира идей того что "нам привычно" и пошли размахивать как молотком, мол, все наши пользователи пойдут в один сервер, или пусть идут нафик. Вот и HTTP, REST у нас, а потом совершенно ВНЕЗАПНО появились Keep Alive, pipelining, WebSocket, QUIC.

S>·>А Mechanical Sympathy — это как раз шаг к тому, как реально работают реальные системы в физическом мире. Потому это и есть дорога к сабж.
S>Всякий раз, как я вижу упоминание "как реально работают реальные системы в реальном мире", я чую булшит. Это и про ООП говорили, и даже немножко про фп.
Говорили то, что говоришь и ты: "можно представить". Тут ведь как... можно представить, а ведь можно и не представить!
Взаимодействие в физическом мире происходит посредством посылки сигналов-сообщений. Открой учебник по ТО — там будут signals-events. Произошло событие — полетел фотон. Долетел куда-то — произошло новое событие, фотоны поглотились, излучились новые.

S>Нам не особо нужно моделировать физический мир. Нам нужно моделировать решение задачи И какой формализм выбрать — state propagation или communicating automata — зависит от того, какие конкретно цели мы преследуем.

Вот только реальности всё равно какой формализм ты выбрал — по проводу пойдёт именно коммуникационный сигнал, а не состояние. Тебе придётся построить кривенькую модель организации передачи состояния посредством сигналов. И удивиться потом, чегой-то оно тормозит и состояния разъезжаются...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 25.02.2026 11:12 · . Предыдущая версия . Еще …
Отредактировано 25.02.2026 10:57 · . Предыдущая версия .
Отредактировано 25.02.2026 10:50 · . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.