Prev Next

Database / REDIS

1. What is a Redis key? 2. What is Redis? 3. What is the purpose of the EXPIRE command? 4. List few Redis Datatypes. 5. Advantages of Redis. 6. What is a Redis Sorted Set? 7. What is a Redis Hash used for? 8. What programming languages does Redis support? 9. Explain Replication in Redis. 10. What is a Redis Set data type used for? 11. Explain about REDIS security. 12. What is the purpose of the INCR command? 13. What is a Redis Stream? 14. Expand REDIS. 15. Define a Redis Bitmap? 16. In which language Redis is developed? 17. What is the purpose of Redis Pub/Sub? 18. Difference between SET and MSET command in REDIS. 19. Explain LPUSH command in REDIS. 20. What are Redis transactions? 21. Limitations of REDIS. 22. What is RDB persistence in Redis? 23. REDIS is fast, but is it also durable? 24. What is AOF persistence in Redis? 25. What is the purpose of the SELECT command in Redis? 26. Difference between Memcached and REDIS. 27. What is the purpose of the TTL command? 28. What is SADD command in REDIS? 29. Define eviction policies in Redis? 30. Mention few LIST operations in REDIS. 31. Mention Spring Boot Drivers for REDIS. 32. What is Redis Sentinel used for? 33. Explain about redisson client for redis. 34. What is Redis Cluster? 35. How do you connect to Redis using the CLI? 36. What is a Cache Penetration Problem? 37. Why is Redis often faster than a traditional relational database for caching? 38. What is Valkey, and how does it relate to Redis? 39. How I/O Multiplexing Works in Redis? 40. What is the difference between RDB and AOF persistence? 41. How does Redis achieve high throughput with a mostly single-threaded design? 42. Why should you configure an eviction policy for a Redis instance used as a cache? 43. How does Redis Cluster shard data across nodes? 44. When should you use Redis Sentinel instead of Redis Cluster? 45. What happens when a Redis master fails in a Sentinel-managed setup? 46. Explain the execution flow of a Redis transaction using MULTI/EXEC? 47. How can you optimize Redis memory usage for large datasets? 48. How do you troubleshoot high memory usage in a Redis instance? 49. Why is the maxmemory-policy setting important for a cache-only Redis deployment? 50. Explain the lifecycle of a key with a TTL set in Redis? 51. How does Redis handle atomicity for multi-key operations? 52. What is the difference between a Redis List and Sorted Set for queues? 53. How do you implement a distributed lock using Redis? 54. How does Redis Streams support consumer groups? 55. Which is better and why: Redis Pub/Sub or Redis Streams for event delivery? 56. How do you integrate Redis as a session store in a web application? 57. Explain the internal working of Redis's hash table resizing (rehashing)? 58. How do you configure Redis persistence for a production deployment? 59. What is the difference between Redis Cluster and client-side sharding? 60. How does Redis support Lua scripting for atomic operations? 61. When would you choose Redis Streams over a message broker like Kafka? 62. How do you secure Redis access using ACLs? 63. Why should the KEYS command be avoided in production? 64. How do you configure Redis for cache-aside pattern usage? 65. Explain the execution flow of a Redis Cluster request with a MOVED redirection? 66. How does Redis handle replication lag between a master and its replicas? 67. Why doesn't Redis guarantee strong consistency by default across replicas? 68. How do you mitigate a Cache Avalanche in a Redis-backed system? 69. What is the difference between Redis's diskless replication and disk-based replication?
Could not find what you were looking for? send us the question and we would be happy to answer your question.

1. What is a Redis key?

A key is the unique string identifier used to store and retrieve a value in Redis — every piece of data in Redis, regardless of its type (string, hash, list, set, and so on), is addressed by exactly one key, the same way a variable name addresses a value in a program.

SET user:1001:name "Alex"
GET user:1001:name

Keys are binary-safe strings, so they can technically contain any bytes, but in practice teams adopt a consistent naming convention — commonly colon-separated segments like user:1001:name — to keep related keys organized and scannable. Redis has no built-in concept of "folders" or namespaces beyond this naming convention, so key design is entirely up to the application, and a poorly thought-out key scheme is a common source of operational pain as a dataset grows.

What identifies a value stored in Redis?
Does Redis enforce a folder or namespace structure for keys?

2. What is Redis?

Redis is an open source in-memory data structure store which can be used as a database and/or a cache and message broker.

NoSQL Key/Value Store.

Supports Multiple data structures.

Built in Replication.

3. What is the purpose of the EXPIRE command?

EXPIRE attaches a time-to-live to an existing key, after which Redis automatically removes it — useful for data that should only be valid temporarily, like a session token, a rate-limit counter, or a cached query result that shouldn't be served stale forever.

SET session:abc123 "user-data"
EXPIRE session:abc123 3600   # expires in 3600 seconds (1 hour)
TTL session:abc123            # check remaining time-to-live

Related commands round out TTL management: PEXPIRE sets the TTL in milliseconds for finer granularity, EXPIREAT/PEXPIREAT set an absolute expiration timestamp instead of a relative duration, and PERSIST removes a key's TTL entirely, making it permanent again. A key's TTL is also cleared if the key is overwritten with a plain SET (unless the KEEPTTL option is used), which is a common source of confusion when a value update unexpectedly makes a previously-expiring key permanent.

What does the EXPIRE command do to a key?
What can unexpectedly clear a key's TTL if you're not careful?

4. List few Redis Datatypes.

Redis supports,

  • Strings,
  • Lists,
  • Sets,
  • Sorted Sets,
  • Hashes,
  • Bitmaps,
  • Hyperlogs,
  • and Geospatial indexes.

5. Advantages of Redis.

  • Very Flexible.
  • No Schema and column names.
  • Very fast, can perform around 110K Set per second and 81K GETS per second.
  • Rich Datatype support,
  • command level Atomic Operation,
  • Caching & Disk Persistence.

6. What is a Redis Sorted Set?

A Sorted Set (ZSET) stores unique members the same way a plain Set does, but pairs each member with a floating-point score, and Redis automatically keeps the whole collection ordered by that score — giving you a structure that's simultaneously a unique-membership set and an ordered ranking, without needing to re-sort anything yourself.

ZADD leaderboard 1500 "alex"
ZADD leaderboard 2200 "sam"
ZRANGE leaderboard 0 -1 WITHSCORES   # returns members in ascending score order
ZRANK leaderboard "alex"              # returns alex's rank (0-indexed)

Because Redis maintains this order internally using a skip list plus a hash table, range queries by score or by rank (ZRANGE, ZRANGEBYSCORE) and rank lookups (ZRANK) are efficient even on large sets, which is exactly what makes Sorted Sets the natural fit for leaderboards, priority queues, and time-ordered event feeds where the score is often a timestamp.

What distinguishes a Sorted Set from a plain Redis Set?
What is a Sorted Set commonly used for?

7. What is a Redis Hash used for?

A Hash stores a set of field-value pairs under a single key, similar to a small object or a row in a table — instead of serializing an entire object into one string value, a Hash lets you store and update individual fields of that object directly.

HSET user:1001 name "Alex" age "30" email "alex@example.com"
HGET user:1001 name
HGETALL user:1001
HINCRBY user:1001 age 1

The practical benefit over storing a JSON-encoded string is field-level access: updating just the age field via HSET or HINCRBY doesn't require reading, deserializing, modifying, and rewriting the entire object, which matters both for network efficiency and for avoiding lost updates if multiple clients touch different fields of the same record concurrently. Hashes are commonly used to represent an entity like a user profile, a product, or a configuration set, where individual attributes are read or updated independently of each other.

What is the main advantage of a Hash over storing an object as a single JSON string?
Which command atomically increments a numeric field within a Hash?

8. What programming languages does Redis support?

REDIS supports most of the programming languages including Java, C#, Python, Scala, C++, R, PHP and many more.

9. Explain Replication in Redis.

Redis supports simple master to slave replication. When a relationship is established, data from the master is replicated to the slave.

10. What is a Redis Set data type used for?

A Set stores an unordered collection of unique strings — no duplicates are allowed, and there's no concept of order or position the way a List has. Its core value is fast membership testing and set algebra: checking whether an item exists, and combining multiple sets via union, intersection, or difference.

