I want really fast caching and hence I am using redis. I think I am doing it wrong and hence am facing issues.
Here is what I am doing everytime I used redis. In my controller file, user.rb
def online?
!Redis.new.get("#{self.auth_token}").nil?
end
Then for checking if users are online or not, I am using this,
@users_ol = User.where(:id => @id).select(&:online?)
This fetches me list of all the users currently online. This works well in localhost but breaks when running on server.
My questions are
You can comment with the link answering theses questions (fine with me) Thanks in advance
You are making redis connection for each controller request. This will be a disaster on scale. Ideally, you should open one connection for one rails instnace. To do that, create config/initializers/redis.rb
redis_host = Rails.application.secrets.redis && Rails.application.secrets.redis['host'] || 'localhost'
redis_port = Rails.application.secrets.redis && Rails.application.secrets.redis['port'] || 6379
# The constant below will represent ONE connection, present globally in models, controllers, views etc for the instance. No need to do Redis.new everytime
REDIS = Redis.new(host: redis_host, port: redis_port.to_i)
See the application secrets part, there I'm specifying the configuration to be used, and exposing the host
and port
for production and other environments in their own secrets. This enables me to have dynamic control of redis host and port based on environment, and fallback to localhost:6379 (Default) on local.
def online?
!Redis.new.get("#{self.auth_token}").nil?
end
should become
def online?
REDIS.get("#{self.auth_token}").present?
end
How to debug and know if this problem is being caused by redis or not?
See the Rails server exception's log to see what breaks and why. Use gem like exception_notification
to send you mails when exception is triggered on different envs.
What is the proper way to use Redis in Rails?
See the initial part of this answer. Make one connection, use Rails secrets or environment variables to expose host, port. Totally depends on how and where you setup Redis instance.
Does redis need extra confguration for server (nginx) to work properly in production?
Doesn't need anything special for nginx. You just have to configure it in your application and make sure you are able to connect.
In production, I am using Kubernetes where the Redis URL is redis://redis:6379/0
.
In my Rails developer environment, in Docker, the Redis URL is also as above but in my Rails on localhost, outside of Docker, the Redis url is redis://localhost:6379
.
He accepted answer makes a good point about setting Redis.new
in the initializer to establish a single connection.
The solution in the accepted answer won't work if you use Rails locally and in Docker in the development environment. The solution for me is to use the code below in my config/initializers/redis.rb file:
redis_url = ENV.fetch("REDIS_URL")
REDIS = Redis.new(url: redis_url)
Then in my controller I use the following code:
REDIS.incr "page hits"
@page_hits = REDIS.get "page hits"
I use .env_file to set REDIS_URL
in Docker and .rbenv-vars
in the parent directory of my Rails application to set REDIS_URL to run Rails on localhost.
For Kubernetes, I set REDIS_URL
in the environment section in my rails_deploy.yaml
file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With