Атомарно назначать наименее используемый прокси в Redis
Используйте отсортированное множество и короткий скрипт Lua, чтобы выбирать и увеличивать счётчик назначений прокси между воркерами.
Когда несколько воркеров совместно используют пул через Redis, отсортированное множество может реализовать простую политику: выбирать подходящий прокси с наименьшим числом записанных назначений. Храните идентификатор прокси как элемент, а число его назначений как счёт.
Для пула, обслуживающего разрешённые публичные запросы, список бесплатных прокси может дать кандидатов в конечные точки для оценки по правилам допустимости этого пула. Инициализируйте подходящие элементы согласованным начальным числом. Затем сделайте выбор и увеличение одной серверной операцией:
local chosen = redis.call('ZRANGE', KEYS[1], 0, 0)[1]
if not chosen then
return nil
end
redis.call('ZINCRBY', KEYS[1], 1, chosen)
return chosenПередайте ключ отсортированного множества как единственный ключевой аргумент скрипта через интерфейс EVAL вашего клиента Redis. Пустой пул даёт результат null, который приложение должно обработать, не отправляя запрос.
Зачем объединять две команды?
Раздельные чтения и увеличения позволяют двум воркерам увидеть один и тот же минимум до того, как кто-либо его обновит. Redis выполняет скрипт Lua атомарно, поэтому другой воркер не может вставить выбор между чтением и увеличением этого скрипта. Держите скрипт коротким: его выполнение блокирует другую работу Redis.
ZRANGE возвращает наименьший счёт первым; равные счёта разрешаются порядком элементов, а не случайно. ZINCRBY увеличивает счёт выбранного элемента на единицу для следующего назначения.
Определите, что означает счёт
Он считает назначения, включая назначение, сетевой запрос которого позже завершается неудачей. Он не измеряет задержку, успешные запросы или текущую работу. Повторный выбор единственного подходящего элемента по-прежнему возможен; скрипт не резервирует его исключительно.
Поддерживайте допустимость по правилам здоровья и политики пула. Если вы удалите элемент и позже восстановите его, решите, сохранять ли его историческое число. Запуск восстановленного прокси с нуля может сосредоточить на нём назначения, пока он догоняет.
Политика наименьшей одновременности требует другого жизненного цикла, включая завершение и обработку брошенных задач. Не трактуйте этот накопительный счётчик как тот жизненный цикл.