Redis – Data Structures – Introduction

Now that you have seen how easy it is to setup Redis. Let’s start our exploration journey. Redis is a data structure server, it means you can store data in various different data structures depending upon your requirements. It supports a number of data structures. Some of them are listed below

  • Simple Strings
  • Lists
  • Sets
  • Sorted sets
  • Hashes
  • Bit Arrays
  • HyperLogLogs
  • Streams

To get started quickly on these data structures via the Redis-CLI – I suggest you have a look at this link. It is a very nice read and a quick way to get introduced to Redis data structures via the CLI interface. Personally, I read this to get started as well! Introduces all the data structures- if you just want a quick introduction just read – Redis Strings, Lists, Sets and Hashes. Remaining you can leave them till you need them!

In this blog, in addition to looking at some of the above data structures, we will also look at how to access Redis cache using Scala and Python APIs. Without the API any Redis introduction for data structures will be incomplete. The data structures covered in this are

  • Simple Strings
  • Lists
  • Sets
  • Hashes

An exhaustive list of libraries is available on this link. For the purpose of this tutorial we are using the following Scala and Python libraries

Redis Strings

The most basic of all the Redis data structures is Redis strings. It stores a simple value for a given key. It is a key-value pair. In the previous entry towards the end, we had a quick look at a couple of commands. Let’s quickly recap the Redis-CLI commands

set testkey "Hello World"

Let’s see how we can access this key and also create additional keys using Python and Scala API.

Using Python APIs

For access to Redis via python, you can install the lib using pip command. For more details, you can always refer to the Readme.md on this link

sudo pip install redis

It should result in something like this

Below is the simple python code for getting a value from Redis server

import redis

# Step 1 - Setup a redis client
redisClient = redis.Redis('localhost', 6379)

# Step 2 - Get the "testkey" created via redis-cli
my_test_key = redisClient.get('testkey')

# Step 3 - Print the key
print 'testkey has a value:'+my_test_key

The output is highlighted below

That was simple! 🙂

Using Scala APIs

For Scala, it is equally simple. For all the examples we use sbt to build the code.

Below is build.sbt for all our examples

name := "Redis-Strings"

version := "0.1"

scalaVersion := "2.11.8"

libraryDependencies += "net.debasishg" %% "redisclient" % "3.10"

The Scala code is below

import com.redis._

object RedisStrings {
  def main(args: Array[String]): Unit = {
    //Step 1 - Create a redis client
    val redisClient = new RedisClient("localhost",6379)

    //Step 2  - Get the redis key from RedisServer.
    val myTestKey = redisClient.get("testkey").getOrElse("NULL")

    //Step 3 - Do something with the key
    println(s"testkey has a value:$myTestKey")
  }
}

While returning key from Redis Server the scala library always returns a Scala Option. Hence the use of getOrElse method.

The program output is below with the relevant part of the output highlighted

Redis Lists

The list is a very common data structure and it is also supported by Redis as well. Redis Lists are implemented as linked lists. Hence head and tail operations are time constant.

In this example, we will create a list using a CLI, python code and Scala and see the various operations using different APIs.

Using Redis-CLI

There are various simple Redis-CLI commands for manipulating lists and some of the most used ones are below

  • LPUSH – Pushes the data from the left of the list or the head of the list
  • RPUSH – Pushes the data from the right of the list or the tail of the list
  • LPOP – Pops data from the left of the list or the head of the list
  • RPOP – Pops data from the right of the list or the tail of the list
  • LRANGE – Extracts elements for a given index range. Starting from the left of the list.
  • LLEN – Length of the list
  • DEL – Deletes any Redis data structure

Below are some example of commands

lpush mylist 10 20 30 40 50
lrange mylist 0 -1
lpush mylist 60
lrange mylist 0 -1
rpush mylist 70
lrange mylist 0 -1
rpop mylist

The output of the commands is shown below

Using Python API

Let’s look at the same operations using python API

import redis

# Step 1 - Create redis client
redisClient = redis.Redis("localhost", 6379)

# Step 2 - Create redis client
redisClient.lpush('mylist', 10, 20, 30, 40, 50)

# Stpe 3 - Get a list of elements in the list
print 'LRANGE command:' + ','.join(redisClient.lrange('mylist', 0, -1))

# Step 4 - Add an element to head/left of the list
redisClient.lpush('mylist', '60')

# Step 5 - Get a list of elements in the list
print 'LRANGE command:' + ','.join(redisClient.lrange('mylist', 0, -1))

# Step 6 - Add an element to tail/right of the list
redisClient.rpush('mylist', '70')

# Step 7 - Get a list of elements in the list
print 'LRANGE command:' + ','.join(redisClient.lrange('mylist', 0, -1))

# Step 8 - Pop and element from the list
element = redisClient.rpop('mylist')
print 'RPOP command: ' + element

# Step 9 - Get a list of elements in the list
print 'LRANGE command:' + ','.join(redisClient.lrange('mylist', 0, -1))

The output is highlighted below

Using Scala API

Similar code in scala is below

import com.redis._

