16.3.3. Keys and Values
Table of Contents
Understanding Keys and Values in Redis
Redis is a key value store, so everything starts with understanding what a key is and what a value is. Even when you later work with lists, sets, hashes, and more complex data, they are still stored under keys.
In this chapter you will learn how keys and values work in Redis, how to choose good keys, and how to store and retrieve data.
What Is a Key in Redis?
A key in Redis is a string that uniquely identifies a piece of data. You can think of it as a variable name or as a row primary key in a database, but it is always a string.
Some examples of valid keys:
"user:1"
"session:abc123"
"cart:42"
"config:site_name"
"counter:visits"Keys:
- Are always strings internally, even if they look like numbers.
- Point to one value each.
- Must be unique in a given Redis database.
If you set the same key again, you overwrite the old value.
Basic rule:
Each Redis key maps to exactly one value at a time.
What Is a Value in Redis?
A value is the data stored under a key. In Redis, values can be of different types, such as:
- Simple string (text or binary data)
- List
- Set
- Sorted set
- Hash
- Stream
- Other specialized types
In this chapter we focus on the idea of key and value in general, and especially on string values, since many commands work with strings.
Examples:
- Key
"username:1"β Value"alice" - Key
"counter:page_views"β Value"1032" - Key
"image:logo"β Value is binary image data - Key
"config:maintenance_mode"β Value"true"
Even numbers are stored as strings by default. Redis can interpret some string values as integers for operations like INCR, but they are still stored as strings.
Basic Key Value Commands
The most important commands for simple key value operations are:
SET: Store a Value
SET saves a value under a key.
SET user:1:name "Alice"
SET user:1:age "30"- If
user:1:namedoes not exist, Redis creates it. - If it already exists, Redis overwrites its value.
You can also store numbers as strings:
SET counter:visits "0"GET: Retrieve a Value
GET returns the value stored under a key.
GET user:1:name
# "Alice"
GET user:1:age
# "30"
If the key does not exist, GET returns a special null reply:
GET user:2:name
# (nil) (means "no value")EXISTS: Check If a Key Exists
EXISTS tells you if a key is present.
EXISTS user:1:name
# (integer) 1 (exists)
EXISTS user:2:name
# (integer) 0 (does not exist)DEL: Delete Keys
DEL removes one or more keys and their values.
DEL user:1:name
DEL user:1:age
DEL returns how many keys were removed:
DEL user:1:name user:1:age
# (integer) 2If you delete a key, the value is gone and memory is freed.
Key Naming Conventions
Choosing good key names is very important in Redis. There are no tables or schemas, so key names are your main way to organize data.
Common Pattern: Use `:` as a Separator
Most Redis users follow a convention similar to:
<namespace>:<object_type>:<id>:<field>Examples:
user:1:nameuser:1:emailuser:2:emailsession:abc123:user_idcart:42:itemsorder:2024-0001:status
This is not mandatory, but it makes keys:
- Easier to understand.
- Easier to list and search with patterns.
- More consistent across your code.
Examples of Good vs Bad Key Names
| Purpose | Good key name | Bad key name | Why good? |
|---|---|---|---|
| User name for id 1 | user:1:name | name1 | Clear model and id |
| User email for id 12 | user:12:email | u12e | Easy to read, no guesswork |
| Shopping cart for user 5 | cart:user:5 | cart5 | Contains both cart and user in name |
| Global page view counter | counter:page_views | pv | Indicates purpose clearly |
| Feature flag: new_checkout | feature:new_checkout | flag1 | Meaningful name, easy to search/filter |
Avoiding Key Collisions
If you mix different types of data, you must name keys carefully to avoid collisions.
Bad:
SET user:1 "Alice"
SET user:1 "something else" # Overwrites the previous valueBetter:
SET user:1:name "Alice"
SET user:1:age "30"Or store structured data under a single key using another type (this is covered in the data structures chapter).
Key Length and Limits
Redis allows keys up to 512 MB in length, but you should not use very long keys.
Practical guidelines:
- Keep keys short but meaningful.
- Avoid putting entire texts, JSON objects, or long URLs directly in keys.
- Put such data in the value, not the key.
Bad:
"user:{"id":1,"name":"Alice","email":"alice@example.com"}"Good:
"user:1"Where the value contains the data (as a string, JSON, hash, etc).
Working With Numeric Values
Even though Redis stores values as strings, you often want to work with numbers. Redis provides atomic operations for integer values.
INCR and DECR
INCR increases a numeric value by 1. Redis interprets the value as an integer.
SET counter:visits "0"
INCR counter:visits
# (integer) 1
INCR counter:visits
# (integer) 2
GET counter:visits
# "2"
DECR decreases by 1:
DECR counter:visits
# (integer) 1
**The value must be a valid integer string, such as "0", "42", or "-5".
If the value is not an integer string, commands like INCR will fail.**
Example of an error:
SET counter:visits "hello"
INCR counter:visits
# (error) ERR value is not an integer or out of rangeINCRBY and DECRBY
You can change a numeric value by more than 1:
SET counter:downloads "10"
INCRBY counter:downloads 5
# (integer) 15
DECRBY counter:downloads 3
# (integer) 12Example: Implementing a Simple Page View Counter
Imagine you want to count how many times a page is viewed.
Each time a user opens the page:
INCR counter:page:homeTo display the count:
GET counter:page:home
# "123"
In code (Python with redis-py style client):
import redis
r = redis.Redis(host="localhost", port=6379, db=0)
def track_page_view(page_id: str) -> int:
key = f"counter:page:{page_id}"
new_value = r.incr(key) # INCR command
return new_value
views = track_page_view("home")
print("Home page views:", views)Key Expiration and Temporary Values
Sometimes you want a key to exist only for a limited time, for example for a login session, a password reset token, or a cache entry.
Redis supports key expiration. After a certain time, the key is automatically deleted.
SET with EX
You can set a key with a time to live in seconds:
SET session:abc123 "user:1" EX 60
This creates session:abc123 which will live for 60 seconds.
After 60 seconds:
GET session:abc123
# (nil)
You can use PX for milliseconds:
SET temp:code "123456" PX 300000 # 5 minutesEXPIRE Command
You can set or change expiration after creating a key:
SET session:abc123 "user:1"
EXPIRE session:abc123 120 # 120 seconds
EXPIRE returns 1 if the timeout was set, 0 if the key does not exist.
Check remaining time to live with TTL:
TTL session:abc123
# (integer) 97 (seconds left)
**When a key expires, it is automatically deleted and cannot be recovered.
Always handle the case where an expected key no longer exists.**
Listing and Searching Keys
For learning and testing, you might want to see what keys exist.
KEYS (for development only)
KEYS lets you search for keys that match a pattern:
KEYS *
# lists all keys
KEYS "user:*"
# lists all keys starting with "user:"
KEYS "session:*:user*"
# lists keys matching the patternPatterns use glob style wildcards:
| Pattern | Meaning |
|---|---|
* | Match any number of characters |
? | Match any single character |
[abc] | Match any one character in the set |
However:
**Never use KEYS in production on large databases.
It can block Redis while scanning all keys.
Use SCAN instead for production systems.**
SCAN is more advanced and covered elsewhere. For now, just know that KEYS is fine for a small local instance when learning.
Overwriting and Replacing Values
Since each key maps to one value, if you call SET multiple times with the same key, Redis always stores the latest value.
Example:
SET user:1:name "Alice"
GET user:1:name
# "Alice"
SET user:1:name "Bob"
GET user:1:name
# "Bob"You can also control overwriting behavior:
SETNX: Set Only If Not Exists
SETNX means "SET if Not eXists":
SETNX config:site_name "MySite"
# (integer) 1 (key created)
SETNX config:site_name "OtherSite"
# (integer) 0 (key already exists, not changed)
GET config:site_name
# "MySite"This is useful when you want to initialize settings or create locks without overwriting existing data.
Practical Key and Value Patterns
1. Caching Example
Imagine you have a slow database query to get a product by id.
You can cache the result:
- Key:
cache:product:<id> - Value: JSON representation of the product
- Expiration: 60 seconds
Commands:
SET cache:product:42 '{"id":42,"name":"Phone","price":299}' EX 60
GET cache:product:42In code:
def get_product_cached(product_id: int):
key = f"cache:product:{product_id}"
cached = r.get(key)
if cached is not None:
return cached # in real code, decode JSON
# simulate slow database query
product = {"id": product_id, "name": "Phone", "price": 299}
r.set(key, json.dumps(product), ex=60)
return product2. Session Example
For user sessions after login:
- Key:
session:<session_id> - Value: user id or serialized session data
- Expiration: lifetime of the session
SET session:abc123 "user:1" EX 3600
GET session:abc123
# "user:1"3. Feature Flags Example
To control features in your app:
- Key:
feature:<feature_name> - Value:
"on"or"off", or"true"and"false"
SET feature:new_checkout "on"
GET feature:new_checkout
# "on"Inspecting Key Types
As mentioned, Redis values can be different types. To see the type of a given key, use TYPE:
SET user:1:name "Alice"
TYPE user:1:name
# string
LPUSH user:1:logins "2024-01-01"
TYPE user:1:logins
# listThis is useful when debugging your data model.
**Do not mix different types under the same key.
If a key is used as a string, do not later use list commands on it.
Always keep one key associated with one consistent type.**
Summary
In Redis, everything starts with keys and values:
- A key is a string that uniquely identifies a single value.
- A value can be a simple string or a complex data type.
- Use
SET,GET,DEL,EXISTSto manage basic key value pairs. - Use clear and consistent key naming conventions, often with
:as a separator. - Keys are always strings, and values are often strings, even when representing numbers.
- Use
INCR,DECR,INCRBY,DECRBYto handle numeric values safely. - Use expirations (
EX,PX,EXPIRE) for temporary data. - Be careful with
KEYSin production, and avoid changing types for existing keys.
With these basics, you can model many common backend problems, such as counters, sessions, and caches, using Redis keys and values.
Views: 6
KAHIBARO