Skip to content

Redis Data Structures & Use Cases

120 companion flashcards · AI-assisted study content · Open the deck →

This deck offers a focused introduction to Redis, the popular in-memory data store, starting with foundational facts like what the name stands for, the language it is written in, and its default network port. From there, it moves into the most basic Redis data type—the string—covering essential commands such as GETSET, SETNX, INCR, APPEND, and MGET, along with the subtle differences between similar-sounding options. Together, these cards build a working vocabulary of Redis primitives that you can apply directly in real projects.

The deck is well suited for backend developers, software engineering students, and anyone preparing for a technical interview that touches on caching or key-value stores. If you are new to Redis, the cards will walk you through the basics step by step, while more experienced users can use them as a quick refresher on exact command behavior and edge cases, such as what happens when INCR is applied to a non-integer value.

To get the most out of this deck, try to recall the exact command names and their arguments rather than just the concept behind them—Redis is unforgiving about typos, and muscle memory pays off. Pair each study session with a few minutes of hands-on practice in a local Redis instance so that the commands feel familiar, and space your reviews over several days rather than cramming, since command syntax tends to stick best when revisited regularly.

Redis Fundamentals and the String Type

Redis, which stands for REmote DIctionary Server, is a versatile data store written in the C programming language. By default it listens for client connections on TCP port 6379. Architecturally, Redis is best classified as an in-memory key-value data store that is simultaneously usable as a database, a cache, and a message broker. Because the data lives in memory rather than on disk, Redis offers very low latency for reads and writes, while still providing optional mechanisms for durability and replication.

The most basic Redis type is the string, which stores a single binary-safe value of up to 512 MB per key. Several variants of the SET command give precise control over how writes behave. GETSET atomically assigns a new value and returns the previous one, which is handy for state transitions. The modern atomic form SET key value NX only writes when the key does not yet exist and can also carry an expiration; its predecessor, the SETNX command, is essentially legacy. Conversely, SET key value XX writes only if the key already exists. Time-based expiration comes in two flavors: SETEX accepts a TTL in seconds, while SET ... PX takes milliseconds for finer control.

Redis also provides arithmetic and bulk operations on string values. INCR atomically increments the integer stored at a key and returns the new value; running it on a non-integer value results in an error rather than silent corruption. APPEND concatenates a value to the existing string, and STRLEN reports its length in bytes. When many keys are needed in one round trip, MGET fetches the values for multiple keys together, drastically reducing the number of network exchanges between a client and the server.

Sets and Sorted Sets

A Set in Redis is an unordered collection of unique strings. Adding members with SADD is constant time, \(O(1)\) per element, while reading the full membership list with SMEMBERS is linear in the size of the set, \(O(N)\). For very large sets, this difference matters: SMEMBERS returns the entire collection in a single blocking call, whereas SSCAN iterates incrementally using a cursor and avoids blocking the server. Membership testing is provided by SISMEMBER, which returns 1 if the element is present and 0 otherwise. Set algebra is built in: SUNIONSTORE writes the union of multiple sets into a destination key, and SDIFF returns the members present in the first set but not in any of the others. SRANDMEMBER returns random members without removing them, in contrast to SPOP, which both returns and removes a random element. Typical use cases for sets include tagging items, tracking unique visitors, and powering intersection-based recommendation features.

The Sorted Set, often called a ZSET, extends the set idea by associating a numeric score with each unique member, so that members are kept in order by that score. Internally, Redis implements a sorted set as a combination of a skip list and a hash table, which together give logarithmic insertion and lookup while preserving order. ZADD therefore runs in \(O(\log N)\) time, where N is the number of members. ZREVRANK returns the rank of a member with the highest score at index 0, while ZSCORE returns the score itself, or nil if the member is not in the set. Two range commands are sometimes confused: ZRANGE selects members by their index position, whereas ZRANGEBYSCORE selects members whose score falls in a specified range. ZINCRBY atomically increments a member's score by a given amount, which is useful for scoring events.

Sorted sets lend themselves naturally to use cases such as leaderboards, where members are users and scores are their points; time-series indexes, where scores are timestamps; and rate limiting. A sliding-window rate limiter, for example, can be implemented by storing request timestamps as scores, calling ZREMRANGEBYSCORE to drop entries that have aged out of the window, and then using ZCARD to count how many requests remain inside the window. If the count exceeds the limit, the request is rejected.

Lists and Hashes

The Redis List is an ordered collection of strings, ordered by insertion. Small lists are stored in a compact structure called a listpack, which replaced the older ziplist representation. Insertion at the head with LPUSH is constant time, \(O(1)\), making lists well suited to use as queues or stacks. Blocking variants exist for consumer-style workloads: BLPOP and BRPOP block the client until an element becomes available or a timeout elapses, which makes it possible to coordinate producers and consumers without busy-waiting. The direction of insertion is chosen with LPUSH (insert at the head, or left end) versus RPUSH (insert at the tail, or right end).

