ПРОБЛЕМА
Я работаю с PostgreSQL v10 + golang, и у меня есть, как мне кажется, очень распространенная проблема SQL:
- У меня есть таблица 'counters', который имеет целочисленные столбцы
current_value
и max_value
. - Строго говоря, однажды
current_value >= max_value
я бы хотел отбросить запрос. - У меня есть несколько стручков Kubernetes, которые длякаждый вызов API может увеличивать
current_value
из той же строки (в худшем случае) в таблице счетчиков на 1 (можно рассматривать как одновременное обновление одной и той же БД с распределенных хостов).
В моей текущей и наивной реализации несколько UPDATES для одной и той же строки естественным образом блокируют друг друга (уровень изоляции «передается на чтение», если это имеет значение).В худшем случае, у меня около 10+ запросов в секунду, которые обновляют одну и ту же строку.Это создает бутылочное горлышко и ухудшает производительность, которую я не могу себе позволить.
ВОЗМОЖНОЕ РЕШЕНИЕ
Я думал о нескольких идеях, чтобы решить эту проблему, но все они жертвуют целостностью или производительностью.Единственный, который поддерживает оба, звучит не очень чисто, для этой, казалось бы, общей проблемы:
Пока счетчик current_value
находится на относительно безопасном расстоянии от max_value
(дельта> 100), отправьтезапрос на обновление канала, который будет сбрасываться примерно каждую секунду работником, который будет агрегировать обновления и запрашивать их сразу.В противном случае (delta <= 100) выполните обновление в контексте транзакции (и столкнитесь с узким местом, но в меньшем количестве случаев).Это будет увеличивать количество запросов на обновление до тех пор, пока предел почти не будет достигнут, эффективно устраняя узкое место. </p>
Это, вероятно, будет работать для решения моей проблемы.Тем не менее, я не могу не думать, что есть более эффективные способы решения этой проблемы.
Я не нашел отличного решения в Интернете, и хотя мой эвристический метод работал бы, он чувствовал себя нечистым и ему не хватало целостности.
Творческие решения приветствуются!
Редактировать:
Благодаря совету @ laurenz-albe я попытался сократить продолжительность обновления до места, где появляется строказаблокирован для фиксации транзакции.Передача всех ОБНОВЛЕНИЙ до конца транзакции, похоже, сделала свое дело.Теперь я могу обрабатывать более 100 запросов в секунду и поддерживать целостность!