2015-01-23 7 views
24

Używam Redis w mojej aplikacji, zarówno dla kolejek Sidekiq, jak i dla buforowania modelu.Jaki jest najlepszy sposób używania Redis w środowisku wielowątkowych szyn? (Puma/Sidekiq)

Jaki jest najlepszy sposób uzyskania połączenia Redis z moimi modelami, biorąc pod uwagę, że modele, które będą uderzać w Redis, będą wywoływane zarówno z mojej aplikacji sieciowej (pobieranej za pośrednictwem Puma), jak iz pracy w tle w Sidekiq?

Jestem obecnie robi to w moim inicjalizatorów:

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

A potem po prostu użyć Redis.current.get/Redis.current.set (i podobne) w całym kodzie ...

ten powinien być bezpieczny wątku, jak jak rozumiem, ponieważ klient Redis uruchamia tylko jedno polecenie naraz, używając monitora.

Teraz Sidekiq posiada własny basen połączenia do Redis, i zaleca robi

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

Jak rozumiem, to byłoby lepsze niż podejście właśnie stosując Redis.current bo nie masz wielokrotność pracownicy na wielu wątkach czekają na siebie nawzajem na jednym połączeniu, gdy trafią Redis.

Jak jednak udostępnić moim modelom to połączenie, które otrzymam od Sidekiq.redis? (bez konieczności przekazywania go jako parametru w każdym wywołaniu metody)

Nie mogę ustawić biegu Redis.current w tym bloku, ponieważ jest on globalny i wróciłem do wszystkich korzystających z tego samego połączenia (plus przełączanie między ich losowo, co może nawet nie być bezpieczne dla wątków)

Czy powinienem przechowywać połączenie, które otrzymuję od Sidekiq.Redis do zmiennej lokalnej Thread i używać wszędzie tej lokalnej zmiennej wątku?

W takim przypadku, co mam zrobić w kontekście "Puma"? Jak ustawić zmienną lokalną wątku?

Wszelkie przemyślenia na ten temat są bardzo cenne.

Dziękujemy!

Odpowiedz

35

Korzystasz z osobnej globalnej puli połączeń dla swojego kodu aplikacji. Umieścić coś takiego w swoim redis.rb inicjatora:

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

Teraz w kodzie aplikacji w dowolnym miejscu, można to zrobić:

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

Będziesz mieć maksymalnie 10 połączeń do dzielenia się między swoim puma/sidekiq pracowników. Doprowadzi to do lepszej wydajności, ponieważ, jak poprawnie zauważysz, nie wszystkie wątki będą walczyć o jedno połączenie Redis.

Wszystko to jest udokumentowane tutaj: https://github.com/mperham/sidekiq/wiki/Advanced-Options#connection-pooling

+1

Teraz, w tym przypadku, że mam własną puli połączeń dla mojego kodu (w przykładzie 10 połączeń), Sidekiq będzie mieć własną puli połączeń, które użyje do swojej "pracy robotniczej" i nie zamierzam używać "Sidekiq.redis" w moim kodzie. Czy to jest poprawne? –

+2

To prawda. –

+0

To działało pięknie w połączeniu z Puma, Redis i Sidekiq.Mój front-end subskrybuje strumień wydarzeń w jednym z moich kontrolerów i jest teraz znacznie bardziej wydajny. Tak jak powiedział @DanielMagliola, nigdy nie używam Sidekiq.redis w moim kodzie, odwołujesz się do zmiennej REDIS, która jest dostępna w całej aplikacji. – Webdevotion

Powiązane problemy