SADD tags:post123 "redis" "database" "nosql"
SISMEMBER tags:post123 "redis"     # membership check, O(1)
SINTER tags:post123 tags:post456    # intersection of two sets
SCARD tags:post123                  # count of members

Typical use cases include tagging (a post's set of tags), tracking unique visitors or unique events (adding a user ID to a set naturally de-duplicates), and relationship queries like "users who like both A and B" via SINTER. Because membership checks and set operations run in close to constant or linear time relative to set size rather than requiring a full scan, Sets are a common choice whenever the core question is "is X in this collection" or "what do these two collections have in common."

What guarantee does a Redis Set provide about its members?
Which command finds the common members between two sets?

11. Explain about REDIS security.

Redis is designed to be accessed by trusted clients.

REDIS can be restricted to certain interfaces.

Data encryption not supported and hence do not allow external access/internet exposure.

12. What is the purpose of the INCR command?

INCR atomically increments the integer value stored at a key by 1, returning the new value — and because it's atomic, it's safe to call concurrently from many clients without a race condition, unlike a naive "read the current value, add 1, write it back" sequence performed in application code.

SET pageviews:home 0
INCR pageviews:home        # 1
INCRBY pageviews:home 5    # 6
DECR pageviews:home        # 5
INCRBYFLOAT price 2.50     # for floating-point increments

This atomicity is the entire point: two clients calling INCR on the same key at the same moment are guaranteed to each get a distinct, correctly-incremented result, with no lost updates — a property that would require explicit locking to replicate safely if the increment were instead implemented as separate GET and SET calls. This makes INCR the standard building block for counters, rate limiters, and unique ID generation in Redis-backed applications.

Why is INCR safe to call concurrently from many clients, unlike a manual read-modify-write?
What is INCR commonly used to build?

13. What is a Redis Stream?

A Stream is an append-only log data structure, similar in spirit to a Kafka topic, where each entry gets a unique, time-ordered ID and holds a set of field-value pairs. Unlike Pub/Sub, entries persist in the stream and can be read by multiple independent readers at their own pace, including readers that connect after an entry was added.

XADD events * sensor "temp-1" reading "72.5"
XRANGE events - +                # read all entries
XLEN events                       # entry count

Each entry ID (like 1691425200000-0) encodes a millisecond timestamp plus a sequence number, which is what gives Streams their strict, gap-free ordering. Streams support both simple sequential reading and, through consumer groups, coordinated parallel processing across multiple readers — making them Redis's answer to durable, replayable event log use cases that a Set, List, or Pub/Sub channel isn't designed to handle well on its own.

How does a Redis Stream differ from Pub/Sub in terms of message persistence?
What does a Redis Stream entry ID encode?

14. Expand REDIS.

Redis stands for REmote DIctionary Server.

15. Define a Redis Bitmap?

A Bitmap isn't a separate data type in Redis — it's a way of treating an ordinary String value as a compact array of individual bits, addressed by offset, using dedicated bit-level commands. Because a String can hold up to 512MB, a single key can represent billions of individual boolean flags extremely compactly.

SETBIT user:1001:active_days 5 1    # mark day 5 as active
GETBIT user:1001:active_days 5      # check day 5
BITCOUNT user:1001:active_days       # count how many bits are set

The classic use case is tracking a large number of boolean states per entity extremely cheaply — whether a user was active on each day of the year (365 bits = under 46 bytes), feature-flag membership across millions of users, or approximate presence tracking. BITCOUNT and bitwise operations like BITOP AND/OR let you answer questions like "how many users were active on both day 5 and day 6" across huge populations using a handful of fast, memory-efficient operations rather than scanning individual records.

What underlying data type does a Redis Bitmap actually use?
Why are Bitmaps considered memory-efficient for tracking many boolean flags?

16. In which language Redis is developed?

Redis is developed using ANSI C and mostly used for cache solution and session management. It creates unique keys for store values.

17. What is the purpose of Redis Pub/Sub?

Pub/Sub lets clients broadcast messages on named channels to any number of subscribers listening at that moment, without Redis storing the message anywhere — it's a pure, ephemeral fire-and-forget messaging mechanism, not a durable queue.

# subscriber
SUBSCRIBE notifications

# publisher, from a different client
PUBLISH notifications "New order received"

If no client is subscribed to a channel when a message is published, that message is simply lost — there's no backlog a late-joining subscriber can catch up on, which is the key difference from a Redis Stream. This makes Pub/Sub well suited to real-time notifications where only currently-connected clients need to know (like pushing a live update to open browser tabs), and poorly suited to anything where a message must be reliably delivered even to a consumer that wasn't listening at the exact moment it was sent.

What happens to a Pub/Sub message if no client is subscribed when it's published?
What kind of use case is Pub/Sub well suited to?

18. Difference between SET and MSET command in REDIS.

SET command creates one key-value pair while using MSET command, multiple key-value pairs can be created.

19. Explain LPUSH command in REDIS.

LPUSH inserts all the specified values at the head of the list stored at key. If the key does not exist, it is created as an empty list before performing the push operations. When key holds a value that is not a list, an error is returned.

Usage: LPUSH key value [value ...]

redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LRANGE mylist 0 -1
1) "Hello"
2) "World"
redis> 

20. What are Redis transactions?

A Redis transaction bundles multiple commands so they execute as a single, uninterrupted sequence — no other client's commands can be interleaved in the middle of a transaction once it starts executing, which is what gives Redis transactions their isolation guarantee.

MULTI
SET account:1:balance 100
DECRBY account:1:balance 20
INCRBY account:2:balance 20
EXEC

MULTI begins queuing subsequent commands rather than executing them immediately; EXEC runs the entire queued batch atomically, back to back; DISCARD cancels a queued transaction before it runs. Redis transactions differ from typical relational-database transactions in one important way: there's no mid-transaction rollback for a command that fails at runtime (like a type error) — the rest of the queued commands still execute, and only commands with syntax errors caught at queue time prevent EXEC from running at all. WATCH adds optimistic locking on top, aborting the transaction if a watched key changes before EXEC, which is the standard pattern for implementing check-then-act logic safely.

What guarantee does MULTI/EXEC provide for the commands inside it?
What does the WATCH command add to a Redis transaction?

21. Limitations of REDIS.

REDIS is single threaded.

It has got limited client support for consistent hashing.

It has significant overhead for persistence.

It cannot be deployed widely.

22. What is RDB persistence in Redis?

RDB (Redis Database) persistence works by taking a point-in-time snapshot of the entire in-memory dataset and writing it to a single compact binary file on disk, either on a configured schedule or on demand. Because it's a full snapshot rather than a running log, restarting from an RDB file is fast — Redis just loads one file back into memory.

# redis.conf
save 900 1      # snapshot if at least 1 key changed in 900 seconds
save 300 10      # snapshot if at least 10 keys changed in 300 seconds

BGSAVE   # trigger a snapshot in the background, non-blocking

The trade-off is the gap between snapshots: any writes that happened after the last successful snapshot are lost if Redis crashes before the next one completes, so RDB alone offers weaker durability than a continuously-appended log. BGSAVE forks a child process to write the snapshot so the main Redis process keeps serving requests during the save, but that fork itself briefly duplicates memory pages (via copy-on-write), which is a real operational consideration on memory-constrained instances with very large datasets.

What does RDB persistence actually save to disk?
What data can be lost if Redis crashes using RDB-only persistence?

23. REDIS is fast, but is it also durable?

No. Redis compromises with durability to enhance the speed. In Redis, in the case of system failure or crash, it writes to disk but may fall behind and lose the data which is not stored.

24. What is AOF persistence in Redis?

AOF (Append Only File) persistence logs every write operation to a file as it happens, in the order it was executed, rather than periodically snapshotting the whole dataset. Recovering from an AOF file means replaying that log of commands from the start to rebuild the exact dataset state.

# redis.conf
appendonly yes
appendfsync everysec   # fsync to disk roughly once per second

The appendfsync setting controls the durability/performance trade-off directly: always fsyncs after every write (safest, slowest), everysec fsyncs about once per second (a common middle-ground default, risking at most ~1 second of writes on a crash), and no lets the OS decide when to flush (fastest, least durable). Because a command-by-command log would grow indefinitely otherwise, Redis periodically performs AOF rewriting, compacting the log into the minimal set of commands needed to reproduce the current dataset, which keeps the file from growing unbounded while preserving the stronger durability AOF offers over RDB snapshots alone.

