2015-01-23 4 views
24

Я использую Redis в своем приложении, как для очередей Sidekiq, так и для кэширования модели.Каков наилучший способ использования Redis в многопоточной среде Rails? (Puma/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»? Как установить локальную переменную потока?

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

Спасибо!

ответ

35

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

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

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

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

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

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

+1

Теперь, в этом случае, я бы свой собственный пул соединений для моего кода (в вашем примере, 10 соединений), Sidekiq будет иметь свой собственный пул соединений, которые он будет использоваться для «рабочих работ», и я не буду использовать «Sidekiq.redis» в любом месте своего кода. Это верно? –

+2

Это правильно. –

+0

Это прекрасно работало в сочетании с Puma, Redis и Sidekiq.Мой front-end подписывается на поток событий в одном из моих контроллеров и теперь намного, гораздо более эффективен. Как @DanielMagliola сказал, я никогда не использую Sidekiq.redis в своем коде, вы ссылаетесь на переменную REDIS, доступную для приложения. – Webdevotion

Смежные вопросы