Skip to main content

Chapter 1: Redis Basics - Complete In-Memory Database Guide

Authored by syscook.dev

What is Redis?​

Redis (Remote Dictionary Server) is an open-source, in-memory data structure store that can be used as a database, cache, message broker, and streaming engine. This comprehensive guide will teach you everything you need to know about Redis and how to use it effectively in your applications.

Why Learn Redis?​

Redis is essential for modern application development because it:

  • High Performance: In-memory storage provides sub-millisecond response times
  • Versatile Data Types: Strings, hashes, lists, sets, sorted sets, and more
  • Caching: Perfect for application caching and session storage
  • Real-time Features: Pub/Sub messaging and streaming capabilities
  • Scalability: Master-slave replication and clustering support
  • Industry Standard: Used by Twitter, GitHub, Stack Overflow, and many others

Redis (Remote Dictionary Server) is an open-source, in-memory data structure store that can be used as a database, cache, message broker, and streaming engine. It supports various data structures such as strings, hashes, lists, sets, sorted sets, bitmaps, hyperloglogs, and geospatial indexes.

Key Features:​

  • In-Memory Storage: Data stored in RAM for ultra-fast access
  • Data Persistence: Optional persistence to disk
  • Data Structures: Rich set of data types
  • Atomic Operations: All operations are atomic
  • Replication: Master-slave replication
  • Clustering: Horizontal scaling with Redis Cluster
  • Pub/Sub: Publish/Subscribe messaging
  • Lua Scripting: Server-side scripting support

Why Use Redis?​

1. Ultra-Fast Performance​

Redis stores data in memory, providing microsecond latency for read and write operations.

# Example: Basic Redis operations
redis-cli

# Set a key-value pair
127.0.0.1:6379> SET user:1001 "John Doe"
OK

# Get the value
127.0.0.1:6379> GET user:1001
"John Doe"

# Set with expiration (TTL)
127.0.0.1:6379> SETEX session:abc123 3600 "user_data"
OK

# Check TTL
127.0.0.1:6379> TTL session:abc123
(integer) 3598

Performance Benefits:

  • Sub-millisecond response times
  • High throughput (hundreds of thousands of operations per second)
  • Low latency for real-time applications
  • Efficient memory usage

2. Rich Data Structures​

Redis supports multiple data types for different use cases.

# String operations
127.0.0.1:6379> SET counter 0
OK
127.0.0.1:6379> INCR counter
(integer) 1
127.0.0.1:6379> INCRBY counter 5
(integer) 6

# Hash operations
127.0.0.1:6379> HSET user:1001 name "John Doe" email "[email protected]" age 30
(integer) 3
127.0.0.1:6379> HGET user:1001 name
"John Doe"
127.0.0.1:6379> HGETALL user:1001
1) "name"
2) "John Doe"
3) "email"
4) "[email protected]"
5) "age"
6) "30"

# List operations
127.0.0.1:6379> LPUSH tasks "task1" "task2" "task3"
(integer) 3
127.0.0.1:6379> LRANGE tasks 0 -1
1) "task3"
2) "task2"
3) "task1"
127.0.0.1:6379> RPOP tasks
"task1"

# Set operations
127.0.0.1:6379> SADD tags "redis" "database" "cache" "nosql"
(integer) 4
127.0.0.1:6379> SMEMBERS tags
1) "nosql"
2) "cache"
3) "database"
4) "redis"
127.0.0.1:6379> SISMEMBER tags "redis"
(integer) 1

# Sorted Set operations
127.0.0.1:6379> ZADD leaderboard 100 "player1" 200 "player2" 150 "player3"
(integer) 3
127.0.0.1:6379> ZRANGE leaderboard 0 -1 WITHSCORES
1) "player1"
2) "100"
3) "player3"
4) "150"
5) "player2"
6) "200"

3. Caching and Session Storage​

Redis is widely used for caching and session management.