What does AOF persistence log, as opposed to RDB's snapshot approach?
What does appendfsync=everysec trade off compared to appendfsync=always?

25. What is the purpose of the SELECT command in Redis?

Redis supports multiple numbered logical databases within a single server instance (16 by default, indexed 0-15), and SELECT switches the current connection's active database to a given index, scoping subsequent commands to just that database's keyspace.

SELECT 1
SET debug:flag "on"     # stored in database 1, not database 0
SELECT 0
GET debug:flag           # returns nil; that key lives in database 1

It's a lightweight way to logically separate data within one Redis instance — for example, keeping a test dataset in database 1 while production data stays in database 0 — without running multiple Redis processes. It's worth knowing the real limitations, though: numbered databases share the same memory pool and the same persistence configuration, offer no per-database access control on their own, and are explicitly unsupported in Redis Cluster mode, which only exposes database 0. For genuine multi-tenant isolation with independent resource limits or access control, separate Redis instances or key-prefixing conventions are generally the better-supported approach.

What does the SELECT command change for the current connection?
What is a key limitation of numbered databases as an isolation mechanism?

26. Difference between Memcached and REDIS.

Memcached.REDIS.
Memcached is multi-threaded. Redis is single threaded.
Memcached only does caching information. Redis does caching information and also supports persistence and replication.
Memcached supports the functionality of LRU (Least Recently Used) eviction of values.Redis does not support the functionality of LRU eviction of values.
In Memcached when they overflow memory, the one you have not used recently (LRU- Least Recently Used) will get deleted. In Redis you can set a time out on everything, when memory is full, it will look at three random keys and deletes the one which is closest to expiry.
Memcached supports CAS(Check And Set). It is useful for maintaining cache consistency. Redis does not support CAS ( Check And Set).

27. What is the purpose of the TTL command?

TTL returns how many seconds remain before a key expires, letting an application check a key's remaining lifetime without having to track expiration times itself in separate application logic.

SET session:abc123 "data" EX 3600
TTL session:abc123      # returns remaining seconds, e.g. 3599
TTL nonexistent:key      # returns -2, key doesn't exist
TTL permanent:key         # returns -1, key exists but has no TTL set

The two special return values are worth memorizing since they're a common source of subtle bugs: -2 means the key doesn't exist at all, while -1 means the key exists but has no expiration set — conflating these two (for example, treating any negative TTL as "expired") can cause an application to misdiagnose a permanent key as missing. PTTL returns the same information in milliseconds for finer-grained checks.

What does TTL return for a key that exists but has no expiration set?
What does TTL return for a key that doesn't exist at all?

28. What is SADD command in REDIS?

Add the specified members to the set stored at key. Specified members that are already a member of this set are ignored. If key does not exist, a new set is created before adding the specified members.

An error is returned when the value stored at key is not a set.

Usage:

SADD key member [member ...]

Example:

redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
redis> SMEMBERS myset
1) "World"
2) "Hello"

29. Define eviction policies in Redis?

When Redis is used as a cache with a fixed maxmemory limit, an eviction policy determines which keys get removed once that limit is reached and new writes still need room — without a policy that allows eviction, Redis would instead simply reject new writes with an out-of-memory error once the limit is hit.

PolicyBehavior
noevictionReject writes once memory limit is reached; default setting.
allkeys-lruEvict the least recently used key, across all keys.
allkeys-lfuEvict the least frequently used key, across all keys.
volatile-lruEvict least recently used, but only among keys with a TTL set.
volatile-ttlEvict the key with the shortest remaining TTL first.
allkeys-randomEvict a random key, across all keys.

The right choice depends on how Redis is being used: a pure cache where any key can reasonably be recomputed typically uses allkeys-lru or allkeys-lfu, while a mixed deployment storing some permanent data alongside expiring cache entries uses one of the volatile-* policies to ensure only the expiring, cache-like keys are ever candidates for eviction.

What is Redis's default eviction policy?
When would a volatile-* eviction policy be preferred over an allkeys-* one?

30. Mention few LIST operations in REDIS.

LPUSH adds an element to the beginning of a list.

RPUSH add an element to the end of a list.

LPOP removes the first element from a list and returns it.

RPOP removes the last element from a list and returns it.

LLEN gets the length of a list.

LRANGE gets a range of elements from a list.

31. Mention Spring Boot Drivers for REDIS.

Spring Boot primarily supports two main Redis drivers (clients): Lettuce (which is the default) and Jedis. It abstracts these clients using the Spring Data Redis framework, allowing developers to switch between them easily.

Supported Redis Drivers

Lettuce

This is the default Redis client used in Spring Boot applications when you include the spring-boot-starter-data-redis dependency.

  • It is built on Netty and is an advanced, thread-safe Redis client.
  • Its thread-safe nature means a single connection instance can be shared across multiple threads, which can lead to more efficient resource usage and fewer physical connections to the Redis server.
  • Lettuce supports both synchronous and reactive (non-blocking) APIs, making it a good fit for modern, reactive Spring applications.

Jedis

This client is also fully supported by Spring Data Redis, although it requires explicitly excluding the default Lettuce dependency and including the Jedis one instead in your pom.xml or build.gradle file.

  • It provides a straightforward, synchronous API that closely mirrors the original Redis commands.
  • Unlike Lettuce, Jedis is generally not thread-safe for shared instances, so it relies on connection pooling in multi-threaded environments to manage connections effectively.

32. What is Redis Sentinel used for?

Sentinel is a separate, lightweight process (or set of processes) that monitors a Redis master and its replicas, and automatically handles failover if the master becomes unavailable — promoting a replica to master and reconfiguring the rest of the replicas to follow the new master, without a human needing to intervene.

# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

Running multiple Sentinel instances (typically 3 or 5, spread across different hosts) is standard, since a single Sentinel would itself be a single point of failure for failover detection; Sentinels use a quorum vote among themselves to agree a master is genuinely down before triggering failover, which guards against one Sentinel mistakenly declaring a failure due to its own local network issue. Sentinel is aimed at high availability for a single logical dataset (one master, several replicas); for horizontally scaling data across multiple masters, Redis Cluster is the separate, complementary tool.

What is Sentinel's main job?
Why are multiple Sentinel instances typically run together rather than just one?

33. Explain about redisson client for redis.

Redisson is a popular, open-source Java client for Redis (and Valkey) that offers a simplified, thread-safe way for Java developers to interact with the Redis data store. It abstracts the complexities of the Redis API by providing familiar Java objects and data structures, such as Map, List, Queue, and Lock, as distributed objects.

Key Features and Benefits of Redisson

Familiar Java Interfaces
Redisson provides implementations of common Java collections and data structures, allowing developers to use Redis with a minimal learning curve.
Distributed Objects and Services
It extends Redis's capabilities with distributed implementations of services like locks, semaphores, and Remote Procedure Calls (RPC).
Integration with Java Ecosystem
Redisson offers seamless integration with various popular Java frameworks, including Spring Cache, Spring Session, Hibernate Cache, and JCache API (JSR-107).
Asynchronous and Reactive APIs
It supports synchronous, asynchronous, reactive streams, and RxJava APIs, catering to different application needs and performance requirements.
High Performance Caching
Redisson enhances caching performance with features like "near cache," which stores frequently accessed data on the Java heap for faster retrieval.
Support for Various Redis Deployments
It supports different Redis configurations, including standalone, master-slave, and cluster modes.

34. What is Redis Cluster?

Redis Cluster is Redis's built-in solution for horizontally scaling data across multiple nodes — instead of one server holding the entire dataset, the keyspace is split into 16,384 fixed hash slots, and those slots are distributed across the cluster's master nodes, each of which can also have its own replicas for high availability.

redis-cli -c -h node1 -p 7000
CLUSTER INFO
CLUSTER SLOTS

A key's slot is computed by hashing the key (or the content inside {} braces if the key uses hash tags, which lets related keys be forced onto the same slot for multi-key operations). Clients need to be cluster-aware, since a request for a key can be redirected (via a MOVED response) to whichever node currently owns that key's slot. This design is what lets Redis Cluster scale write throughput and total dataset size well beyond a single instance's memory, at the cost of added operational complexity and some restrictions — multi-key operations only work if all involved keys map to the same slot, and numbered databases beyond database 0 aren't supported.