object RedisLists {
  def main(args: Array[String]): Unit = {
    val redisClient = new RedisClient("localhost",6379)

    // Step 2 - Create redis client
    redisClient.lpush("mylist",10,20,30,40,50)

    // Stpe 3 - Get a list of elements in the list
    println (redisClient.lrange("mylist",0,-1)
      .get //Option of List is returned.
      .map(_.get)) //Each element inside the list(if present)is also an option

    // Step 4 - Add an element to head/left of the list
    redisClient.lpush("mylist",60)

    // Stpe 5 - Get a list of elements in the list
    println (redisClient.lrange("mylist",0,-1)
      .get //Option of List is returned.
      .map(_.get)) //Each element inside the list(if present)is also an option

    // Step 6 - Add an element to tail/right of the list
    redisClient.rpush("mylist",70)

    // Stpe 7 - Get a list of elements in the list
    println (redisClient.lrange("mylist",0,-1)
      .get //Option of List is returned.
      .map(_.get)) //Each element inside the list(if present)is also an option

    // Step 8 - Pop and element from the list
    val element = redisClient.rpop("mylist").getOrElse("NULL")
    println(s"RPOP command: $element")
  }
}

The output from the above code is below

Redis Hashes

Redis Hashes data structure stores data as a set of key-value pairs and is useful in representing complex objects. There is no limit on the number of key-values into a Redis Hash.

Some of the Redis Hash commands are listed below

  • HMSET – Set Multiple fields stored at key
  • HSET – Set a specific field stored at key
  • HMGET – Returns the values associated with the specified fields in the hash stored at key.
  • HGETALL – Returns all the fields and values stored in the has stored at key as an array
  • HKEYS – Returns all the keys
  • HVALS – Returns all the values stored at key

Using Redis-CLI

hmset emp:10 fname john lname smith dept sales salary 1000
hmset emp:20 fname allen lname tang dept it salary 2000
hset emp:10 manager jim
hset emp:20 manager sally
hgetall emp:10
hmget emp:20 fname

The output of the commands is shown below

Using Python API

Similar code in python is below

import redis

# Step 1 - Create redis client
redisClient = redis.Redis('localhost', 6379)

# Step 2 - Create a dict objects.
emp_10 = dict(fname='john', lname='smith', dept='sales', salary='1000')
emp_20 = dict(fname='allen', lname='tang', dept='it', salary='2000')

# Step 3 - Create a redis hash with the dict objects
redisClient.hmset('emp:10', emp_10)

redisClient.hmset('emp:20', emp_20)

# Step 4 - Add additional key-value pair in the Redis Hash
redisClient.hset('emp:10', 'manager', 'jim')

redisClient.hset('emp:20', 'manager', 'sally')

# Step 5 - Get all key-value pairs for a hash
for k, v in redisClient.hgetall('emp:10').iteritems():
    print 'Key: ' + k + ', Value: ' + v

# Step 6 - Get a specific key-value pair from a hash
print 'First name is: ', redisClient.hmget('emp:10', 'fname')[0]

# Step 7 - Print all the keys of a hash
print 'Print all the keys of a hash'
for k in redisClient.hkeys('emp:10'):
    print 'Key: ' + k

# Step 8 - Print all the values of a hash
print 'Print all the values of a hash'
for v in redisClient.hvals('emp:10'):
    print 'Value: ' + v

The output from the program is below

Using Scala API

Similar code in scala is below

import com.redis._

object RedishHash {
  def main(args: Array[String]): Unit = {

    //Step 1 - Create a redis client
    val redisClient = new RedisClient("localhost",6379)

    //Step 2 - Create a map objects.
    val emp_10 = Map( "fname" -> "john",
                      "lname" -> "smith",
                      "dept"  -> "sales",
                      "salary"-> "1000"
    )

    val emp_20 = Map( "fname" -> "allen",
                      "lname" -> "tang",
                      "dept"  -> "it",
                      "salary"-> "2000"
    )

    //Step 3 - Create a redis hash with the map objects
    if (!redisClient.hmset("emp:10",emp_10))
      println("Error in setting employee id:10")

    if (!redisClient.hmset("emp:20",emp_20))
      println("Error in setting employee id:20")

    //Step 4 - Add additional key-value pair in the Redis Hash
    if (!redisClient.hset("emp:10","manager","jim"))
      println("Manager not set!")

    if (!redisClient.hset("emp:20","manager","sally"))
      println("Manager not set!")

    //Step 5 - Get all key-value pairs for a hash
    redisClient.hgetall1("emp:10")
      .get
      .foreach(x=>println(s"Key:${x._1}, Value:${x._2}"))

    //Step 6 - Get a specific key-value pair from a hash
    redisClient.hmget("emp:10","fname")
      .get
      .foreach(x=>println(s"First name is :${x._2}"))

    //Step 7 - Print all the keys of a hash
    println("Print all the keys of a hash")
    redisClient.hkeys("emp:10")
      .get
      .foreach(x=>println(s"Key: ${x}"))

    //Step 8 - Print all the values of a hash
    println("Print all the values of a hash")
    redisClient.hvals("emp:10")
      .get
      .foreach(x=>println(s"Value: ${x}"))
  }
}

The output from the program is below

This brings us to the end of a long post. Hope you find this post useful. Coming up next. Integrating Redis with Spark!

Leave a Comment