Introduction to Using Redis with Rails

Share this article

Redis is a key-value store that stands out from others, like memcached, in that it has built-in support for data structures like lists, sets, and hashes, and that it can persist data to disk. As such, it is quite useful as both a cache store and as a full-fledged, NoSQL data store. In this article, we will walk through a basic usage example in order to learn how to use Redis within a Rails application.

A Basic Example

Imagine that we have written a simple blogging platform in Rails. We use MySQL as our main database, which is where we store all post content, comments, and user accounts. Let’s say it’s hosted at myrailsblog.com. We get regular traffic directly to posts, thanks to our game-changing social media strategy. There are direct links to these posts all over the internet. The one thing we’re not crazy about is that a URL to a post looks like this: http://myrailsblog.com/321. Aside from the fact that it’s a little ugly and exposes internal ids, we could get better search engine rankings if we implemented slugs for post URLs. We would like the URL to look like this instead: http://myrailsblog.com/using-redis-with-rails. So we decide that from now on, posts are going to have slugs which are auto-generated from the title. We will find posts by slug rather than by id. When a new post is created, it will generate a slug which gets stored in a new column of our posts table. However, our platform allows editing of post titles, and furthermore, we would like authors to be able to customize the slug in case the auto-generated one turns out to be undesirable for any reason. This means that a post URL can change after it has been published. What happens when someone follows an old URL? Rather than awkwardly spitting back a 404, our platform should find the correct post from the old slug. This means that all old slugs need to continue to reference the post. Our natural approach as Rails developers to finding a post by its slug would be to implement something like this: [gist id=”2596145″] The questions start flying when we think about the “what do we do here?” bit. Conceptually, we need to check the :id parameter against the post’s old slugs to see if any of them match. One possible approach would be to create a Slug model, and set Posts to have_many :slugs. However, we can solve this problem a little more elegantly with Redis by mapping slugs to post ids. We can utilize the hash data type to store all slugs under one main key. We will get O(1) lookup time, and we won’t need to migrate the database. In the end, finding a post will look like this instead: [gist id=”2596151″]

Adding Redis

Getting up and running with Redis is as simple as compiling the server, running it, and connecting to it. Downloading and installing Redis is outside the scope of this article, but there are detailed instructions here. Once it has been successfully installed, it can be run by opening a new terminal window and typing redis-server. Now that the server is running, we need to let our app talk to it. First, we need to install the redis gem. With bundler, this is as simple as adding the following to the Gemfile, and running bundle install
: [gist id=”2596166″] We then need to connect to the server and store that connection as a global resource. Additionally, we are going to use the “redis-namespace” gem to organize everything under one application-wide namespace. This will help enormously down the road when multiple apps use the same Redis server. Create a file called “redis.rb” in your config/initializers folder with the following: [gist id=”2596173″] That’s it. We may now issue Redis commands directly to the $redis global variable. Let’s test it out by opening a Rails console and executing the following commands: [gist id=”2596180″] Cool. We can see that the instance methods of the Redis class are the same as the the Redis commands, found here. For simple get/set operations, we can also use array notation: [gist id=”2596185″] Now we are ready to dig a little deeper.

The Slug Model

Fetching

The Slug model has one main purpose: to turn a slug into a post id. We are going to utilize the hash data type in order to avoid polluting the key space with a bunch of slugs. As such, all slugs will reside under the single key, “slugs.” Our first pass at app/models/slug.rb looks like this: [gist id=”2596191″] We simply fetch the value of a specific slug within the hash “slugs.” If the key doesn’t exist, Redis returns nil, which will cause our PostsController to redirect to the root path. Fetching is easy, but we need to be able to store slug/id mappings for this to have any effect.

Storing

Storing values is simple enough as well. We can add a PostObserver to our app with the following code: [gist id=”2596197″] Then, we can modify our Slug model to allow for mapping a slug to a post id: [gist id=”2596202″]

Deleting

The last thing we’ll need to handle is clearing out unused slugs when a post is destroyed. This is because we will need to validate slug uniqueness against all slugs. If a slug points to a post that no longer exists, it will be unusable for future posts. We will revisit this a bit later. As it turns out, deleting slugs presents an interesting problem: how do we know which slugs reference a particular post id? As we have seen, we can easily find a post id given a slug, but we don’t have an easy way to find all slugs that reference a given post id. With our current implementation, we would have to search every slug in the hash and select only those which map to a given post id. It would be a linear-time operation over the total number of slugs, and this is way too slow. This problem is also a good excuse to introduce Redis’s “set” data type. The change is just a bit of simple bookkeeping. Every post id will have an associated set whose members are the slugs which map to that post id. That is, whenever we map a slug to a post id, we will also add that slug to the set of slugs associated with that post id. Moreover, as it is possible to update a slug to point to a different post id, we will first need to remove that slug from the set of slugs for the old post id. Here’s the change: [gist id=”2596216″] Now that we have an efficient way to fetch all slugs for a given post id, we are ready to implement the destroy method: [gist id=”2596220″] We will destroy the mapping from the PostObserver: [gist id=”2596225″]

Uniqueness