How does Redis Cluster distribute data across multiple nodes?
What restriction applies to multi-key operations in Redis Cluster?

35. How do you connect to Redis using the CLI?

redis-cli is Redis's interactive command-line client, and connecting to a running instance is typically a single command specifying the host, port, and (if configured) authentication credentials:

redis-cli -h localhost -p 6379
redis-cli -h redis.example.com -p 6379 -a mypassword
redis-cli -h localhost -p 6379 --tls   # for a TLS-enabled instance

Once connected, commands can be typed interactively, or the CLI can run a single command non-interactively and exit (redis-cli GET mykey), which is convenient for scripting. Passing a password with -a on the command line is convenient but leaves the credential visible in shell history and process listings; --user combined with -a supports ACL-based authentication for a specific user rather than the legacy single-password AUTH, and reading the password from an environment variable or a config file is generally the safer approach for anything beyond quick local testing.

What flag connects redis-cli to a password-protected Redis instance?
Why is passing a password directly via -a on the command line not ideal for production use?

36. What is a Cache Penetration Problem?

Cache penetration is a performance issue where requests for non-existent data repeatedly bypass the cache and hit the backend database, causing overload, often due to malicious attacks or data deletion. Solutions involve caching null/empty results with short TTLs, using a Bloom filter to pre-check for non-existent keys, or implementing logical checks to filter invalid IDs before database queries.

37. Why is Redis often faster than a traditional relational database for caching?

The speed difference comes from where and how data is stored and accessed, not from any single trick. Redis keeps its entire working dataset in RAM, so a read or write is a direct memory access rather than a disk seek, and its data structures (hash tables, skip lists, linked lists) are purpose-built for O(1) or O(log n) operations rather than the general-purpose relational model a SQL database has to support.

  • In-memory storage — no disk I/O on the read/write path for normal operations, several orders of magnitude faster than disk access.
  • Simple protocol — the RESP protocol is lightweight text/binary, avoiding the parsing and planning overhead of a SQL query.
  • No query planner or joins — a GET or HGET is a direct structure lookup, not a query that needs to be parsed, planned, and optimized.
  • Purpose-built data structures — a Sorted Set or Hash operation maps almost directly to an efficient underlying structure, rather than being expressed through general-purpose relational tables and indexes.

The trade-off is exactly what you'd expect from those design choices: Redis isn't meant to replace a relational database for complex, ad hoc queries, multi-table joins, or datasets far larger than available RAM — it excels specifically at fast, simple key-based access to a working set that fits in memory.

What is the primary reason Redis reads/writes are faster than typical disk-based database operations?
What kind of workload is Redis poorly suited to compared to a relational database?

38. What is Valkey, and how does it relate to Redis?

Valkey is a Linux Foundation-backed, BSD-3-Clause licensed fork of Redis, created immediately after Redis Ltd. moved the core Redis project off the permissive BSD license to a source-available dual license (SSPLv1/RSALv2) in March 2024. Valkey started from the last BSD-licensed Redis release (7.2.4) and has continued developing independently since, with contributions from major cloud vendors and several original Redis engineers, including Redis creator Salvatore Sanfilippo, who has contributed to Valkey.

Redis (current, 8.x line)Valkey
Tri-licensed: AGPLv3 (OSI-approved, added back in Redis 8, May 2025) or source-available SSPLv1/RSALv2.BSD-3-Clause, unrestricted, OSI-approved open source, no copyleft terms.
Maintained by Redis Ltd.Maintained by the Linux Foundation with a broad multi-vendor contributor base.
Adds newer Redis-exclusive features like vector sets (VADD/VSIM).Its own independent roadmap; e.g. Valkey 9.x added multi-database cluster support and atomic slot migration.

The two remain wire-protocol compatible in most respects, so standard client libraries (Jedis, Lettuce, redis-py, and others) generally work against either without code changes, which is why major managed cache services (AWS ElastiCache, Google Cloud Memorystore, among others) now default new deployments to Valkey. For teams choosing between them, the practical question usually comes down to license comfort (BSD vs AGPL/source-available) rather than a meaningful feature gap, since the two have stayed close in core capability even while diverging in governance.

What license does Valkey use, in contrast to Redis's current tri-license option?
Why do most existing Redis client libraries generally work against Valkey without changes?

39. How I/O Multiplexing Works in Redis?

Redis uses I/O multiplexing to enable its single-threaded core to efficiently handle thousands of concurrent client connections. This technique allows the Redis server to monitor multiple sockets simultaneously and process data on those that are ready, without blocking on any single connection.

Single-threaded core
Redis processes all commands sequentially in a single main thread, which eliminates the overhead of thread creation, context switching, locks, and race conditions.
Non-blocking I/O
All client sockets are set to non-blocking mode. This means that an I/O operation (read/write) returns immediately if no data is available, rather than pausing the entire thread.
Event Loop
The main thread runs an event loop that uses a specific I/O multiplexing system call provided by the operating system (e.g., epoll on Linux, kqueue on macOS/BSD, evport on Solaris).
Kernel Notification
Instead of constantly polling all connections (which wastes CPU), the event loop blocks in a single, efficient system call (like epoll_wait). The operating system kernel is responsible for monitoring all the file descriptors (sockets) and notifying Redis when one or more of them are ready for an I/O operation.
Event Handling
When the system call returns, Redis's event loop processes only the "ready" sockets one by one. It reads the command, executes it from memory, and writes the response back to the client.

40. What is the difference between RDB and AOF persistence?

Both write data to disk so a Redis instance can recover its dataset after a restart or crash, but they capture that data in fundamentally different forms, with different trade-offs.

RDBAOF
Point-in-time binary snapshot of the full dataset.Append-only log of every write command, in order.
Faster restart, since loading one compact file is quick.Slower restart, since the log must be replayed command by command (mitigated somewhat by AOF rewriting).
Can lose all writes since the last snapshot on a crash.Can lose at most ~1 second of writes with appendfsync=everysec, or none with always.
Smaller file size, since it's a compacted binary snapshot.Larger file size, though periodic rewriting keeps it from growing unbounded.

Many production deployments run both together: RDB for fast, compact backups and quick restarts, AOF for tighter durability against a crash between snapshots. Redis merges the two on restart by preferring AOF if both are enabled, since it generally represents more recent state, falling back to RDB if AOF is disabled.

Which persistence mechanism generally offers stronger durability against data loss on a crash?
If both RDB and AOF are enabled, which does Redis prefer when restoring data on restart?

41. How does Redis achieve high throughput with a mostly single-threaded design?

Redis's core command execution has traditionally run on a single thread, which sounds like it should limit throughput, but it actually sidesteps a large class of overhead that a multi-threaded design would otherwise need to pay for.

  • No lock contention — since only one thread ever touches the core data structures at a time, there's no need for mutexes or locking around reads and writes, which removes a meaningful source of overhead multi-threaded in-memory stores have to manage.
  • In-memory operations are already fast — most commands complete in microseconds, so a single thread can still issue an enormous number of operations per second.
  • Efficient event-driven networking — the server uses an event loop over multiplexed I/O to handle many client connections concurrently on that one thread, rather than blocking per connection.
  • Predictable atomicity — because commands run one at a time with nothing else interleaved, individual commands (and MULTI/EXEC transactions) are naturally atomic with no extra coordination needed.

Modern Redis does offload some genuinely parallelizable work — like background persistence via a forked child process, and I/O threading for reading/writing client sockets in newer versions — to separate threads/processes, while keeping command execution itself single-threaded. This hybrid approach is what lets Redis claim both simplicity/atomicity and very high real-world throughput at the same time.

What does Redis's single-threaded command execution avoid, compared to a multi-threaded design?
What work does modern Redis offload to separate threads or processes, despite single-threaded command execution?

42. Why should you configure an eviction policy for a Redis instance used as a cache?

The default noeviction policy means once maxmemory is reached, Redis starts rejecting new write commands outright with an out-of-memory error, rather than making room by removing older data. For a pure caching use case, that's usually the wrong behavior: a cache is supposed to gracefully lose its least valuable entries under memory pressure, not stop accepting new data and start returning errors to the application.

