Introduction

Redis is a powerful in-memory key-value database that supports a wide range of data types, including strings, lists, maps, sets, bitmaps, streams, spatial indices, and more.

It is a versatile tool that can be used as a database, cache, or message broker in many different scenarios.

In this article, we will discuss the supported data structures, features, and common use cases of Redis. Please note that we will not cover the setup process in this article, as it is already explained in detail in the Redis documentation here.

Where to Use

Redis is a tool that excels in use cases that demand high performance, scalability, and flexibility in data modeling, such as caching, real-time analytics, messaging, job queuing, and session management.

Where Not to Use

Redis is not well-suited for scenarios that require complex transaction support, more advanced authentication mechanisms with fine-grained permissions, storage of large binary files, or places where high write throughput is essential.

Data Types and Structures

Redis supports a wide variety of data types, each with unique characteristics that make them suitable for different tasks. In this section, we'll discuss the characteristics of each type and their common use cases.

Strings

String is the most basic data type supported by Redis. Anything stored by Redis will be stored as a string.

Strings are best used in situations where you need to store a single value, such as a simple string or serialized data structure or where you can make most of the Time-to-Live functionality.

Strings allow you to perform a variety of operations, such as:

  • Setting or getting the value of a key
  • Incrementing or decrementing an integer value stored in a key
  • Appending or prepending values to a key's existing value
  • Performing bitwise operations on integer values stored in a key

Common use cases include:

  • Caching frequently accessed data, such as HTML fragments or serialized data structures
  • Storing session or user data, such as authentication tokens or user preferences
  • Implementing simple counters or rate limiters, such as tracking the number of API requests or login attempts
  • Storing configuration settings, such as application settings or feature flags

Lists

Lists are data structures that allow you to store a collection of ordered items. The items are sorted based on the order in which they were inserted.

Under the hood, lists are implemented as a doubly-linked list, which means that items can be efficiently inserted or removed from both ends.

Lists are best used in situations where you need to store a collection of ordered items that may change frequently, but where maintaining the order of the items is important.

Lists allow you to perform a wide array of operations, such as:

  • Adding or removing items from both ends of the list
  • Inserting items before or after a given item
  • Retrieving an index-based range of items
  • Trimming the list to a specified range

Common use cases include:

  • Storage of activity logs
  • Storage of message history
  • Implementation of queues or stacks
  • Buffering of data

Sets

Sets are data structures that allow you to store a collection of items. The items are unique and cannot appear in the set more than once.

Under the hood, sets are implemented as a hash table, which provides efficient lookup times for individual items.

Sets are best used in situations where you need to store and retrieve a collection of unique items, but the order in which they were added is not significant.

Sets allow you to perform a variety of operations, such as:

  • Adding or removing items from a set
  • Checking if an item is a member of a set
  • Performing set operations like union, intersection, and difference between sets
  • Retrieving a random item from a set

Common use cases include:

  • Storing list of users who liked or viewed a post
  • Implementing a recommendation system that uses set intersections, unions, and differences to find similar or novel items.

Ordered Sets (ZSets)

Ordered Sets are data structures that allow you to store an ordered collection of items. The items are unique and cannot appear in the set more than once and are sorted based on the score assigned to them. If two items have the same score, they are sorted based on a secondary criteria (typically lexicographically) based on their value.

Under the hood, ordered sets are implemented as a combination of a hash table and a skip list, which provides efficient lookup times for individual items and efficient range queries.

Ordered Sets are best used in situations where you need to store data in a specific order based on an assigned score, and you need fast access to items based on their rank or score.

Ordered Sets allow you to perform a variety of operations, such as:

  • Adding or removing items from an ordered set
  • Checking if an item is a member of an ordered set
  • Retrieving a range of items based on their score
  • Retrieving a range of items based on their rank (position) in the set
  • Retrieving items in descending order by score

Common use cases include:

  • Storage of leaderboards or rankings based on scores
  • Real-time ranking or sorting of data based on a changing score or metric
  • Recommendation systems that use ordered sets to store item ratings or preferences

Hash Tables

Hash Tables are data structures that allow you to store a collection of key-value pairs. Each key is unique and is used to access its corresponding value.

Under the hood, hash tables are implemented as an array of linked lists, where each linked list is referred to as a bucket. Hash functions are used to determine which bucket an entry should be placed in, making it possible to quickly find and access a value based on its key.

Hash Tables are best used in situations where you need to store and retrieve complex objects or structures, or when you need to perform frequent, fast lookups based on a key.

Hash tables allow you to perform a wide range of operations, such as:

  • Adding or updating key-value pairs
  • Retrieving the value associated with a given key
  • Checking if a key exists in the hash table
  • Removing a key-value pair from the hash table
  • Retrieving all keys or values in the hash table
  • Performing bulk operations like incrementing or decrementing values associated with keys

Common use cases include:

  • Storing user or session data
  • Caching frequently accessed data
  • Storing complex objects or structures like configurations or JSON data
  • Indexing data for fast retrieval
  • Implementing rate limiters or other throttling mechanisms

Streams

Streams are data structures that allow you to store a sequence of messages. Each message in a stream is identified by a unique ID, and can contain multiple fields and values.

Streams are best used in situations where you need to process data in real-time, track the state of a system, or build an event-driven architecture.

