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.
  • Redis can store more data types besides strings, such as Hashes, Lists, Sets and Sorted Sets. I will talk about them later.

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

$ 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

$ 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.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

# 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

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

# 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

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

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.

Computer engineer. Working as a web developer since 2000.

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