How to use Redis with Rails?
Asked Answered
D

2

10

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

  • How to debug and know if this problem is being caused by redis or not?
  • What is the proper way to use Redis in Rails?
  • Does redis need extra confguration for server (nginx) to work properly in production?

You can comment with the link answering theses questions (fine with me) Thanks in advance

Darien answered 22/6, 2018 at 10:16 Comment(1)
Have you tried following the guide from Rails official site? guides.rubyonrails.org/…Hop
A
22

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.

Amarelle answered 22/6, 2018 at 11:0 Comment(1)
Yes. Use redis-rb or ioredis gem. You also need to make sure that redis is installed in your system or remote host, and port (default 6379) is accessibleAmarelle
C
5

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.

Coreen answered 1/1, 2019 at 12:34 Comment(1)
Nice configuration approach. You can take this one step further and create a config/redis.yml file similar to database.yml, and pull out different details depending on the environment, using Rails.application.config_forMildamilde

© 2022 - 2024 — McMap. All rights reserved.