Basic Data Types

Introduction

Redis is not just a key-value store where values are plain strings. It gives you five fundamental data structures—String, List, Set, Hash, and Sorted Set—each designed for specific access patterns. This chapter introduces every core type, shows the commands you will use daily, and explains when to choose one over the others. Master these types and you will solve the majority of caching, messaging, and real-time ranking problems you encounter in production.

Prerequisites

  • A running Redis server (see Installation and the Redis CLI)
  • Basic comfort with redis-cli or any Redis client
  • No programming language is required; examples use redis-cli commands

String

The String is the simplest Redis type, but do not let that fool you. It can hold text, integers, floats, or binary data up to 512 MB. Because Redis stores Strings in memory, reads and writes are consistently sub-millisecond.

Setting and Getting Values

MSET and MGET reduce network round trips. When you know you need three keys, fetching them in one command is faster than three separate GET calls.

Atomic Counters

Redis guarantees that INCR, DECR, and their variants are atomic even when hundreds of clients race to update the same key.

Tip

Counter Pattern

Use INCR for rate limiters, inventory counts, and view statistics. Because the operation is atomic, you never need distributed locks for simple increments.

Expiration and Conditional Sets

bash
# Set a key that disappears after 60 seconds
SETEX session:token:abc123 60 "user_id=42"
 
# Set only if the key does not exist (useful for locks)
SETNX lock:report:generation "owner=job_7"
# (integer) 1
 
# SETNX returns 0 if the key already exists
SETNX lock:report:generation "owner=job_8"
# (integer) 0

SETEX combines SET and EXPIRE into one atomic command. SETNX (Set if Not eXists) is the primitive behind distributed locking patterns you will see later in this track.

String Substring and Length Operations

bash
# Append to a string
APPEND log:tail "[INFO] Server started\n"
 
# Get a substring (inclusive, zero-based)
GETRANGE user:1:bio 0 50
 
# Overwrite a portion of a string
SETRANGE user:1:bio 10 " engineer"
 
# Get the length in bytes
STRLEN user:1:bio

List

A List in Redis is an ordered collection of strings, implemented as a doubly linked list. You can push or pop elements from either end in constant time.

Push and Pop

Tip

Queue vs Stack

Use LPUSH + RPOP (or the reverse) for a FIFO queue. Use LPUSH + LPOP for a LIFO stack.

Inspecting Lists

LTRIM is a powerful companion to LPUSH when you want to keep only the most recent N items, such as a user's latest 50 notifications.

Blocking Pop

bash
# Wait up to 30 seconds for an element to become available
BLPOP queue:emails 30

BLPOP and BRPOP block the client until another process pushes data into the list. This is the foundation of a simple, reliable task queue without external message broker software.

Set

A Set is an unordered collection of unique strings. Sets excel at membership tests, deduplication, and mathematical set operations.

Adding, Removing, and Checking Membership

Set Operations

bash
# Find tags shared by two posts
SINTER post:42:tags post:43:tags
 
# Combine tags from two posts
SUNION post:42:tags post:43:tags
 
# Find tags unique to post 42
SDIFF post:42:tags post:43:tags
 
# Store the intersection into a new key
SINTERSTORE common:tags post:42:tags post:43:tags

Tip

Social Graph Pattern

Store each user's friends as a Set. SINTER user:1:friends user:2:friends returns mutual friends instantly.

Hash

A Hash stores field-value pairs inside a single key. It is the Redis equivalent of a plain JavaScript object or a Python dictionary, and it is the most memory-efficient way to represent structured data in Redis.

Field Operations

Atomic Field Updates

bash
# Increment a numeric field atomically
HINCRBY user:42 score 10
# (integer) 10
 
# Increment a float field
HINCRBYFLOAT product:7:metrics rating_avg 0.5

Warning

Avoid the "String JSON" Trap

Developers sometimes store an entire JSON object as a single String: SET user:42 "{\"name\":\"Elena\"}". This forces you to fetch and overwrite the entire blob just to change one field. Use a Hash instead. It keeps memory low and allows per-field updates.

Sorted Set

A Sorted Set (or ZSet) is like a Set where every member has an associated floating-point score. Members are stored in ascending order by score, and no two members can be identical. Sorted Sets are the engine behind leaderboards, priority queues, and time-series windows.

Adding and Scoring

bash
# Add players with their scores
ZADD leaderboard 1500 "alice"
ZADD leaderboard 1200 "bob"
ZADD leaderboard 1800 "carol"
 
# Update a score (adds if new, updates if exists)
ZINCRBY leaderboard 100 "alice"
# "1600"

Range Queries

Counting and Removal

Tip

Time-Series Pattern

Store timestamps as scores and event IDs as members: ZADD events:system 1704067200 "server_restart". Query windows with ZRANGEBYSCORE and automatically expire old entries with ZREMRANGEBYSCORE.

Choosing the Right Type

If you need...UseExample
A simple value, counter, or cache blobStringSession token, page view count
A FIFO queue or activity feedListBackground job queue, recent comments
Unique items with fast membership checksSetTags, IP allowlists, friend lists
Structured objects with per-field accessHashUser profile, product metadata
Ranked data or range queries by scoreSorted SetLeaderboard, priority queue, timeline

FAQ

Can I store nested objects like a Hash inside a Hash?

No. Redis values are flat. If you need nesting, store a JSON string in a String field, or flatten the structure across multiple Hash keys. Alternatively, use a document database such as MongoDB for deeply nested schemas.

What happens if I use LPOP on an empty List?

It returns (nil). If you use the blocking variant BLPOP, the client waits until another process pushes an element or the timeout expires.

Are Set operations like SINTER atomic?

Yes. All Redis commands are atomic because the server is single-threaded. A massive SINTER against huge Sets will block other commands briefly, but the result is always consistent.

**How does Redis store Hashes so efficiently??

Small Hashes (typically under a few hundred entries) are stored with a compact internal encoding called ziplist. When they grow beyond configurable thresholds, Redis converts them to a standard hash table automatically. You rarely need to think about this, but it explains why Hashes beat JSON strings on memory usage.

Can two members in a Sorted Set have the same score?

Yes. When scores tie, Redis sorts members lexicographically by the member name itself. This is deterministic and useful for alphabetical tie-breaking.

Is there a limit to how many elements a List or Set can hold?

Theoretical limits are in the hundreds of millions per key, bounded only by available memory. Practical limits are lower: extremely large keys cause latency spikes during deletion or serialization. Aim to keep individual keys under a few hundred thousand elements when possible.