# Cache example
127.0.0.1:6379> SETEX cache:user:1001:profile 300 '{"name":"John","email":"[email protected]"}'
OK
127.0.0.1:6379> GET cache:user:1001:profile
"{\"name\":\"John\",\"email\":\"[email protected]\"}"

# Session storage
127.0.0.1:6379> HSET session:abc123 user_id 1001 login_time "2024-01-15T10:30:00Z" last_activity "2024-01-15T10:35:00Z"
(integer) 3
127.0.0.1:6379> EXPIRE session:abc123 1800
(integer) 1

How Does Redis Work?​

1. Memory Architecture​

Data Storage​

Redis stores all data in memory for maximum performance:

# Check memory usage
127.0.0.1:6379> INFO memory
# Memory
used_memory:1048576
used_memory_human:1.00M
used_memory_rss:2097152
used_memory_rss_human:2.00M
used_memory_peak:1048576
used_memory_peak_human:1.00M
used_memory_peak_perc:100.00%
used_memory_overhead:1038336
used_memory_startup:980736
used_memory_dataset:10240
used_memory_dataset_perc:1.00%

Persistence Options​

Redis offers different persistence mechanisms:

# RDB (Redis Database Backup)
# Automatic snapshots at specified intervals
# Configuration in redis.conf:
# save 900 1 # Save if at least 1 key changed in 900 seconds
# save 300 10 # Save if at least 10 keys changed in 300 seconds
# save 60 10000 # Save if at least 10000 keys changed in 60 seconds

# AOF (Append Only File)
# Logs every write operation
# Configuration in redis.conf:
# appendonly yes
# appendfsync everysec # Sync every second

2. Data Types and Operations​

Strings​

The most basic Redis data type:

# Basic string operations
127.0.0.1:6379> SET mykey "Hello World"
OK
127.0.0.1:6379> GET mykey
"Hello World"
127.0.0.1:6379> STRLEN mykey
(integer) 11
127.0.0.1:6379> APPEND mykey " Redis"
(integer) 17
127.0.0.1:6379> GET mykey
"Hello World Redis"

# Numeric operations
127.0.0.1:6379> SET counter 0
OK
127.0.0.1:6379> INCR counter
(integer) 1
127.0.0.1:6379> INCRBY counter 10
(integer) 11
127.0.0.1:6379> DECR counter
(integer) 10
127.0.0.1:6379> DECRBY counter 5
(integer) 5

# Bit operations
127.0.0.1:6379> SETBIT mykey 7 1
(integer) 0
127.0.0.1:6379> GETBIT mykey 7
(integer) 1
127.0.0.1:6379> BITCOUNT mykey
(integer) 1

Hashes​

Perfect for storing objects:

# Hash operations
127.0.0.1:6379> HSET user:1001 name "John Doe" email "[email protected]" age 30
(integer) 3
127.0.0.1:6379> HGET user:1001 name
"John Doe"
127.0.0.1:6379> HGETALL user:1001
1) "name"
2) "John Doe"
3) "email"
4) "[email protected]"
5) "age"
6) "30"
127.0.0.1:6379> HKEYS user:1001
1) "name"
2) "email"
3) "age"
127.0.0.1:6379> HVALS user:1001
1) "John Doe"
2) "[email protected]"
3) "30"
127.0.0.1:6379> HEXISTS user:1001 name
(integer) 1
127.0.0.1:6379> HDEL user:1001 age
(integer) 1

Lists​

Ordered collections of strings:

# List operations
127.0.0.1:6379> LPUSH tasks "task1" "task2" "task3"
(integer) 3
127.0.0.1:6379> LRANGE tasks 0 -1
1) "task3"
2) "task2"
3) "task1"
127.0.0.1:6379> RPUSH tasks "task4"
(integer) 4
127.0.0.1:6379> LPOP tasks
"task3"
127.0.0.1:6379> RPOP tasks
"task4"
127.0.0.1:6379> LLEN tasks
(integer) 2
127.0.0.1:6379> LINDEX tasks 0
"task2"
127.0.0.1:6379> LINSERT tasks BEFORE "task2" "newtask"
(integer) 3