Several commands shape lists in place. LTRIM removes all elements outside a specified index range, leaving only the requested window. LLEN reports the current length. The classic producer/consumer pattern uses LPUSH to enqueue and BRPOP to dequeue, giving a simple message queue in just two commands. A second pattern, the recent-activity feed, is built by LPUSH-ing new items and then calling LTRIM to keep only the most recent N, so the list automatically stays bounded in size. LMOVE, the modern replacement for RPOPLPUSH, atomically pops an element from one list and pushes it to another, with the direction configurable.

A Hash maps field-value pairs within a single key, which is a natural fit for objects such as users, products, or sessions. Reading a single field with HGET is constant time, \(O(1)\). To inspect an entire hash, HGETALL returns all fields and values as a flat list, while HVALS returns only the values. Numeric updates on a field can be done atomically with HINCRBY, which increments the integer value of a field. HDEL removes one or more fields, and from Redis 7.4 onward, HEXPIRE can attach a TTL to an individual hash field. Choosing a hash to represent an object instead of many separate string keys typically uses less memory and allows partial-field reads and writes, which is far more efficient than fetching and rewriting the entire object.

Streams, Pub/Sub, and Messaging

A Redis Stream is an append-only log data structure that supports consumer groups, message IDs, and acknowledgments. Each entry carries an ID composed of the millisecond timestamp at which it was created plus a sequence number for entries written within the same millisecond, ensuring total ordering. Entries are added with XADD and read with XREAD. To coordinate multiple workers, XREADGROUP lets clients consume a stream as part of a consumer group so that each entry is delivered to exactly one consumer. Once a consumer has successfully processed an entry, XACK acknowledges it; unacknowledged entries remain in the pending entries list and can be inspected or claimed later.

Streams are designed for durability and replayability, which is the main problem they solve relative to Pub/Sub and Lists. Lists can serve as queues but lack a built-in notion of acknowledgment or per-consumer delivery, and Pub/Sub is fire-and-forget: messages are not stored and are simply dropped if no subscriber is listening. Streams preserve history and let new consumers pick up where they left off. To keep a stream from growing without bound, XADD accepts a MAXLEN ~ N option that performs approximate trimming to roughly N of the most recent entries with very low overhead, avoiding the cost of an exact size check on every write.

Redis Pub/Sub is a simpler real-time messaging model in which publishers send messages to channels and subscribers receive them as they arrive. SUBSCRIBE attaches a client to one or more channels, while PSUBSCRIBE matches channels by a glob pattern, so a single subscriber can receive traffic from many related channels. The defining limitation of Pub/Sub compared to Streams is its fire-and-forget semantics: there is no storage of messages, no acknowledgments, and no replay; if no subscriber is connected when a message is published, the message is lost.

Specialized Data Structures

Beyond the core types, Redis offers several specialized structures that solve specific problems very efficiently. The HyperLogLog is a probabilistic counter for unique items. Regardless of how many distinct items have been added, it occupies a fixed footprint of about 12 KB per key and has a typical standard error of around 0.81%. Both PFADD and PFCOUNT run in constant time, \(O(1)\), per key. HyperLogLogs are ideal for daily unique visitor counts, distinct query counts, or counting distinct IP addresses, where exact cardinality would be far too expensive to track.

Bitmaps are ordinary Redis strings interpreted as arrays of bits, addressable by index. SETBIT sets a single bit at a given offset, GETBIT reads it, and BITOP performs bitwise AND, OR, XOR, and NOT across multiple keys in a single operation. These structures are extremely compact and very fast for tracking per-user boolean state across days, for daily active user analytics, or for feature flags where each user is simply a bit in a long string of bytes.

The geospatial index is a sorted set in disguise. Locations are stored in a sorted set where the score is a 52-bit geohash encoding of the latitude and longitude, which is what makes range queries by position possible. GEOADD adds a location, and GEOSEARCH, introduced in Redis 6.2 to replace the older GEORADIUS, returns places within a given radius of a point. GEODIST computes the distance between two members of the index. The complexity of GEOSEARCH is roughly \(O(N + \log M)\), where N is the number of items in the radius and M is the total number of items in the index. Finally, Bloom filters provide a probabilistic membership test with possible false positives but no false negatives; in Redis they are delivered by the RedisBloom module as either Bloom or Cuckoo filters. Their main use is to avoid expensive downstream lookups for items that are very likely absent, such as checking whether a username or cache key exists before hitting a backing database.

Memory Management and Persistence

Redis gives operators fine-grained control over what happens when memory fills up. Two settings drive this behavior: the maxmemory directive, which caps how many bytes Redis is allowed to use, and the maxmemory-policy, which selects the algorithm used to free space. Redis also supports keyspace notifications, configured by the notify-keyspace-events directive in redis.conf, which publish events on a Pub/Sub channel whenever a key is created, modified, expired, or evicted. To subscribe specifically to expiration events, a client connects to a channel named like __keyevent@0__:expired, where the 0 is the database index, and listens there.