maxmemory 2gb
maxmemory-policy allkeys-lru

Configuring an eviction policy like allkeys-lru or allkeys-lfu makes the cache self-managing: as memory fills up, Redis automatically removes the least recently (or least frequently) used entries to make room, which matches how a cache is expected to behave — stale or unused data quietly falls out, while hot data stays resident. Skipping this configuration is a common cause of production incidents where a cache-only Redis instance unexpectedly starts throwing write errors under load, simply because nobody told it that eviction, not rejection, was the intended behavior when full.

What happens by default (noeviction) when a Redis instance used as a cache hits its memory limit?
What is a common production consequence of forgetting to configure an eviction policy on a cache?

43. How does Redis Cluster shard data across nodes?

Redis Cluster divides the entire keyspace into 16,384 fixed hash slots, and assigns ownership of ranges of those slots to each master node in the cluster — a 3-master cluster might own roughly 5,461 slots each, for example. A key's slot is computed as CRC16(key) mod 16384, so which node a given key belongs to is a deterministic function of the key itself, not a lookup table that has to be consulted for every single key individually.

CLUSTER KEYSLOT mykey
CLUSTER ADDSLOTS 0 1 2 3 4

To let related keys be co-located for multi-key operations, Redis supports hash tags: if a key contains a substring wrapped in {}, only that substring is hashed to determine the slot, so user:{1001}:profile and user:{1001}:orders both land on the same slot despite being different keys. Slots (and their data) can be migrated between nodes for rebalancing without downtime, and a client that sends a command for a key not owned by the node it contacted gets redirected to the correct node via a MOVED response, which is why cluster-aware client libraries cache the slot-to-node mapping rather than guessing on every request.

How is a key's hash slot determined in Redis Cluster?
What do hash tags (using {}) let you control in Redis Cluster?

44. When should you use Redis Sentinel instead of Redis Cluster?

The deciding factor is whether the real need is high availability for a dataset that fits comfortably on one node, or horizontal scaling across many nodes because the dataset or write throughput has outgrown a single instance.

Sentinel is the right fit when a single master's capacity (memory and throughput) is genuinely sufficient, and the goal is just automatic failover if that master goes down — it's simpler to operate, has no sharding restrictions (multi-key operations, transactions across arbitrary keys, and all 16 numbered databases work normally), and client configuration is comparatively straightforward.

