Chapter 02 · Keys, Namespaces, Expiration, TTL, Scanning, and Data-Type Introspection
TYPE, OBJECT, MEMORY USAGE, DUMP/RESTORE, COPY, RENAME, UNLINK, and Deletion Cost
Inspect Redis values and internal representation, estimate memory, serialize and restore values safely, copy or rename keys deliberately, and choose deletion behavior from operational cost.
Learning outcomes
AtlasMart is preparing a data-model migration. Operations can discover the target keys, but now it must answer harder questions safely: Is this key a string, hash, list, or something else? Which internal representation is Redis using? How much memory is attributed to it? Can the value be copied or moved without losing compatibility? Will renaming overwrite something? Will deleting a large collection pause command processing while memory is reclaimed? This lesson connects introspection and movement commands to those operational consequences.
Distinguish logical Redis data type from version-sensitive internal encoding and memory accounting.
Use TYPE, OBJECT ENCODING, MEMORY USAGE, and TTL/PTTL as evidence without over-interpreting them.
Explain DUMP/RESTORE serialization, RDB-version/checksum compatibility, and why DUMP does not carry TTL metadata.
Choose COPY, RENAME/RENAMENX, or explicit migration from overwrite, topology, and lifetime requirements.
Choose DEL or UNLINK from deletion complexity and latency risk, then verify logical deletion separately from asynchronous memory reclamation.
All Chapter 02 labs reuse the disposable Chapter 01
environment: Redis Open Source 8.10.1 from
Docker Official Image redis:8.10.1, container
atlasmart-redis-ch01, standalone topology, host
publication 127.0.0.1:6379, TLS disabled because
traffic stays on loopback, default user disabled, named ACL
users atlasmart-app and
academy-admin, logical database 0, AOF with
appendfsync everysec plus RDB snapshots, and a
persistent /data Docker volume. No explicit
maxmemory limit or eviction policy is introduced
in this chapter. Search, JSON, vector, time-series, and
probabilistic features are not required for these exercises.
The lab creates bounded strings, hashes, and a 5,000-element
list under atlasmart:ch02:. It does not claim
that 5,000 elements are “large” in production; the list merely
makes asynchronous reclamation easier to discuss safely.
1. TYPE is the public data-structure contract; OBJECT exposes implementation evidence
TYPE key reports the Redis data type visible to
commands, such as string, hash,
list, set, zset, or
stream. Code should normally branch on the
application schema, not dynamically guess types, but TYPE is
valuable in diagnostics and migration validation.
OBJECT ENCODING key reports the internal
representation Redis currently uses for that value. Redis may
choose compact representations for small collections and switch
representations as size/shape changes. The encoding name is an
implementation detail that can change by Redis version or
dataset shape; it is evidence for capacity diagnosis, not a
stable application API.
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app HSET atlasmart:ch02:inspect:product:7 name "Desk Lamp" stock 18 price 39.50docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin TYPE atlasmart:ch02:inspect:product:7docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin OBJECT ENCODING atlasmart:ch02:inspect:product:7# TYPE should be "hash".# OBJECT ENCODING is version/data dependent; record it rather than asserting one universal value.
2. MEMORY USAGE estimates bytes attributable to a key/value
MEMORY USAGE key returns the number of bytes Redis
attributes to a key and its value, including administrative
overhead. For nested data structures, Redis can sample elements;
the optional SAMPLES argument controls that
estimate, and SAMPLES 0 asks Redis to sample all
nested elements. More exhaustive sampling can cost more work.
The result still does not equal total process resident memory
because allocator fragmentation, client buffers, replication/AOF
buffers, fork copy-on-write, and integrated indexes consume
memory outside one key.
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app SET atlasmart:ch02:inspect:string "1234567890"docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin MEMORY USAGE atlasmart:ch02:inspect:stringdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin MEMORY USAGE atlasmart:ch02:inspect:product:7 SAMPLES 0# Expect positive integers. Exact bytes depend on Redis build, allocator, encoding, and data shape.
Redis 8.10 includes version-specific memory-accounting changes for some compact hash representations. This is exactly why capacity documents should record the server version, representative value distribution, and sampling method beside the number.
3. DUMP serializes the value; RESTORE validates and recreates it
DUMP key returns an opaque, Redis-specific
serialized representation of the value using Redis Database
(RDB) serialization, including version/checksum information. It
is binary data, not JSON and not a supported format for
hand-editing. Critically, the payload does
not contain the key’s expiration. If a
migration needs the remaining lifetime, capture
PTTL separately.
RESTORE key ttl serialized-value recreates a value
from a DUMP-compatible payload. The TTL argument is in
milliseconds; 0 makes the restored key persistent. RESTORE
validates checksum/RDB compatibility and can reject corrupt or
incompatible payloads. REPLACE permits overwriting
an existing destination; ABSTTL interprets the TTL
argument as an absolute Unix millisecond timestamp. Treat these
options as explicit migration policy.
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app SET atlasmart:ch02:dump:source "serialized-value" PX 180000docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin PTTL atlasmart:ch02:dump:sourcedocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user academy-admin DUMP atlasmart:ch02:dump:source# redis-cli renders the opaque binary payload in an escaped form for the terminal.# The PTTL must be carried separately if migration must preserve remaining lifetime.
Do not copy the escaped terminal rendering into a text file and assume it is the original bytes. Production migration code must transport the binary DUMP payload losslessly and preserve/translate TTL deliberately. Redis MIGRATE or a maintained binary-safe client can be preferable when its exact topology/operational semantics fit.
4. COPY duplicates; RENAME changes identity and may overwrite
COPY source destination creates another key
containing the source value. By default it fails if the
destination exists; REPLACE allows overwrite. The
optional DB target is a standalone logical-database
feature and is not a portable Cluster partitioning strategy. For
collection values, copying can require work proportional to the
value size, so copying “one key” is not automatically cheap.
RENAME source destination atomically changes the
key name in the current server context, but if the destination
already exists it is replaced. RENAMENX refuses
when the destination exists. The source TTL follows a RENAME. In
Cluster, multi-key operations have slot-locality constraints; a
future naming/hash-tag scheme can determine whether a
server-side rename/copy is legal. Never freeze standalone
assumptions into a Cluster migration tool.
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app SET atlasmart:ch02:move:source "v1" EX 300# COPY fails safely if destination exists unless REPLACE is requested.docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app COPY atlasmart:ch02:move:source atlasmart:ch02:move:copy# (integer) 1 on first copy# RENAMENX protects an unexpected destination.docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app RENAMENX atlasmart:ch02:move:source atlasmart:ch02:move:renamed# (integer) 1 when destination did not existdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 \ redis-cli --user atlasmart-app TTL atlasmart:ch02:move:renamed# positive: source expiry moved with the renamed key
For COPY, verify the destination TTL on the exact target release/client and state the intended policy explicitly; for cross-version migrations, validate both value and lifetime after restore/copy instead of assuming all metadata semantics from memory.
5. DEL and UNLINK separate keyspace removal from memory reclamation differently
DEL removes a key and reclaims its value as part of
the command’s work. The cost for some complex values grows with
the number of elements. UNLINK first detaches the
key from the keyspace in O(1) per key and schedules actual
memory reclamation on a background lazy-free thread. The key
becomes logically absent immediately from client perspective,
while memory may be reclaimed later.
This separation is valuable for large collections when
synchronous freeing would threaten latency, but it is not magic:
the background work still consumes CPU/memory bandwidth, and a
burst of huge unlinks can create a backlog. Observe
lazyfree_pending_objects in
INFO memory rather than claiming deletion is
“free.” For small strings, DEL can be perfectly appropriate.
# Build one bounded collection inside the disposable chapter prefix.docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 sh -lc 'redis-cli --user atlasmart-app LPUSH atlasmart:ch02:biglist $(seq 1 5000) >/dev/null'docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin LLEN atlasmart:ch02:biglistdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin MEMORY USAGE atlasmart:ch02:biglist SAMPLES 0docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 sh -lc 'redis-cli --user academy-admin INFO memory | grep lazyfree_pending_objects'docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app UNLINK atlasmart:ch02:biglist# (integer) 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app EXISTS atlasmart:ch02:biglist# 0 immediately from keyspace perspectivedocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 sh -lc 'redis-cli --user academy-admin INFO memory | grep lazyfree_pending_objects'# May already be 0 on a fast machine; the exact transient value is timing-dependent.
6. Deliberately wrong migration: overwrite, drop TTL, and block on cleanup
A brittle AtlasMart script scans old keys, converts terminal-rendered DUMP output into text, RESTOREs every destination with TTL 0, uses RENAME without checking for an existing destination, then DELs huge old collections during peak traffic. It risks corrupted binary payloads, accidental persistent copies, destination data loss, and latency spikes.
The repair is a staged migration: inventory source TYPE/TTL/memory; define collision policy; transport serialized bytes with a binary-safe mechanism; validate target compatibility; preserve or intentionally transform TTL; use COPY/RENAMENX/RESTORE REPLACE only when policy says so; verify checksums/value/schema/application reads; switch traffic; then choose UNLINK or bounded DEL based on measured deletion cost. Keep source data until rollback criteria expire.
| Evidence before move | Why it matters |
|---|---|
TYPE + application schema |
Prevents interpreting one data structure as another. |
OBJECT ENCODING |
Diagnostic implementation evidence; useful for memory investigation, not a portability contract. |
MEMORY USAGE |
Highlights big-key/migration/deletion risk. |
PTTL |
Captures lifetime because DUMP does not include TTL. |
| destination EXISTS/TYPE | Prevents accidental overwrite or schema collision. |
| server version/topology | Determines serialization/command/Cluster compatibility boundaries. |
7. Hands-on lab: introspect, copy, rename, and clean up
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch02:migrate:product:9 name "Chair" stock 12docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app EXPIRE atlasmart:ch02:migrate:product:9 600docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin TYPE atlasmart:ch02:migrate:product:9docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin OBJECT ENCODING atlasmart:ch02:migrate:product:9docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin MEMORY USAGE atlasmart:ch02:migrate:product:9 SAMPLES 0docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PTTL atlasmart:ch02:migrate:product:9docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app COPY atlasmart:ch02:migrate:product:9 atlasmart:ch02:migrate:product:9:copydocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app RENAMENX atlasmart:ch02:migrate:product:9:copy atlasmart:ch02:migrate:product:9:stageddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HGETALL atlasmart:ch02:migrate:product:9:stageddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app PTTL atlasmart:ch02:migrate:product:9:staged
The exact copied TTL behavior should be recorded from your target Redis 8.10.1 lab rather than treated as an undocumented assumption in a migration plan. The validation requirement is explicit: source and destination value, TTL policy, type, and application behavior must match the migration design.
Verification checklist:
- You distinguish TYPE (public data structure) from OBJECT ENCODING (implementation detail).
- You recorded MEMORY USAGE with its server version and sampling choice instead of treating bytes as a universal constant.
- You can explain why DUMP bytes are opaque and why TTL must be carried separately for DUMP/RESTORE migration.
- You used a collision-aware operation such as COPY without REPLACE or RENAMENX before allowing overwrite.
- You observed that UNLINK makes the key absent before asynchronous reclamation necessarily finishes.
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app UNLINK \ atlasmart:ch02:inspect:product:7 atlasmart:ch02:inspect:string atlasmart:ch02:dump:source \ atlasmart:ch02:move:copy atlasmart:ch02:move:renamed \ atlasmart:ch02:migrate:product:9 atlasmart:ch02:migrate:product:9:copy atlasmart:ch02:migrate:product:9:staged atlasmart:ch02:biglist
8. Production judgment
Introspection commands are diagnostic tools, not schema governance. Querying OBJECT/MEMORY across every key can itself become expensive; sample representative distributions. DUMP/RESTORE are useful for value movement when versions/topologies are compatible and binary/TTL handling is explicit, but tested backups and migrations require much more: configuration, ACL/TLS state, persistence files, indexes, application reconciliation, RPO/RTO, and rollback.
Choose deletion by measured value complexity and latency budget. UNLINK reduces synchronous reclamation work but can transfer pressure to background threads; monitor lazy-free backlog and memory. Replication propagates mutations asynchronously, Sentinel can fail over to replicas, and Cluster adds slot-locality rules. Client timeouts/retries around COPY/RENAME/RESTORE must use idempotent staging names and post-condition checks. Never infer migration success merely from a command returning OK.
9. Summary and next step
TYPE identifies the logical Redis data structure; OBJECT exposes version-sensitive implementation evidence; MEMORY USAGE estimates per-key bytes. DUMP carries opaque serialized value bytes but no TTL, while RESTORE recreates compatible values under an explicit lifetime/collision policy. COPY duplicates, RENAME changes identity and can overwrite, and UNLINK separates keyspace removal from asynchronous memory reclamation. The final lesson turns all of these mechanics into a production lifecycle policy.
Check your understanding
- Why should application code not depend on OBJECT ENCODING names?
- Does DUMP include a key’s TTL?
- What risk distinguishes RENAME from RENAMENX?
- Why can UNLINK improve latency for large values?
- What does MEMORY USAGE not include?
Review the answers
1. Encoding is an internal, version/data-dependent implementation choice. TYPE and the application schema are the stable behavioral contracts.
2. No. Capture PTTL separately and pass an explicit TTL/ABSTTL policy to RESTORE if lifetime matters.
3. RENAME can replace an existing destination; RENAMENX refuses if the destination already exists.
4. It detaches keys from the keyspace quickly and performs memory reclamation asynchronously, avoiding all deallocation work in the foreground command.
5. It is per-key accounting, not total process RSS; allocator fragmentation, client/replication/AOF buffers, fork copy-on-write, indexes, and other process overhead can live outside that number.
Authoritative references
- TYPE command — logical Redis data type
- OBJECT ENCODING command — internal representation evidence
- MEMORY USAGE command — per-key memory accounting and SAMPLES
- DUMP command — RDB serialization, checksum/version, no TTL
- RESTORE command — deserialization, TTL, REPLACE/ABSTTL, compatibility checks
- COPY command — copy semantics and destination policy
- RENAME command — rename/overwrite and TTL transfer
- UNLINK command — asynchronous memory reclamation