Several eviction policies are available. The default is noeviction, which simply returns write errors when memory is full rather than removing any data. volatile-lru evicts the least recently used keys among those that have a TTL set, while allkeys-lru applies LRU eviction to every key regardless of whether it has an expiration. volatile-ttl evicts the key with the shortest remaining TTL among keys that have one. For workloads where frequency matters more than recency, the LFU policies, namely volatile-lfu and allkeys-lfu, evict the least frequently used keys, again scoped by whether a TTL is present. Choosing among these policies is essentially a question of whether some keys are exempt from eviction and whether access patterns are better captured by recency or by frequency.

For durability, Redis supports two main persistence mechanisms. RDB takes point-in-time snapshots of the dataset and writes them to a file named dump.rdb at configured intervals; the default rule in redis.conf is to snapshot after 1 hour if at least 1 key changed, after 5 minutes if at least 100 changed, and after 1 minute if at least 10,000 changed. AOF, by contrast, appends every write command to a file named appendonly.aof, which is replayed at restart to rebuild the dataset. Because the AOF file can grow indefinitely, a background rewrite compacts it from the current dataset. The appendfsync setting controls how often the OS flushes AOF data to disk: the common everysec mode flushes once per second, offering a balance between durability and performance. In general, AOF with appendfsync always gives the strongest durability, while RDB may lose the last seconds or minutes of writes in the event of a crash.

Replication, Clustering, Transactions, and Operations

Redis provides several mechanisms for distributing data and coordinating concurrent access. Replication involves asynchronous copies from a primary to one or more replica nodes, which both scales reads and improves availability. For stronger write guarantees, the WAIT command blocks the client until a specified number of replicas have acknowledged the write. Sentinel is a built-in high-availability system that monitors primaries and replicas and performs automatic failover when the primary becomes unreachable. For horizontal scaling, Redis Cluster is a native sharding solution that splits the keyspace across nodes using 16,384 hash slots, with each key mapped by \(\text{CRC16}(key) \bmod 16384\). When a multi-key command touches keys in different slots, Redis returns a CROSSSLOT error. To force related keys into the same slot, a substring can be enclosed in curly braces, a feature called a hash tag.

When a slot is being migrated, clients may receive two different redirection errors. A MOVED response is permanent and tells the client that the requested slot is now owned by a different node, so the client should update its routing table. An ASK response is transient and is only valid during the migration itself, hinting that the key may still be on the source node for this particular request. A recommended production topology for Redis Cluster is three masters with one replica each, for a total of six nodes, which tolerates the loss of a single master while remaining manageable. Atomicity across multiple commands is provided by transactions: MULTI starts a transaction, EXEC executes the queued commands atomically and in isolation from other clients, and WATCH provides optimistic concurrency by aborting the transaction if any watched key is modified before EXEC. Lua scripts, invoked with EVAL or with EVALSHA by their SHA1 hash, also run atomically and additionally support conditional logic and complex cross-key operations. If EVALSHA cannot find the script in the cache, the server returns a NOSCRIPT error, and clients should fall back to EVAL to re-cache it.

Operational commands round out the Redis toolbox. SCAN iterates over the keyspace using a cursor in small batches and is safe on large datasets, whereas KEYS returns all matches in a single blocking call and should be avoided in production. Inside SCAN, MATCH filters returned keys by a glob pattern. The TYPE command reports the data type stored at a key, while OBJECT ENCODING reveals the internal encoding, such as embstr for small strings up to 44 bytes stored inline in the Redis object, int for small integers, listpack for small lists and hashes, skiplist for sorted sets, or hashtable for larger collections. OBJECT IDLETIME returns the seconds since a stored object was last accessed. The SLOWLOG records commands that exceeded a configurable time threshold, which is invaluable for diagnosing performance issues. Finally, the INFO command provides a comprehensive set of server statistics and configuration values, including used_memory, the total bytes Redis has allocated to store data including overhead.

Frequently asked questions

What does the acronym Redis stand for?

REmote DIctionary Server

Which command appends a value to an existing string?

APPEND

What is a typical use case for Redis Sets?

Tagging, unique visitor tracking, and set-intersection recommendations

What is the time complexity of LPUSH?

O(1)

Which command increments the integer value of a hash field?

HINCRBY

What problem do Streams solve compared to Pub/Sub or Lists?

Durable, replayable messaging with per-consumer delivery and acknowledgment

What does GEODIST return?

The distance between two members of a geospatial index

What is the default maxmemory-policy in Redis?

noeviction

What is Redis Cluster?

A native sharding solution that distributes keys across nodes using 16384 hash slots

What is the main limitation of Pub/Sub compared to Streams?

Pub/Sub is fire-and-forget: messages are not stored and are lost without a subscriber

Drill this topic

120 flashcards on Redis Data Structures & Use Cases — free, no signup needed to start.

Study Redis Data Structures & Use Cases flashcards

LearnWiki pages are generated with AI assistance from LearnCoachAssist's reviewed study catalog and may contain errors — verify anything critical against your course materials.