Redis Cluster is the right fit once the dataset or throughput genuinely needs to span multiple masters — it adds high availability too (each master can have its own replicas, similar to Sentinel's role but built into the cluster itself), but at the cost of the sharding restrictions covered elsewhere (same-slot requirement for multi-key ops, no numbered databases beyond 0, more complex client and operational tooling).

The practical rule: don't reach for Cluster's added complexity just for high availability if a single master would otherwise be plenty — Sentinel solves that specific problem with meaningfully less operational overhead.

What is Sentinel's main advantage over Cluster when a single master's capacity is sufficient?
When does Redis Cluster become the better choice over Sentinel?

45. What happens when a Redis master fails in a Sentinel-managed setup?

Sentinel's failover process follows a defined sequence rather than reacting instantly to any single missed check, specifically to avoid triggering an unnecessary failover from a brief, isolated network blip.

flowchart TD A[Sentinel loses contact with master] --> B[Master marked SDOWN, subjectively down, by that one Sentinel] B --> C[Sentinel asks other Sentinels for their view of the master] C --> D{Quorum of Sentinels agree master is down?} D -- No --> E[No failover; likely a local network issue for one Sentinel] D -- Yes --> F[Master marked ODOWN, objectively down] F --> G[Sentinels elect a leader Sentinel to run the failover] G --> H[Leader Sentinel selects the best-positioned replica, e.g. most up-to-date] H --> I[Selected replica promoted to master via REPLICAOF NO ONE] I --> J[Other replicas reconfigured to replicate from the new master] J --> K[Sentinels update their config and notify connected clients of the new master]

Clients using a Sentinel-aware library discover the new master by asking Sentinel for the current address rather than hardcoding a fixed host, which is what lets an application keep working through a failover without a manual configuration change. Any writes made to the old master that hadn't yet replicated to the promoted replica at the moment of failure are lost, since Sentinel can't recover data the new master never received.

Why does Sentinel require quorum agreement before declaring a master objectively down (ODOWN)?
What data can be lost during a Sentinel-managed failover?

46. Explain the execution flow of a Redis transaction using MULTI/EXEC?

Unlike a database transaction that begins actual execution immediately, a Redis MULTI block queues commands on the client's connection without running them, and only EXEC triggers the whole batch to actually execute, uninterrupted.

flowchart TD A[Client sends MULTI] --> B[Redis enters queuing mode for this connection] B --> C[Client sends SET, INCR, etc.] C --> D{Command has a syntax error?} D -- Yes --> E[Command rejected immediately, flagged for this transaction] D -- No --> F[Command queued, reply QUEUED sent back] F --> C C --> G[Client sends EXEC] G --> H{Any command was flagged with a syntax error earlier?} H -- Yes --> I[Whole transaction aborted, nothing executes] H -- No --> J[All queued commands execute back-to-back, no other client interleaved] J --> K[Array of each command's individual result returned to the client]

The key nuance for interviews: a runtime error (like incrementing a key that holds a string) is different from a syntax error — runtime errors are only discovered during execution in step J, and don't stop the remaining queued commands from still running, since Redis doesn't inspect a command's effect on data until it actually executes it.

What does MULTI do to subsequent commands, before EXEC is sent?
Does a runtime error in one queued command stop the rest of the transaction from executing?

47. How can you optimize Redis memory usage for large datasets?

Since Redis keeps data in RAM, memory efficiency directly determines both cost and how much data fits on a given instance, and a handful of concrete techniques typically account for most of the achievable savings.

  1. Use compact encodings for small collections — Redis automatically stores small Hashes, Lists, Sets, and Sorted Sets using memory-efficient internal encodings (like listpack) instead of full hash tables, as long as they stay under configurable size thresholds (hash-max-listpack-entries, etc.); keeping collections small where the data model allows it takes advantage of this automatically.
  2. Choose Hashes over separate keys — storing related fields in one Hash has meaningfully less per-key overhead than the same data spread across many individual String keys.
  3. Use Bitmaps or HyperLogLog for large boolean/cardinality tracking instead of a Set of millions of individual entries, when the exact-membership guarantee a Set provides isn't actually needed.
  4. Set appropriate TTLs so stale cache data doesn't accumulate indefinitely and silently consume memory nobody's using.
  5. Enable an eviction policy with a maxmemory cap so memory usage has a hard, predictable ceiling rather than growing until the instance runs out of RAM.
  6. Analyze actual usage with MEMORY USAGE and redis-cli --bigkeys before optimizing blindly, to find which specific keys or patterns are actually consuming the most memory.
What Redis feature automatically uses a compact encoding for small collections?
What command helps identify which specific keys are consuming the most memory?

48. How do you troubleshoot high memory usage in a Redis instance?

High memory usage troubleshooting starts with distinguishing "memory usage is high but expected" from "memory usage is growing unexpectedly," since the fixes are very different.

INFO memory
MEMORY DOCTOR
redis-cli --bigkeys
MEMORY USAGE mykey

  1. Check INFO memory for used_memory, maxmemory, and mem_fragmentation_ratio — a high fragmentation ratio can mean actual data usage is much lower than the process's real memory footprint suggests.
  2. Run redis-cli --bigkeys to sample the keyspace and identify unusually large individual keys, which are a common, easy-to-fix source of runaway memory.
  3. Check for missing TTLs on data that was meant to be temporary — a caching pattern that forgot to set an expiration accumulates forever.
  4. Review the eviction policy and maxmemory setting — if neither is configured appropriately, memory has no ceiling at all.
  5. Check for unbounded collection growth — a List or Set that only ever gets appended to, with nothing trimming or expiring it, is a classic slow memory leak in application logic rather than in Redis itself.
  6. Use MEMORY USAGE on suspect keys to confirm exactly how much a specific key is consuming, rather than guessing from aggregate stats alone.
What does a high mem_fragmentation_ratio suggest?
What is a classic application-side cause of slow, unbounded memory growth?

49. Why is the maxmemory-policy setting important for a cache-only Redis deployment?

maxmemory-policy is what actually determines Redis's behavior once the configured maxmemory limit is hit, and for a cache-only deployment, getting this setting wrong can turn a memory-pressure event into an application outage rather than a graceful, expected eviction.

maxmemory 4gb
maxmemory-policy allkeys-lfu

Left at the default noeviction, a cache-only instance under memory pressure starts rejecting every new write with an error, which most application code isn't written to handle gracefully — a caching layer failing writes often isn't treated as a soft, expected condition the way a cache miss is. Setting an appropriate allkeys-* policy instead means the instance quietly evicts less valuable entries to make room, keeping the cache functional and the application unaware anything unusual even happened. The choice between allkeys-lru (recency-based) and allkeys-lfu (frequency-based) matters too: LFU tends to perform better for workloads with a strong "hot set" of frequently-accessed keys, since LRU alone can be tricked by a burst of one-time accesses pushing genuinely hot keys out.

What happens to writes on a cache-only instance under memory pressure if maxmemory-policy is left at noeviction?
Why might allkeys-lfu outperform allkeys-lru for a workload with a strong 'hot set' of keys?

50. Explain the lifecycle of a key with a TTL set in Redis?

A key's TTL doesn't trigger a background timer that fires exactly at expiration — Redis uses a combination of lazy and active strategies to actually reclaim expired keys, which is worth understanding since it explains some otherwise-surprising behavior around memory and replication.

flowchart TD A[Key created with EXPIRE/EX/PX] --> B[Expiration timestamp stored alongside the key] B --> C{Key accessed by a client command before expiring?} C -- Yes, and TTL has passed --> D[Lazy expiration: key deleted on access, treated as if it doesn't exist] C -- No access yet --> E[Key remains in memory, technically expired but not yet removed] E --> F[Active expiration cycle runs periodically in the background] F --> G[Redis samples a set of keys with TTLs, deletes any that have expired] G --> H{Sampled expired-key ratio still high?} H -- Yes --> F H -- No --> I[Cycle pauses until next scheduled run] D --> J[Expiration event propagated to replicas as an explicit DEL command] I --> J

The propagation detail in step J matters for consistency: replicas don't independently decide a key has expired based on their own clock — the master is the source of truth for expiration, and sends an explicit DEL/UNLINK to replicas once it expires a key, which avoids replicas disagreeing about whether a key is still valid due to clock drift or replication lag.

What are the two mechanisms Redis uses to actually reclaim expired keys?
How does a replica learn that a key has expired?

51. How does Redis handle atomicity for multi-key operations?

A single Redis command, even one touching multiple keys (like MSET or SUNIONSTORE), is always atomic on its own — because command execution is single-threaded, nothing else can run in the middle of it. The harder case is atomicity across a sequence of separate commands, where Redis offers a few different tools depending on what's actually needed.

ToolUse When
MULTI/EXECA fixed, known sequence of commands needs to run uninterrupted.
WATCH + MULTI/EXECThe sequence depends on first reading a value (check-then-act), needing optimistic locking.
Lua scripting (EVAL)Complex conditional logic across multiple keys needs to run as one atomic unit, including branching not expressible as a flat command list.

Lua scripts are the most powerful option here: the entire script executes as a single atomic step from Redis's perspective, with no other command interleaved anywhere in the middle, which lets you express logic (loops, conditionals, computed values feeding into further commands) that plain MULTI/EXEC can't, since MULTI/EXEC only queues a fixed list without letting one command's result influence the next command in the same transaction.

Is a single command touching multiple keys, like MSET, atomic on its own?
What can a Lua script do that plain MULTI/EXEC cannot?

52. What is the difference between a Redis List and Sorted Set for queues?

Both can back a queue, but they fit different queue semantics depending on whether strict FIFO insertion order or a computed priority should determine processing order.

List (LPUSH/RPOP)Sorted Set (ZADD/ZPOPMIN)
Strict insertion-order FIFO (or LIFO with matching push/pop ends).Ordered by an explicit score, which can represent priority, a timestamp, or any custom ranking.
Simple, minimal overhead per operation.Slightly more overhead, since it maintains sorted order via a skip list.
Good fit for a plain task queue where order of arrival is all that matters.Good fit for a priority queue, delayed queue (score = due time), or any case needing reordering.
BLPOP/BRPOP provide blocking pop for worker patterns.ZPOPMIN/ZPOPMAX support similar patterns, plus range queries by score.

The deciding question is usually: does processing order need to be anything other than strict arrival order? If yes — priority levels, a scheduled/delayed queue, or reordering based on some external factor — a Sorted Set's score gives that flexibility directly; if the queue is genuinely just first-in-first-out, a List is simpler and has less overhead per operation for the same result.

What ordering does a Sorted Set-based queue provide that a plain List doesn't?
When is a List generally the simpler, more appropriate choice for a queue?

53. How do you implement a distributed lock using Redis?

The basic pattern uses a single atomic command to both acquire the lock and set a safety expiration in one step, so a crashed client can never hold a lock forever:

SET lock:resource-1 "unique-client-token" NX PX 30000

NX means the key is only set if it doesn't already exist (so only one client can "win" the lock at a time), and PX 30000 gives it a 30-second auto-expiring safety net in case the client that acquired it crashes before releasing it explicitly. Releasing the lock safely requires checking that the client releasing it is the one that actually holds it — done via a small Lua script so the check-and-delete is atomic:

if redis.call("GET", KEYS[1]) == ARGV[1] then
    return redis.call("DEL", KEYS[1])
else
    return 0
end

This basic pattern is sufficient for most single-instance use cases, but it has a known weakness against a master failing over to a replica that hadn't yet received the lock write, which is what the more elaborate Redlock algorithm (acquiring the lock across a majority of independent Redis instances) is designed to address for scenarios where lock correctness genuinely can't tolerate that edge case — though Redlock's own guarantees have been debated in the distributed-systems community, and many applications find the simpler single-instance pattern an acceptable trade-off in practice.

What does the PX option on the lock-acquiring SET command guard against?
Why does releasing the lock require a Lua script rather than a plain DEL?

54. How does Redis Streams support consumer groups?

A consumer group lets multiple consumers cooperatively process a single stream, with Redis tracking, per group, which entries have been delivered and which have been explicitly acknowledged — behavior much closer to a traditional message queue than Redis's other data types offer.

XGROUP CREATE events mygroup 0
XREADGROUP GROUP mygroup consumer-1 COUNT 10 STREAMS events >
XACK events mygroup 1691425200000-0

When a consumer reads with XREADGROUP, entries are added to that consumer's pending entries list (PEL) — delivered but not yet acknowledged. Calling XACK removes an entry from the PEL once processing is confirmed complete. If a consumer crashes with unacknowledged entries still in its PEL, XCLAIM (or the newer XAUTOCLAIM) lets another consumer in the same group take ownership of those stuck entries and retry them, which is what gives Streams at-least-once delivery semantics within a group — an entry isn't considered fully processed until it's explicitly acknowledged, no matter which consumer ends up handling it.

What does a consumer's pending entries list (PEL) track?
What lets another consumer take over entries stuck in a crashed consumer's PEL?

55. Which is better and why: Redis Pub/Sub or Redis Streams for event delivery?

The two solve overlapping but genuinely different problems, so "better" depends entirely on whether message durability and replay matter for the use case.

Pub/Sub is the better fit when messages are only meaningful to clients that are connected right now — live dashboards, real-time notifications, chat presence updates — where a message missed by a disconnected client is expected to simply be irrelevant by the time that client reconnects. It's simpler, has lower overhead, and needs no consumer-group bookkeeping.

Streams is the better fit whenever a message must not be silently lost if no one happens to be listening at that exact instant — event sourcing, audit logs, task queues, or any pipeline where a consumer restarting or briefly disconnecting shouldn't mean lost data. Streams' persistence, consumer groups, and per-message acknowledgment give it delivery guarantees Pub/Sub fundamentally doesn't attempt to provide.

The practical rule: reach for Pub/Sub when "only currently-listening clients need this" is actually true and acceptable; reach for Streams the moment reliable delivery, replay, or coordinated processing across multiple consumers becomes a real requirement rather than a nice-to-have.

When is Pub/Sub the better choice over Streams?
What does Streams offer that Pub/Sub fundamentally does not?

56. How do you integrate Redis as a session store in a web application?

Using Redis for session storage means each user's session data (login state, cart contents, preferences) is stored as a Hash or JSON-serialized String under a key derived from a session ID, with a TTL matching the desired session lifetime — instead of relying on server-local in-memory session storage, which breaks as soon as requests are load-balanced across multiple application servers.

HSET session:abc123 user_id "1001" cart_items "3"
EXPIRE session:abc123 1800   # 30-minute session timeout

Most web frameworks (Express with connect-redis, Spring Session with its Redis integration, Django with django-redis, and others) provide a ready-made session store adapter, so the application typically doesn't hand-roll this logic — it configures the framework to use Redis as the session backend and gets automatic session read/write/expiry wired in. The key operational benefit over local in-memory sessions is that any application server instance can serve any request for a given session, since session state lives centrally in Redis rather than pinned to whichever server first created it, which is exactly what makes horizontal scaling and rolling deployments practical for a stateful-feeling web application.

What problem does centralizing sessions in Redis solve for a load-balanced web application?
How do most web frameworks typically integrate Redis for session storage?

57. Explain the internal working of Redis's hash table resizing (rehashing)?

Redis's core keyspace (and large Hash-type values) are backed by a hash table, and as entries are added or removed, the table needs to grow or shrink to keep lookups close to O(1) — but a naive full rehash (allocate a new table, move every entry, free the old one) would briefly block every other operation on a table with millions of entries, which conflicts directly with Redis's single-threaded, low-latency design.

flowchart TD A[Load factor crosses a threshold, growth or shrink needed] --> B[Allocate a second, differently-sized hash table] B --> C[Rehashing flag set: both old and new tables now active simultaneously] C --> D[Each subsequent command incrementally moves one bucket's worth of entries from old to new table] D --> E{All buckets migrated?} E -- No --> F[Old table still holds unmigrated entries; lookups check both tables during this period] F --> D E -- Yes --> G[Old table freed, new table becomes the sole active table]

This incremental rehashing spreads the cost of a full table resize across many individual commands instead of pausing everything for one large operation, which is what lets Redis resize its hash tables even under heavy load without a noticeable latency spike. During the migration window, any lookup for a key has to check both tables (since it might not have been migrated yet), which is a small, bounded per-operation cost rather than one large blocking one.

Why doesn't Redis perform a full hash table rehash in one blocking step?
What must a lookup do while incremental rehashing is in progress?

58. How do you configure Redis persistence for a production deployment?

Production Redis persistence is typically both RDB and AOF enabled together, tuned to balance recovery speed, durability, and operational overhead, rather than relying on just one mechanism alone.

# redis.conf
save 900 1
save 300 10
save 60 10000

appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

The reasoning behind this common combination: RDB snapshots provide fast, compact backups useful for disaster recovery and moving data between environments, while AOF with appendfsync everysec caps potential data loss at roughly one second of writes, a durability level most applications find acceptable without the latency cost of always. auto-aof-rewrite-percentage controls when Redis automatically compacts the AOF file (once it's grown a configured percentage larger than after the last rewrite), keeping it from growing unbounded. For genuinely critical data, pairing this local persistence config with replication (so a replica also holds a full copy) is standard, since local persistence alone still leaves a gap between the last fsync and any writes since, whereas a fully synced replica offers an additional, independent copy.

What is a common production pattern combining both persistence mechanisms?
Why is replication often paired with local persistence for critical data?

59. What is the difference between Redis Cluster and client-side sharding?

Both split data across multiple Redis instances, but they differ in where the sharding logic and cluster awareness actually live.

Redis ClusterClient-Side Sharding
Sharding logic (hash slots, redirection) built into Redis and cluster-aware clients.Sharding logic implemented entirely in application/client code, against plain standalone Redis instances.
Automatic slot rebalancing and MOVED redirection handled by the cluster.Rebalancing across shards must be handled manually by the application.
Built-in replica-based failover per shard.Failover must be implemented separately, e.g. pairing each shard with its own Sentinel setup.
Standardized behavior across any cluster-aware client library.Sharding scheme (e.g. consistent hashing) is whatever the application chooses, requiring custom logic per client language.

Client-side sharding predates Redis Cluster's maturity and still shows up in some existing systems or when the sharding key logic needs to be more custom than Cluster's simple hash-slot model allows, but for new deployments Redis Cluster is generally preferred since it removes the need to hand-build and maintain sharding, rebalancing, and failover logic in application code that Redis itself now handles natively.

Where does the sharding logic live in client-side sharding, as opposed to Redis Cluster?
Why might a team still choose client-side sharding today despite Redis Cluster's maturity?

60. How does Redis support Lua scripting for atomic operations?

Redis embeds a Lua interpreter directly in the server, and EVAL (or the cached, more efficient EVALSHA) runs a Lua script as a single atomic unit — the entire script executes with no other client command interleaved anywhere in the middle, the same guarantee a single native command gets.

-- atomic "increment if under a limit" check
local current = tonumber(redis.call("GET", KEYS[1]) or "0")
if current < tonumber(ARGV[1]) then
    return redis.call("INCR", KEYS[1])
else
    return -1
end

EVAL "..." 1 rate:user:1001 100

Keys the script will touch are passed explicitly via KEYS (rather than the script hardcoding key names), which matters for Redis Cluster compatibility, since the cluster needs to know up front which slots a script will access. Because the script logic runs entirely inside Redis rather than requiring a round trip back to the client between each step, it also cuts network latency for multi-step logic — a "check current value, conditionally increment" pattern that would otherwise need two separate round trips (with a race condition between them) becomes one atomic, single-round-trip operation.

What guarantee does an entire Lua script get when run via EVAL?
Why are a script's keys passed explicitly via KEYS rather than hardcoded inside the script?

61. When would you choose Redis Streams over a message broker like Kafka?

Both give you a durable, replayable, partitioned-ish log with consumer groups, but they're built for different scales and operational footprints, so the choice usually comes down to how large and how critical the messaging workload actually is.

Redis Streams makes sense when messaging is a secondary capability layered on top of a system that's already using Redis for caching, sessions, or other data — adding a Stream avoids standing up an entirely separate piece of infrastructure just for a moderate-volume event pipeline. It's also naturally in-memory (though persistable via RDB/AOF like any Redis data), giving low latency for smaller-to-moderate workloads without Kafka's operational overhead of a distributed log system with its own cluster, brokers, and tooling.

Kafka is the better choice once the workload genuinely needs Kafka-scale throughput, very long retention windows measured in weeks or months across large datasets, tiered storage for cost-effective long-term retention, or a rich ecosystem of connectors and stream-processing tools (Kafka Connect, Kafka Streams). Kafka is purpose-built and heavily optimized for exactly that scale of durable event streaming in a way Redis, fundamentally an in-memory store, isn't designed to match.

The practical rule: reach for Redis Streams when messaging needs are modest and you'd rather not run a second piece of infrastructure; reach for Kafka once volume, retention, or ecosystem requirements genuinely exceed what an in-memory-first system is built for.

When does Redis Streams make more sense than standing up Kafka?
What does Kafka offer that makes it the better fit at very large scale?

62. How do you secure Redis access using ACLs?

Redis's Access Control List (ACL) system lets you define named users, each with their own password, and fine-grained permissions over which commands they can run and which keys they can touch — a meaningful step up from the older, single shared-password requirepass model, which offered no per-user distinction at all.

ACL SETUSER app-readonly on >secretpass ~cache:* +get +mget -@write
ACL SETUSER app-writer on >anotherpass ~orders:* +@all -flushall -flushdb
ACL LIST

The pattern above shows the key building blocks: ~pattern restricts which keys a user can access (glob-style, so ~cache:* limits the user to keys under that prefix), +command/-command grants or denies specific commands, and +@category/-@category does the same for whole command categories (like @write or @dangerous). This lets a deployment give a read-only reporting service exactly read access to its own key namespace, while a different service gets write access scoped to its own keys, with neither able to run administrative commands like FLUSHALL — a level of least-privilege access control that a single shared password can't express at all.

What does the ~pattern syntax control in a Redis ACL user definition?
What limitation does ACLs solve compared to the older requirepass model?

63. Why should the KEYS command be avoided in production?

KEYS pattern scans the entire keyspace to find matching keys, and because it runs on Redis's single command-execution thread, it blocks every other client from being served for however long that full scan takes — on a dataset with millions of keys, that can mean a multi-second (or longer) freeze of the entire instance, affecting every application using it, not just the one that ran the command.

# avoid in production
KEYS user:*

# use instead
SCAN 0 MATCH user:* COUNT 100

SCAN is the safe alternative: it walks the keyspace incrementally, returning a small batch of keys plus a cursor per call, so the cost of a full traversal is spread across many small, non-blocking operations instead of one large blocking one — at the cost of a weaker consistency guarantee (keys added or removed during the scan may or may not be reflected, unlike KEYS's single atomic snapshot view). For production Redis, KEYS is generally reserved for one-off debugging on a non-critical instance, never for application logic or scheduled jobs, precisely because of the blocking behavior that makes it dangerous at any meaningful dataset size.

Why can KEYS cause a production outage on a large dataset?
What does SCAN trade away compared to KEYS in exchange for not blocking?

64. How do you configure Redis for cache-aside pattern usage?

The cache-aside (lazy-loading) pattern keeps the application in control of when data is read from and written to the cache, with Redis itself needing minimal special configuration — the pattern mostly lives in application logic, with a few Redis-side settings that support it well.

# pseudocode for the read path
value = redis.get(cache_key)
if value is None:
    value = database.query(...)
    redis.set(cache_key, value, ex=300)  # cache for 5 minutes
return value

maxmemory 4gb
maxmemory-policy allkeys-lru

On the read side: check the cache first; on a miss, fetch from the source of truth (typically a database) and populate the cache with an appropriate TTL before returning. On the write side, the application typically writes to the database and then either updates or invalidates the corresponding cache key, rather than writing to the cache directly as the source of truth — Redis in this pattern is explicitly a derived, disposable copy, never the authoritative store. An eviction policy (as covered elsewhere) and sensible per-key TTLs are the main Redis-side configuration that keeps a cache-aside deployment healthy, since the pattern assumes cache misses are cheap and expected, not a failure condition.

In the cache-aside pattern, what happens on a cache miss?
In cache-aside, is Redis treated as the authoritative source of truth?

65. Explain the execution flow of a Redis Cluster request with a MOVED redirection?

A cluster-aware client doesn't need to know in advance exactly which node owns every key, but it does need to handle being told it guessed wrong, which is what the MOVED response mechanism exists for.

flowchart TD A[Client computes key's hash slot, e.g. via CRC16] --> B[Client sends command to the node it believes owns that slot] B --> C{Does this node actually own the slot?} C -- Yes --> D[Command executes normally, result returned] C -- No --> E[Node replies: MOVED slot-number target-host:target-port] E --> F[Client updates its local slot-to-node mapping cache] F --> G[Client resends the exact same command to the correct node] G --> D

Well-behaved cluster clients cache the slot-to-node mapping after learning it, so a MOVED redirection typically only happens once per stale mapping, not on every single request — the client corrects its cache and future requests for that slot go directly to the right node. A related response, ASK, appears specifically during live slot migration between nodes: it tells the client to retry the command against a different node for this one request only, without permanently updating its cached mapping, since the migration might not be finished yet.

What does a client do when it receives a MOVED response?
How does an ASK response differ from a MOVED response?

66. How does Redis handle replication lag between a master and its replicas?

Redis replication is asynchronous by default: a write completes and is acknowledged to the client as soon as the master processes it, without waiting for any replica to confirm receipt — which is what makes writes fast, but also means a replica's data can lag slightly behind the master at any given moment, and that gap can widen under heavy write load or network issues.

INFO replication
# master_repl_offset:12345
# slave0:...,offset=12300,lag=1

Redis exposes replication offsets on both master and replicas, and the difference between them is effectively the lag — visible via INFO replication, which is the standard way to monitor how far behind a given replica currently is. For workloads that can't tolerate reading stale data from a lagging replica, the WAIT command lets a client block until a write has been acknowledged by a specified number of replicas (with a timeout), effectively trading some of replication's default speed for a stronger consistency guarantee on that specific write, without switching the whole deployment to synchronous replication permanently. Persistent, growing lag over time is usually a sign the replica's hardware, network, or CPU can't keep pace with the master's write volume, and is treated as an operational issue to investigate rather than expected behavior.

Is Redis replication synchronous or asynchronous by default?
What does the WAIT command let a client do?

67. Why doesn't Redis guarantee strong consistency by default across replicas?

Redis's default replication is asynchronous specifically to keep write latency low: a master acknowledges a write as soon as it's processed locally, without pausing to confirm every replica has received it too. That design choice is exactly what makes strong consistency (every replica always reflecting the latest acknowledged write) not guaranteed by default — there's an inherent window, however small, where a replica's data can be behind the master's.

The practical consequence shows up most visibly during failover: if a master fails and a replica that hadn't yet received the most recent writes is promoted (by Sentinel or Redis Cluster), those most recent writes are permanently lost, and any client that had already read them from the old master before the failure effectively saw data that no longer exists post-failover. This is a deliberate trade-off, not an oversight — Redis prioritizes latency and availability over strict consistency by default, which fits the vast majority of caching and session-storage use cases where slightly stale replica reads or an occasional lost write during a rare failover are an acceptable cost.

For workloads that need stronger guarantees, the WAIT command (blocking until a specified number of replicas acknowledge a given write) is the available lever, used selectively for specific critical writes rather than as a blanket default, since applying it to every write would erode the latency benefit that makes Redis attractive in the first place.

Why is Redis's default asynchronous replication a deliberate trade-off rather than an oversight?
What can happen to very recent writes if a master fails before a replica received them?

68. How do you mitigate a Cache Avalanche in a Redis-backed system?

A Cache Avalanche happens when a large number of cached keys expire at (or near) the same moment, sending a sudden flood of requests through to the backing database all at once, since the cache can no longer absorb them — a database that was comfortably handling load with the cache in front of it can be overwhelmed by that simultaneous mass of cache misses.

  • Jitter TTLs — instead of setting every similar key to expire in exactly, say, 300 seconds, add a small random offset (e.g. 300 seconds ± 30 seconds) so expirations spread out over time rather than clustering.
  • Use a mutex/lock on cache repopulation — when a popular key expires, let only one request rebuild it while others either wait briefly or serve a slightly stale value, rather than every concurrent request hammering the database for the same data simultaneously.
  • Multi-tier caching — a local, short-lived in-process cache layer in front of Redis absorbs some traffic even if the Redis-level entry has just expired.
  • Circuit breaking / rate limiting on the database — as a last line of defense, protect the database itself from being overwhelmed regardless of what caused the surge.
  • Redis high availability (Sentinel or Cluster) — guards against the related scenario where the avalanche is caused by the Redis instance itself going down, not just mass key expiration, sending all traffic straight to the database with no cache layer at all.
What triggers a Cache Avalanche?
What does 'jittering' TTLs mean as a mitigation technique?

69. What is the difference between Redis's diskless replication and disk-based replication?

When a new replica connects (or an existing one falls too far behind to catch up incrementally), the master needs to send it a full copy of the dataset to bootstrap from, and Redis supports two different mechanisms for producing that initial transfer.

Disk-based ReplicationDiskless Replication
Master writes a full RDB snapshot to a local disk file first, then transfers that file to the replica.Master streams the RDB snapshot data directly over the network socket to the replica, without writing it to local disk first.
Extra disk I/O and disk space needed for the temporary snapshot file.Avoids that disk I/O and space entirely, generating the snapshot data on the fly during transfer.
Can be beneficial if disk I/O is fast and network is comparatively slow, since the file is ready before transfer starts.Beneficial when disk I/O or space is the constrained resource, e.g. on cloud instances with limited or slow local disk.
repl-diskless-sync norepl-diskless-sync yes

Diskless replication is generally the better default on modern cloud infrastructure where local disk can be a scarcer or slower resource than network bandwidth, which is why it's commonly enabled in production. repl-diskless-sync-delay adds a small configurable wait before starting a diskless sync, giving multiple replicas that connect around the same time a chance to be served by a single generated snapshot stream instead of the master redundantly generating one per replica.

What does diskless replication avoid, compared to disk-based replication?
What does repl-diskless-sync-delay help with?
«
»

Comments & Discussions