Sets​

Unordered collections of unique strings:

# Set operations
127.0.0.1:6379> SADD tags "redis" "database" "cache" "nosql"
(integer) 4
127.0.0.1:6379> SMEMBERS tags
1) "nosql"
2) "cache"
3) "database"
4) "redis"
127.0.0.1:6379> SISMEMBER tags "redis"
(integer) 1
127.0.0.1:6379> SCARD tags
(integer) 4
127.0.0.1:6379> SADD tags2 "redis" "python" "web"
(integer) 3
127.0.0.1:6379> SINTER tags tags2
1) "redis"
127.0.0.1:6379> SUNION tags tags2
1) "nosql"
2) "cache"
3) "database"
4) "redis"
5) "python"
6) "web"
127.0.0.1:6379> SDIFF tags tags2
1) "nosql"
2) "cache"
3) "database"

Sorted Sets​

Sets with scores for ordering:

# Sorted Set operations
127.0.0.1:6379> ZADD leaderboard 100 "player1" 200 "player2" 150 "player3"
(integer) 3
127.0.0.1:6379> ZRANGE leaderboard 0 -1 WITHSCORES
1) "player1"
2) "100"
3) "player3"
4) "150"
5) "player2"
6) "200"
127.0.0.1:6379> ZRANK leaderboard "player2"
(integer) 2
127.0.0.1:6379> ZSCORE leaderboard "player1"
"100"
127.0.0.1:6379> ZCOUNT leaderboard 100 200
(integer) 3
127.0.0.1:6379> ZINCRBY leaderboard 50 "player1"
"150"

3. Key Management​

Key Operations​

# Key operations
127.0.0.1:6379> SET mykey "value"
OK
127.0.0.1:6379> EXISTS mykey
(integer) 1
127.0.0.1:6379> TYPE mykey
string
127.0.0.1:6379> EXPIRE mykey 60
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 58
127.0.0.1:6379> PERSIST mykey
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379> DEL mykey
(integer) 1
127.0.0.1:6379> EXISTS mykey
(integer) 0

# Pattern matching
127.0.0.1:6379> SET user:1:name "John"
OK
127.0.0.1:6379> SET user:2:name "Jane"
OK
127.0.0.1:6379> SET user:3:name "Bob"
OK
127.0.0.1:6379> KEYS user:*
1) "user:2:name"
2) "user:1:name"
3) "user:3:name"
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 10
1) "0"
2) 1) "user:2:name"
2) "user:1:name"
3) "user:3:name"

Practical Examples​

1. Simple Caching System​

Basic Cache Implementation​

#!/bin/bash
# cache-example.sh

# Set cache with TTL
redis-cli SETEX cache:user:1001:profile 300 '{"name":"John","email":"[email protected]","age":30}'

# Get from cache
redis-cli GET cache:user:1001:profile

# Check if key exists
redis-cli EXISTS cache:user:1001:profile

# Get TTL
redis-cli TTL cache:user:1001:profile

# Update cache
redis-cli SETEX cache:user:1001:profile 300 '{"name":"John","email":"[email protected]","age":31}'

# Delete from cache
redis-cli DEL cache:user:1001:profile

Cache with Hash Structure​

#!/bin/bash
# hash-cache-example.sh

# Store user data as hash
redis-cli HSET user:1001 name "John Doe" email "[email protected]" age 30 last_login "2024-01-15T10:30:00Z"

# Get specific field
redis-cli HGET user:1001 name

# Get all fields
redis-cli HGETALL user:1001

# Update specific field
redis-cli HSET user:1001 age 31

# Check if field exists
redis-cli HEXISTS user:1001 email

