What is Redis?

Redis logo

Redis is an in-memory data structure store used to help building high-performance and scalable web applications, similar to Memcached, but with these main differences:

  • Redis can persist data to disk, making it a kind of NoSQL database, so data won’t disappear when restarting the server. This feature can be optionally disabled.

The persistence feature is interesting, but some applications may be affected if there is some power failure and Redis didn’t have time to persist the latest data. For these cases there is another interesting feature: it can append each command to a log. So if a failure occurs, after restarting Redis it can apply all the commands over the data to get back to the latest state.

Redis can be used as a database, cache system, or a message-queue broker. It can also be used in a server group, using primary-secondary asynchronous replication.

Installation

If you’re using macOS, it’s very easy to install Redis using Homebrew:

$ brew install redis

Then you can start it using this command:

$ redis-server /usr/local/etc/redis.conf

The redis.conf file is where the server is configured.

If you are using Linux, you can use your distribution’s package manager to install it easily.

I will also install the redis-rb gem to deal with Redis from Ruby:

$ gem install redis

Connecting

Let’s use the Redis CLI utility to connect to the server and check the installation:

$ redis-cli

It should display a prompt with the loopback IP address and the port where the server is running. When entering the ping command, the server should respond with PONG:

127.0.0.1:6379> ping
PONG

Yay! The installation is working!

From now on I will switch to the Ruby gem. The commands are the same, but using them as object methods.

Open another terminal tab and fire up irb. Let’s connect to the server:

require "redis"
=> true
redis = Redis.new
=> #<Redis client v3.2.2 for redis://127.0.0.1:6379/0>

You are connected to the server using the default configuration (localhost and port 6379).

Now ping the server:

redis.ping
=> "PONG"

Strings

Redis can store any value in a string using up to 512 MB.

redis.set 'greeting', 'hello'
=> "OK"
redis.get 'greeting'
=> "hello"

Another interesting way to set a string is by assigning an expiry in seconds:

redis.setex 'temp_greeting', 5, 'hi!'
=> "OK"
redis.get 'temp_greeting'
=> "hi!"
# after waiting for more than 5 seconds
redis.get 'temp_greeting'
=> nil

There are lots of commands for strings. I will show a few below:

# Appending
redis.append 'greeting', '!'
=> 6
redis.get 'greeting'
=> "hello!"
# Getting a range
redis.getrange 'greeting', 0, 1
=> "he"
# Getting multiple strings:
redis.set 'farewell', 'goodbye'
=> "OK"
redis.mget 'greeting', 'farewell'
=> ["hello", "goodbye"]
# Incrementing/decrementing:
redis.set 'counter', 1
=> "OK"
redis.incr 'counter'
=> 2
redis.incrby 'counter', 2
=> 4
redis.decr 'counter'
=> 3
redis.decrby 'counter', 2
=> 1

Hashes

A hash is a collection of key-value pairs that is initialized using a series of strings:

# set a hash with some key-values
redis.hmset 'my_city', 'name', 'Barcelona', 'country', 'Spain'
=> "OK"
# add one more key-value
redis.hset 'my_city', 'region', 'Catalonia'
=> true
# get the city name
redis.hget 'my_city', 'name'
=> "Barcelona"
# get name and region
redis.hmget 'my_city', 'name', 'region'
=> ["Barcelona", "Catalonia"]
# get hash contents
redis.hgetall 'my_city'
=> {"name"=>"Barcelona", "country"=>"Spain", "region"=>"Catalonia"}

A few more interesting things we can do with hashes:

# listing keys
redis.hkeys 'my_city'
=> ["name", "country"]
# checking existence of keys
redis.hexists 'my_city', 'name'
=> true
redis.hexists 'my_city', 'province'
=> false
# setting a value to a non-existing key
redis.hsetnx 'my_city', 'weather', 'sunny'
=> true
redis.hsetnx 'my_city', 'weather', 'rainy'
=> false
redis.hget 'my_city', 'weather'
=> "sunny"

Lists

Lists are a series of strings sorted by insertion order. More can be added on the head or on the tail.

redis.rpush 'brands', 'Apple'
=> 1
redis.rpush 'brands', 'Microsoft'
=> 2
redis.rpush 'brands', ['AMD', 'Nvidia']
=> 4
redis.lrange 'brands', 0, 3
=> ["Apple", "Microsoft", "AMD", "Nvidia"]
redis.lpush 'brands', 'Intel'
=> 5
redis.lrange 'brands', 0, 4
=> ["Intel", "Apple", "Microsoft", "AMD", "Nvidia"]

Values can be extracted from the head or from the tail as well:

redis.lpop 'brands'
=> "Intel"
redis.rpop 'brands'
=> "Nvidia"

Sets

Sets are unordered and non-repeating collection of strings.

# remove the brands list we created before
redis.del 'brands'
redis.sadd 'brands', ['Apple', 'Microsoft', 'Intel']
=> 3
redis.smembers 'brands'
=> ["Microsoft", "Apple", "Intel"]
# try to add Apple again
redis.sadd 'brands', 'Apple'
=> true
redis.smembers 'brands'
=> ["Microsoft", "Apple", "Intel"]
# check if some brands are included
redis.sismember 'brands', 'Samsung'
=> false
redis.sismember 'brands', 'Intel'
=> true

Sorted sets

A sorted set sets a score to each member, from the smallest to the greatest score.

redis.zadd 'colors', 1, 'red'
=> true
redis.zadd 'colors', 2, 'green'
=> true
redis.zadd 'colors', 3, 'blue'
=> true
redis.zrange 'colors', 0, 5, with_scores: true
=> [["red", 1.0], ["green", 2.0], ["blue", 3.0]]
# how many members with a score from 0 to 2?
redis.zcount 'colors', 0, 2
=> 2

Conclusion

I have scratched the surface of Redis features, talking about the basic data types and how to use them through the Ruby gem.

There are other interesting features such as messaging, where an instance can create a channel and receive messages from other instances.

Redis is a very useful and efficient piece of software that can be used to enhance our web applications. In fact there are some important gems that use it, like Sidekiq.

--

--

Web Developer. Technical Instructor.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store