Подтвердить что ты не робот

Каков наилучший способ использования Redis в многопоточной среде Rails? (Puma/Sidekiq)

Я использую Redis в своем приложении, как для очередей Sidekiq, так и для кэширования модели.

Каков наилучший способ подключения Redis к моим моделям, учитывая, что модели, которые будут бить Redis, будут вызваны как из моего веб-приложения (запущенного через Puma), так и из фоновых заданий внутри Sidekiq?

В настоящее время я делаю это в своих инициализаторах:

Redis.current = Redis.new(host: 'localhost', port: 6379)

А затем просто используйте Redis.current.get/Redis.current.set (и подобное) во всем коде...

Это должно быть поточно-безопасным, насколько я понимаю, поскольку клиент Redis выполняет только одну команду за раз, используя монитор.

Теперь у Sidekiq есть свой пул подключений к Redis и рекомендует делать

Sidekiq.redis do |conn|
   conn.get
   conn.set
end

Как я понимаю, это было бы лучше, чем просто использовать Redis.current, потому что у вас нет нескольких рабочих в нескольких потоках, ожидающих друг друга в одном соединении, когда они попадают в Redis.

Однако, как я могу сделать это соединение, которое я получаю от Sidekiq.redis, доступным для моих моделей? (без необходимости передавать его в качестве параметра при каждом вызове метода)

Я не могу установить Redis.current внутри этого блока, так как он глобальный, и я возвращаюсь к каждому, используя одно и то же соединение (плюс переключение между ними случайным образом, что может быть даже небезобезопасным)

Должен ли я сохранить соединение, которое я получаю из Sidekiq.Redis, в локальную переменную Thread и везде использовать эту локальную переменную?

В этом случае, что мне делать в контексте "Puma"? Как установить локальную переменную потока?

Любые мысли об этом очень ценятся.

Спасибо!

4b9b3361

Ответ 1

Для кода приложения используется отдельный пул глобальных соединений. Поместите что-то подобное в ваш инициализатор redis.rb:

require 'connection_pool'
REDIS = ConnectionPool.new(size: 10) { Redis.new }

Теперь в вашем коде приложения вы можете сделать это:

REDIS.with do |conn|
  # some redis operations
end

У вас будет до 10 подключений к вашим сотрудникам puma/sidekiq. Это приведет к повышению производительности, поскольку, как вы правильно заметили, у вас не будет всех потоков, сражающихся за одно соединение Redis.

Все это описано здесь: https://github.com/mperham/sidekiq/wiki/Advanced-Options#connection-pooling