Core Data Types and Internal Structures
Redis supports five primary data structures, each optimized for specific use cases.
Strings
Binary-safe sequences capable of holding text, serialized objects, or binary data like images up to 512MB. They are the foundational type.
SET user:name "Alice"
GET user:name
MSET user:age 30 user:city "NYC"
INCR user:login_count
SETNX user:token "abc123"
Internal: Simple Dynamic String (SDS). Capacity doubles up to 1MB, then grows by 1MB increments.
Lists
Linked lists maintaining insertion order, allowing pushes and pops from both ends. Ideal for message queues.
LPUSH tasks "process_email" "generate_report"
RPOP tasks
LRANGE tasks 0 -1
Internal: Quicklist. Combines ziplists (for small datasets) with doubly linked lists to save pointer memory overhead.
Sets
Unordered collections of unique strings. Provides O(1) complexity for add, remove, and membership checks.
SADD tags "java" "redis" "spring"
SISMEMBER tags "redis"
SINTER tags user_1_tags
Internal: Hash table with null values.
Hashes
Field-value maps, perfect for representing objects.
HSET product:1001 name "Laptop" price 999.99
HGET product:1001 price
HGETALL product:1001
Internal: Ziplist for small structures, Hashtable for larger ones.
Sorted Sets (Zsets)
Unique strings linked to floating-point scores, maintaining automatic ordering. Useful for leaderboards.
ZADD leaderboard 1500 "playerA" 2000 "playerB"
ZRANGE leaderboard 0 -1 WITHSCORES
ZREVRANGEBYSCORE leaderboard +inf -inf
Internal: Hashtable for value-to-score mapping, combined with a Skip List for fast range queries. Skip lists offer efficiency comparable to red-black trees but with simpler implementation.
Publish/Subscribe Messaging
A communication paradigm where senders push messages to channels without knowing subscribers. Subscribers receive messages from subscribed channels in real-time.
# Subscriber Terminal
SUBSCRIBE events:notifications
# Publisher Terminal
PUBLISH events:notifications "System reboot initiated"
Extended Data Types
Bitmaps
Bit-level operations on strings. Treats the string as an array of bits, enabling extreme memory efficiency for boolean states.
SETBIT user:active:20231010 45 1 # User 45 logged in
GETBIT user:active:20231010 45
BITCOUNT user:active:20231010 # Total logins
HyperLogLog
Probabilistic data structure for cardinality estimation (counting unique elements). Uses roughly 12KB regardless of input size, accepting a small standard error.
PFADD unique:visits "ip1" "ip2" "ip3"
PFCOUNT unique:visits
PFMERGE total:visits unique:visits unique:visits_backup
Geospatial
Stores geographic coordinates and provides radius queries and distance calculations.
GEOADD locations 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
GEODIST locations Palermo Catania km
GEORADIUS locations 15 37 100 km
Spring Boot Integration
Include the required starters in your project dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
Define connection parameters in your application configuration.
spring:
data:
redis:
host: 10.0.0.5
port: 6379
password: securePass
timeout: 3000ms
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 2
Configure the RedisTemplate to use JSON serialization.
@Configuration
public class RedisInstanceConfig {
@Bean
public RedisTemplate<String, Object> customRedisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer<Object> Serializer = new Jackson2JsonRedisSerializer<>(Object.class);
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setValueSerializer(Serializer);
template.setHashKeySerializer(stringSerializer);
template.setHashValueSerializer(Serializer);
template.afterPropertiesSet();
return template;
}
}
Use the template for basic operations.
@RestController
@RequestMapping("/api")
public class CacheController {
@Autowired
private RedisTemplate<String, Object> customRedisTemplate;
@GetMapping("/status")
public String fetchStatus() {
customRedisTemplate.opsForValue().set("system:state", "OPERATIONAL");
return (String) customRedisTemplate.opsForValue().get("system:state");
}
}
Transaction Mechanisms
Redis transactions queue commands for sequential, isolated execution using MULTI, EXEC, and DISCARD.
- Command Queuing: MULTI initiates the transaction. Commands are queued but not executed.
- Execution: EXEC processes all queued commands atomically.
- Abandonment: DISCARD clears the queue and exits the transaction.
Error handling differs based on when the error occurs:
- Syntax errors during queuing cause the entire transaction to abort on EXEC.
- Runtime errors (e.g., operating on the wrong type) only fail the specific command; remaining commands still execute. Redis does not support rollbacks.
Locking Strategies
Pessimistic Locking: Assumes conflicts will happen. Resources are locked before modification, blocking others.
Optimistic Locking: Assumes conflicts are rare. Uses WATCH to monitor keys. If a watched key changes before EXEC, the transaction fails. This check-and-set mechanism is native to Redis.
Persistence Strategies
RDB (Redis Database)
Point-in-time snapshots saved to disk. Forks a child process to write data to a temporary file, ensuring the main process avoids I/O operations. Uses Copy-On-Write (COW) for memory efficiency.
- Advantages: Fast recovery, compact file size, excellent for backups.
- Disadvantages: Risk of data loss between snapshots, high memory usage during fork.
AOF (Append Only File)
Logs every write operation sequentially. Upon restart, commands are replayed to rebuild state.
Sync policies:
always: Maximum durability, low performance.everysec: Syncs once per second (default and recommended).no: Delegates syncing to the OS.
AOF files grow over time. BGREWRITEAOF creates an optimized file by rewriting only the minimal commands needed for the current state. Since Redis 4.0, rewriting combines RDB formatting for historic data with AOF incremental logs.
- Advantages: Higher data durability, human-readable log.
- Disadvantages: Larger file size, slower recovery than RDB.
When both are enabled, Redis prioritizes AOF for data recovery due to its superior completeness.
Replication and High Availability
Master-Slave replication enables read/write separation. Masters handle writes; Slaves handle reads and synchronize data.
- Full Synchronization: Occurs on initial connection. The master creates an RDB snapshot and sends it to the slave, followed by command buffering.
- Incremental Propagation: Subsequent writes are streamed continuously to slaves.
Topologies
- Cascading Replication: Slaves act as masters to other slaves, reducing load on the primary master.
- Manual Failover: Promoting a slave to master manually upon master failure.
Sentinel Mode
Automates failover. Sentinel processes monitor master and slave instances. If the master fails, Sentinels vote to promote a slave. Slaves priority is determined by slave-priority, replication offset (data completeness), and RunID.
Cluster Architecture
A decentralized cluster distributes data across multiple nodes. It partitions data using Hash Slots.
- A cluster contains exactly 16,384 slots.
- Keys are assigned to a slot using the formula:
CRC16(key) % 16384. - Each master node handles a subset of these slots.
If a client queries a node that does not own the key's slot, it receives a MOVED redirect. For high availability, every master must have at least one replica. If both a master and its replica fail simultaneously, the slot range becomes unavailable. If cluster-require-full-coverage is set to yes, the entire cluster halts.
Cache Anomalies and Distributed Locking
Cache Penetration
Queries for non-existent data bypass the cache and overload the database.
- Mitigation: Cache null values with short TTLs, implement Bloom Filters to reject invalid queries at the cache layer, or enforce strict access whitelisting.
Cache Breakdown
A highly contested hot key expires, causing a sudden surge of concurrent database requests.
- Mitigation: Preload critical hot keys with indefinite TTLs, or implement a distributed lock so only one thread rebuilds the cache while others wait.
Cache Avalanche
Mass cache expiration occurs simultaneously, overwhelming the database.
- Mitigation: Disperse expiration times by adding randomized jitter to TTLs, deploy multi-tier caching (e.g., Nginx + Redis + Local), or throttle database access using locking mechanisms.
Distributed Locks
In distributed systems, local JVM locks fail to synchronize access across nodes. Distributed locks ensure mutual exclusion across multiple processes and machines.
- Implementation Strategies: Database-level locks, Redis (using SETNX with expiry), or ZooKeeper (using ephemeral nodes).
- Redis offers the highest performance, while ZooKeeper provides the strongest reliability guarantees.