redis / redis-rb

A Ruby client library for Redis
MIT License
3.97k stars 1.03k forks source link

Proper documentation on how to setup rails to connect to a redis cluster for session management #1280

Closed darkmakukudo closed 5 months ago

darkmakukudo commented 5 months ago

Hi everyone,

I have tried using redis-rails and redis, but I cannot properly connect to a Redis cluster and alway encountering. 'ConnectionError: MOVED' everytime my application tries to connect and register a new key.

From my understanding redis-rails is not relevant in this case and has no in built support for clustering. A lot of gems also suggested like redis-clustering but documentation wise, it is not clear.

This is how I configure it in my initializer.

` redis_session_servers = ENV['REDIS_CLUTER_NODES']&.split(',') || [] expire_after_hours= ENV.fetch('REDIS_EXPIRE_AFTER', 1).to_i

Rails.application.config.session_store :redis_store, servers: redis_session_servers.map { |server| { url: server, password: ENV['REDIS_PASSWORD'] } }, expire_after: expire_after_hours.hours, key: "key", threadsafe: true`

darkmakukudo commented 5 months ago

@supercaracal-san, I have read in the comment that you are expert on this clustering. Please share if you have a piece of idea on the problem, highly appreciated.

supercaracal commented 5 months ago

Sorry, I'm not familiar with the latest rails. I see a related issue, but I don't know whether we still need a such peripheral gem or not.

I'd say that we can use redis-clustering if we can pass the instance to the setting in a way like a cache store.

https://github.com/rails/rails/blob/d60890c6534d4221dfa821744ebfcc2e8465cc7b/activesupport/lib/active_support/cache/redis_cache_store.rb#L70-L95

supercaracal commented 5 months ago

https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/middleware/session/cache_store.rb

Can we use a session store by using a cache store in rails?

byroot commented 5 months ago

Can we use a session store by using a cache store in rails?

Yes. I recommend using that, and avoiding the redis-store gem.

darkmakukudo commented 5 months ago

Can we use a session store by using a cache store in rails?

@supercaracal, @byroot Does this mean create a custom abstract store and underlying store is redis?

Thanks for your responses.

byroot commented 5 months ago

No you don't need any custom code. Just something like:

config.session_store = ActionDispatch::Session::CacheStore.new(
  cache: ActiveSupport::Cache::RedisCacheStore.new(redis: <build-redis-cluster-client>)
)
darkmakukudo commented 5 months ago

Thank you but sorry do we have a sample to do it in initializer?

Not yet expert on rails, please bear with me

On Wed, May 15, 2024 at 8:36 Jean Boussier @.***> wrote:

No you don't need any custom code. Just something like:

config.session_store = ActionDispatch::Session::CacheStore.new( cache: ActiveSupport::Cache::RedisCacheStore.new(redis: ))

— Reply to this email directly, view it on GitHub https://github.com/redis/redis-rb/issues/1280#issuecomment-2111327985, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADDBBH2BZ2XHSIKGDD443T3ZCKNWDAVCNFSM6AAAAABHWS3E46VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMJRGMZDOOJYGU . You are receiving this because you authored the thread.Message ID: @.***>

byroot commented 5 months ago

https://guides.rubyonrails.org/v7.1/configuring.html#config-session-store

So updated:

config.session_store :cache_store, cache: ActiveSupport::Cache::RedisCacheStore.new(redis: <build-redis-cluster-client>)
darkmakukudo commented 5 months ago

@byroot @supercaracal-san.

I have tried your suggestion: ` redis_cluster_nodes = [ "redis://:host1:6379/0", "redis://:host2:6379/0", "redis://:host3:6379/0", "redis://:host4:6379/0", ]

Rails.application.config.session_store :cache_store, cache: ActiveSupport::Cache::RedisCacheStore.new(url: redis_cluster_nodes)`

Reference: RedisCacheStore API Documentation

I was able to confirm the keys were created fine. Thanks for your help!

supercaracal commented 5 months ago

Redis::Distributed is an implementation for client-side consistent hashing. Redis::Cluster is a client for Redis cluster. These are different.

darkmakukudo commented 5 months ago

@supercaracal-san, How should I properly implement it? Sorry I got confused on the implementation part due to less reference I can find in the web

supercaracal commented 5 months ago

I think the above comment is the answer. And you can see the following document.

https://github.com/redis/redis-rb/blob/master/cluster/README.md

config.session_store :cache_store, cache: ActiveSupport::Cache::RedisCacheStore.new(redis: Redis::Cluster.new(nodes: %w[redis://your-host:6379]))
darkmakukudo commented 5 months ago

@supercaracal Understood, so eventually I need to pass an instance of redis cluster to redis attribute, not the url attribute I shared above. Thanks! I will revise my code.

darkmakukudo commented 5 months ago

Update:

Seems also working fine. I needed to include redis-clustering gem.

config/initializers/session_store.rb

` require 'redis-clustering'

redis_cluster_nodes = [ "redis://:host1:6379/0", "redis://:host2:6379/0", "redis://:host3:6379/0", "redis://:host4:6379/0", ]

redis_cluster = Redis::Cluster.new(nodes: redis_cluster_nodes) Rails.application.config.session_store :cache_store, cache: ActiveSupport::Cache::RedisCacheStore.new(redis: redis_cluster)

Thank you @supercaracal-san