# Set expiration
redis-cli EXPIRE user:1001 3600

2. Session Management​

Session Storage​

#!/bin/bash
# session-example.sh

# Create session
redis-cli HSET session:abc123 user_id 1001 login_time "2024-01-15T10:30:00Z" last_activity "2024-01-15T10:35:00Z" ip_address "192.168.1.100"

# Update last activity
redis-cli HSET session:abc123 last_activity "2024-01-15T10:40:00Z"

# Get session data
redis-cli HGETALL session:abc123

# Set session expiration (30 minutes)
redis-cli EXPIRE session:abc123 1800

# Check session validity
redis-cli TTL session:abc123

# Extend session
redis-cli EXPIRE session:abc123 1800

# Destroy session
redis-cli DEL session:abc123

3. Task Queue System​

Simple Task Queue​

#!/bin/bash
# task-queue-example.sh

# Add tasks to queue
redis-cli LPUSH task_queue "process_order_123"
redis-cli LPUSH task_queue "send_email_456"
redis-cli LPUSH task_queue "generate_report_789"

# Check queue length
redis-cli LLEN task_queue

# Process tasks (FIFO)
redis-cli RPOP task_queue
redis-cli RPOP task_queue
redis-cli RPOP task_queue

# Add priority tasks (high priority at the end)
redis-cli RPUSH task_queue "urgent_task_999"

# Process urgent task first
redis-cli RPOP task_queue

Best Practices​

1. Key Naming Conventions​

# Good: Descriptive and hierarchical
user:1001:profile
session:abc123:data
cache:product:123:details
queue:email:high_priority

# Bad: Unclear or too generic
key1
data
temp

2. Memory Management​

# Set appropriate TTL for temporary data
SETEX cache:user:1001 300 "user_data"

# Use appropriate data types
# For objects: Use hashes instead of JSON strings
HSET user:1001 name "John" email "[email protected]"

# Monitor memory usage
INFO memory

3. Performance Optimization​

# Use pipelines for multiple operations
redis-cli --pipe << EOF
SET key1 value1
SET key2 value2
SET key3 value3
EOF

# Use appropriate data structures
# For counters: Use INCR instead of GET + SET
INCR page_views

# For unique items: Use sets
SADD unique_visitors "user123"

Common Pitfalls and Solutions​

1. Memory Issues​

# ❌ Problem: Memory usage growing indefinitely
# Solution: Set appropriate TTL and monitor memory

# Set TTL for temporary data
SETEX temp_data 3600 "data"

# Monitor memory usage
INFO memory
CONFIG GET maxmemory

2. Key Expiration Issues​

# ❌ Problem: Keys expiring unexpectedly
# Solution: Check TTL and use appropriate expiration

# Check TTL
TTL mykey

# Set appropriate expiration
EXPIRE mykey 3600 # 1 hour

# Use SETEX for immediate expiration
SETEX mykey 3600 "value"

3. Data Type Confusion​

# ❌ Problem: Using wrong data type
# Solution: Choose appropriate data type for use case

# For simple key-value: Use strings
SET user:1001:name "John"

# For objects: Use hashes
HSET user:1001 name "John" email "[email protected]"

# For lists: Use lists
LPUSH tasks "task1" "task2"

# For unique items: Use sets
SADD tags "redis" "database"

Conclusion​

Redis is a powerful, versatile in-memory data store that excels in caching, session management, and real-time applications. By understanding:

  • What Redis is and its key features
  • Why it's valuable for high-performance applications
  • How to use its rich data structures and operations

You can leverage Redis to build fast, scalable applications. Redis's simplicity and performance make it an excellent choice for a wide range of use cases, from simple caching to complex real-time systems.

Next Steps​

  • Practice with different data types and operations
  • Learn about Redis configuration and optimization
  • Move on to Chapter 2: Installation and Configuration

This tutorial is part of the Redis Mastery series by syscook.dev