As mentioned above, another important aspect of our slug implementation is making sure that a post never has a slug that is mapped to another. In our Post model, we must implement a validation that ensures there is a slug, and that it either does not point to a post id, or it points to the same post we’re currently saving (in the case of an update): [gist id=”2596235″] Note that this means that slug auto-generation needs to take place before validation.

Save Post IDs as Slugs

The last little bit of bookkeeping involves mapping post ids to themselves in Redis. As mentioned above, there are links all over the internet in this format: http://myrailsblog.com/321. After we launch our slug implementation, when someone visits a post URL, we will look for “321” in Redis to see if it maps to a post id. Unless we want all of these old URLs to redirect to the homepage, we’ll need to run a simple script: [gist id=”2596239″] Of course, the other option is to modify the PostController to also find Posts by id in the event that Redis has no mapping, but this is slightly less efficient: [gist id=”2596245″]

All Done

With that, we have successfully implemented slugs for our blogging platform. Even if an old post URL is followed, our platform will still find the correct post. Moreover, we did all of this without needing to modify the database schema, and we get the benefits of the speedy lookup time of Redis. I hope you have found this example useful, and continue to find creative ways to use Redis on your own.

Frequently Asked Questions (FAQs) on Using Redis with Rails

How Do I Install Redis on Rails?

To install Redis on Rails, you first need to install the Redis server on your machine. You can do this by downloading the stable version from the official Redis website. After installing the Redis server, you can then add the ‘redis’ gem to your Gemfile. Run ‘bundle install’ to install the gem. Once the gem is installed, you can start using Redis in your Rails application.

How Can I Use Redis as a Cache Store in Rails?

Rails provides built-in support for Redis cache store. You can set Redis as your cache store by adding the following line to your configuration file: config.cache_store = :redis_cache_store, { url: ENV[‘REDIS_URL’] }. Replace ‘REDIS_URL’ with the URL of your Redis server.

What Are the Benefits of Using Redis with Rails?

Redis provides several benefits when used with Rails. It offers fast in-memory data storage and retrieval, which can significantly improve the performance of your Rails application. Redis also supports various data structures such as strings, hashes, lists, sets, and sorted sets, giving you more flexibility in how you store and manage your data.

How Can I Use Redis for Session Management in Rails?

To use Redis for session management in Rails, you need to set Redis as your session store. You can do this by adding the following line to your configuration file: config.session_store :redis_store, servers: [“redis://localhost:6379/0/session”], expire_after: 90.minutes. This will store session data in Redis and automatically expire the session after 90 minutes.

How Can I Handle Failures When Using Redis with Rails?

When using Redis with Rails, you can handle failures by using the ‘redis-namespace’ and ‘redis-objects’ gems. These gems provide a set of tools and utilities that allow you to handle failures gracefully. For example, you can use the ‘redis-namespace’ gem to isolate your Redis keys in a namespace, preventing key collisions. The ‘redis-objects’ gem allows you to map Redis data types to Ruby objects, making it easier to handle failures.

How Can I Monitor the Performance of Redis in Rails?

You can monitor the performance of Redis in Rails by using the ‘redis-rails’ gem. This gem provides a dashboard that displays various metrics about your Redis server, such as memory usage, number of connections, and command statistics. You can access this dashboard by navigating to ‘/redis/dashboard’ in your Rails application.

How Can I Secure My Redis Server in Rails?

You can secure your Redis server in Rails by setting a password. You can do this by adding the following line to your Redis configuration file: requirepass yourpassword. Replace ‘yourpassword’ with a strong, unique password. Once you’ve set a password, you’ll need to update your Rails configuration to include the password when connecting to the Redis server.

How Can I Use Redis for Background Jobs in Rails?

You can use Redis for background jobs in Rails by using the ‘sidekiq’ gem. Sidekiq uses Redis to store job data, allowing you to process jobs in the background. To use Sidekiq, you need to add the ‘sidekiq’ gem to your Gemfile and run ‘bundle install’. You can then configure Sidekiq to use Redis by adding the following line to your configuration file: Sidekiq.configure_server { |config| config.redis = { url: ‘redis://localhost:6379/0’ } }.

How Can I Scale My Redis Server in Rails?

You can scale your Redis server in Rails by using Redis clustering. Redis clustering allows you to distribute your data across multiple Redis nodes, increasing the capacity and performance of your Redis server. To set up Redis clustering, you need to configure each Redis node to participate in the cluster and then use the ‘redis-trib’ utility to create the cluster.

How Can I Backup and Restore My Redis Data in Rails?

You can backup and restore your Redis data in Rails by using the ‘SAVE’ and ‘RESTORE’ commands. The ‘SAVE’ command creates a snapshot of your Redis data and saves it to disk. You can then use the ‘RESTORE’ command to restore your data from the snapshot. Note that these commands can block your Redis server, so you should use them with caution in a production environment.

Peter BrindisiPeter Brindisi
View Author

Peter Brindisi has been a Ruby on Rails developer since the early days. About a year ago, he decided to leave his native homeland of New York for the shores of Italy to become CTO of frestyl. He thoroughly enjoys finding new and interesting ways to utilize Rails, and loves writing and playing music in his free time.

redis
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week