Redis Streams allow you to perform a variety of operations, such as:

  • Adding messages to a stream
  • Retrieving messages from a stream based on their ID or a range of IDs
  • Grouping messages in a stream by consumer group
  • Acknowledging or claiming ownership of messages in a consumer group
  • Retrieving information about a stream, such as its length or the number of consumers

Common use cases include:

  • Building real-time data pipelines or messaging systems
  • Capturing and processing event data from applications or IoT devices
  • Implementing distributed task queues or job schedulers
  • Storing and processing logs or audit trails in a scalable way.

Bitmaps

Bitmaps are data structures that allow you to store a sequence of bits. Each bit in the sequence can be set to either 0 or 1.

Under the hood, bitmaps are implemented as an array of bits, with each bit representing a binary value of 0 or 1.

Bitmaps are best used in situations where you need to store and manipulate large sets of binary values, such as in applications that deal with user behavior, click tracking, or other similar metrics.

Bitmaps allow you to perform a wide range of operations, such as:

  • Setting or clearing individual bits within the bitmap
  • Performing logical operations on two or more bitmaps, such as AND, OR, and XOR
  • Counting the number of bits set to 1 within the bitmap
  • Retrieving the value of a specific bit within the bitmap

Common use cases for bitmaps include:

  • User behavior tracking, such as tracking which pages a user has visited on a website
  • Click tracking, such as tracking which elements on a webpage a user has clicked on
  • Session tracking, such as tracking which users are currently active on a website
  • Geospatial indexing, such as storing and querying geospatial data represented as a sequence of bits

HyperLogLogs

HyperLogLogs are data structures that allow you to estimate the cardinality of a set by using a small amount of memory. They are particularly useful when you need to count unique items in a large set without storing all of the items themselves.

Under the hood, HyperLogLogs use a probabilistic algorithm to estimate the number of unique items in a set. They work by hashing the items in the set and then counting the number of leading zeros in the resulting binary string. The number of leading zeros is used to estimate the cardinality of the set.

HyperLogLogs are best used in situations where you need to count the number of unique items in a large set, but don't need exact counts. They are particularly useful in cases where you have limited memory available.

HyperLogLogs allow you to perform a variety of operations, such as:

  • Adding items to a HyperLogLog
  • Counting the number of unique items in a HyperLogLog
  • Merging multiple HyperLogLogs into a single HyperLogLog

Common use cases include:

  • Counting the number of unique visitors to a website
  • Counting the number of unique searches on a search engine
  • Counting the number of unique items in a shopping cart
  • Analyzing large data sets to identify unique patterns or trends

Geospatial Indexes

Geospatial indexes are data structures that allow you to store and query location-based data. They use a coordinate system to map locations onto a two-dimensional surface, and allow you to perform spatial queries to find points of interest within a given radius or boundary.

Under the hood, geospatial indexes are implemented as a combination of a geohash and a hash table, which provides efficient lookup times for individual locations and efficient range queries.

Geospatial indexes are best used in situations where you need to store and query location-based data, such as:

  • Mapping applications that need to store and query the locations of points of interest, such as restaurants, shops, and landmarks
  • Logistics applications that need to track the locations of vehicles or packages in real-time
  • Social media applications that need to store and query the locations of users or posts
  • Internet of Things (IoT) applications that need to track the locations of sensors or devices
  • Gaming applications that need to store and query the locations of players or game objects

Features

Redis is a versatile database that offers a variety of features to fit different use cases. In this section, we'll explore some of the most commonly used features of Redis and how they can benefit your application.

Persistence

Redis provides two options for data persistence, RDB and AOF. RDB creates a point-in-time snapshot of your data at specified intervals, while AOF logs each write operation and can be used to rebuild the dataset in case of a crash.

Replication

Redis supports master-slave replication, where changes made to a master instance are automatically propagated to its slave instances. This allows for high availability and scalability, especially with distributed systems.

Clustering

Redis Cluster allows you to shard your data across multiple Redis instances, providing automatic data distribution and failover in case of node failures.

Lua Scripting

Redis allows you to write Lua scripts and execute them within the Redis server. This provides a powerful way to perform complex operations or implement custom functionality.

Pub/Sub Messaging

Redis supports publish/subscribe messaging, where publishers send messages to channels and subscribers receive them. This allows for real-time communication between components of your system.

Transactions

Redis supports transactions, allowing you to group multiple commands into a single atomic operation. This provides a way to perform multiple changes to the dataset in a single step, ensuring consistency.

Security

Redis provides authentication and access control, allowing you to restrict access to your Redis instance.

Client Libraries

Redis provides client libraries for a wide range of programming languages, making it easy to use Redis in your applications.

Bloom Filters

Redis supports Bloom filters, a probabilistic data structure that allows you to test for set membership with a high degree of accuracy while using minimal memory.

Redis provides a full-text search module that allows you to perform fast and efficient searches on your dataset.

Time-To-Live (TTL)

Redis provides a feature called Time-to-Live (TTL) that allows you to set an expiration time for a key. Once the expiration time is reached, the key is automatically deleted by Redis.

Final Thoughts

In conclusion, Redis is a powerful and versatile in-memory data store that serves multiple purposes. It can function as a cache, a fully-fledged database, or even a message broker. What used to serve a very small niche now spans across different areas and excels in them. It is an absolute must-have when it comes to distributed systems and many other applications.