Балансировка нагрузки SQL читает при пакетной обработке? - PullRequest
0 голосов
/ 23 апреля 2020

С учетом таблицы SQL с отметками времени. Время от времени приложение App0 делает что-то вроде foreach record in since(certainTimestamp) do process(record); commitOffset(record.timestamp), то есть периодически оно потребляет пакет данных «fre sh», последовательно обрабатывает их и фиксирует успех после каждой записи, а затем просто спит в течение разумного времени (для накопить еще одну партию). Это прекрасно работает с одним экземпляром ... однако как сбалансировать нагрузку на несколько экземпляров?

В точно такой же среде App0 и App1 одновременно конкурируют за данные fre sh. Идея состоит в том, что готовый запрос, выполняемый App0 , не должен накладываться на один и тот же запрос чтения, выполняемый App1, так что они никогда не пытаются обработать один и тот же элемент. Другими словами, мне нужны гарантии на основе SQL, что параллельные запросы чтения возвращают разные данные. Это вообще возможно?

PS Postgres является предпочтительным вариантом.

1 Ответ

1 голос
/ 23 апреля 2020

Описание проблемы довольно расплывчато в отношении того, что App1 должен делать, пока App0 обрабатывает ранее выбранные записи.
В этом ответе я делаю следующие предположения:

  • all Apps каким-то образом знает, что такое последний certainTimestamp, и он одинаков для всех Apps всякий раз, когда они запускают запрос к БД.
  • пока App0 обрабатывает, скажем, 10 записей, которые он обнаружил, когда он начал работать, приходят новые записи. Это означает, что куча новых записей относительно certainTimestamp увеличивается.
  • при запуске App1 (или далее App ) должна обрабатываться только те новые записи по отношению к certainTimestamp, которые еще не обрабатываются другими Apps .
  • пока, если в App произойдет сбой / сбой, незаконченные записи должны быть выбраны при следующем запуске другого App .

This может быть достигнуто путем блокировки записей во многих SQL базах данных.

Один из способов go об этом - использовать

 SELECT ... FOR UPDATE SKIP LOCKED

Этот оператор в сочетании с диапазоном выбора since(certainTimestamp) выбирает и блокирует все записи, соответствующие условию и не являющиеся заблокирован в настоящее время. Каждый раз, когда новый экземпляр App выполняет этот запрос, он получает только «то, что осталось» и может работать над этим.

Это решает проблему «оверлея» или работает на тех же данных.

Осталось только определение и обновление certainTimestamp. Чтобы этот ответ был коротким, я не расскажу об этом go и просто оставляю указатель на ОП, который необходимо должным образом продумать, чтобы избежать ситуаций, когда, например, сохраняется одна запись, которая по какой-то причине не может быть обработана certainTimestamp на постоянном минимуме.

...