Appearance
Generate UUID in Redis
Redis doesn't have built-in UUID generation functions, but you can generate UUIDs using Lua scripts or in your client application. Here are the most common approaches:
lua
-- Lua script for UUID v4 generation in Redis
local function uuid4()
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function (c)
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
return string.format('%x', v)
end)
end
-- Generate and return UUID
return uuid4()
Most commonly, UUIDs are generated in client applications and used as Redis keys:
bash
# Generate UUID in client and use as Redis key
SET "550e8400-e29b-41d4-a716-446655440000" "user_session_data"
GET "550e8400-e29b-41d4-a716-446655440000"
# Use UUID for session management
SETEX "session:550e8400-e29b-41d4-a716-446655440000" 3600 '{"user_id": 123, "role": "admin"}'
# Use UUID for temporary data
HSET "temp:550e8400-e29b-41d4-a716-446655440000" "data" "temporary_value" "expires" "2024-12-31"
Lua Scripts for UUID Generation
UUID v4 Lua script:
lua
-- uuid_v4.lua
local function uuid4()
math.randomseed(redis.call('TIME')[1] * 1000000 + redis.call('TIME')[2])
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function (c)
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
return string.format('%x', v)
end)
end
-- Store UUID with data
local uuid = uuid4()
local key = KEYS[1] .. ':' .. uuid
redis.call('SET', key, ARGV[1])
redis.call('EXPIRE', key, ARGV[2] or 3600)
return uuid
Load and execute Lua script:
bash
# Load script and get SHA
redis-cli SCRIPT LOAD "$(cat uuid_v4.lua)"
# Returns: "a42059b356c875f0717db19a51f6aaca7734f8ca"
# Execute script
redis-cli EVALSHA a42059b356c875f0717db19a51f6aaca7734f8ca 1 "session" "user_data" 7200
# Returns: "550e8400-e29b-41d4-a716-446655440000"
Client-Side UUID Generation
Node.js with Redis:
javascript
const redis = require('redis');
const { v4: uuidv4, v1: uuidv1 } = require('uuid');
const client = redis.createClient();
async function examples() {
// Generate UUID in client and use as key
const sessionId = uuidv4();
await client.setex(`session:${sessionId}`, 3600, JSON.stringify({
userId: 123,
role: 'admin',
loginTime: new Date().toISOString()
}));
// Use UUID for cache keys
const cacheKey = `cache:${uuidv4()}`;
await client.set(cacheKey, 'cached_data', 'EX', 300);
// Generate time-based UUID for ordered data
const eventId = uuidv1();
await client.zadd('events', Date.now(), eventId);
// Store UUID mapping
const userId = 123;
const userUUID = uuidv4();
await client.hset('user_uuids', userId, userUUID);
await client.hset('uuid_users', userUUID, userId);
}
Python with Redis:
python
import redis
import uuid
import json
from datetime import datetime, timedelta
r = redis.Redis(host='localhost', port=6379, db=0)
# Generate UUID and use for session
session_id = str(uuid.uuid4())
session_data = {
'user_id': 123,
'role': 'admin',
'login_time': datetime.now().isoformat()
}
r.setex(f'session:{session_id}', 3600, json.dumps(session_data))
# Use UUID for temporary data
temp_id = str(uuid.uuid4())
r.hset(f'temp:{temp_id}', mapping={
'data': 'temporary_value',
'created': datetime.now().isoformat()
})
r.expire(f'temp:{temp_id}', 1800) # 30 minutes
# Generate deterministic UUID
namespace = uuid.NAMESPACE_URL
deterministic_id = str(uuid.uuid5(namespace, 'https://example.com'))
r.set(f'resource:{deterministic_id}', 'resource_data')
Advanced Redis UUID Patterns
Session management with UUIDs:
bash
# Create session with UUID
SET "session:550e8400-e29b-41d4-a716-446655440000" '{"user_id": 123, "role": "admin"}' EX 3600
# Session lookup
GET "session:550e8400-e29b-41d4-a716-446655440000"
# Session refresh
EXPIRE "session:550e8400-e29b-41d4-a716-446655440000" 3600
# Session cleanup (automatic with TTL)
# Sessions expire automatically
UUID-based rate limiting:
lua
-- rate_limit.lua
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local uuid = ARGV[3]
local current = redis.call('GET', key)
if current == false then
redis.call('SET', key, 1)
redis.call('EXPIRE', key, window)
return {1, limit}
else
current = tonumber(current)
if current < limit then
local new_val = redis.call('INCR', key)
return {new_val, limit}
else
return {current, limit, 'RATE_LIMITED'}
end
end
UUID-based distributed locking:
lua
-- distributed_lock.lua
local key = KEYS[1]
local uuid = ARGV[1]
local ttl = tonumber(ARGV[2])
local current = redis.call('GET', key)
if current == false then
redis.call('SET', key, uuid, 'EX', ttl)
return 1
elseif current == uuid then
redis.call('EXPIRE', key, ttl)
return 1
else
return 0
end
Performance Optimization
UUID key patterns:
bash
# Good: Use prefixes for organization
SET "user:550e8400-e29b-41d4-a716-446655440000" "user_data"
SET "session:550e8400-e29b-41d4-a716-446655440000" "session_data"
SET "cache:550e8400-e29b-41d4-a716-446655440000" "cached_data"
# Good: Use hash tags for Redis Cluster
SET "{user:123}:550e8400-e29b-41d4-a716-446655440000" "data"
SET "{user:123}:profile" "profile_data"
# Avoid: Very long keys (impacts memory)
# SET "very_long_prefix_that_uses_lots_of_memory:550e8400-e29b-41d4-a716-446655440000" "data"
Batch operations with UUIDs:
bash
# Pipeline multiple UUID operations
redis-cli --pipe <<EOF
SET session:550e8400-e29b-41d4-a716-446655440000 '{"user": 1}' EX 3600
SET session:6ba7b810-9dad-11d1-80b4-00c04fd430c8 '{"user": 2}' EX 3600
SET session:6ba7b811-9dad-11d1-80b4-00c04fd430c8 '{"user": 3}' EX 3600
EOF
# Use MSET for multiple UUID keys
MSET "uuid:550e8400-e29b-41d4-a716-446655440000" "value1" "uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" "value2"
Redis Cluster Considerations
UUID distribution in Redis Cluster:
javascript
const Redis = require('ioredis');
const { v4: uuidv4 } = require('uuid');
const cluster = new Redis.Cluster([
{ host: '127.0.0.1', port: 7000 },
{ host: '127.0.0.1', port: 7001 },
{ host: '127.0.0.1', port: 7002 }
]);
async function clusterExamples() {
// UUIDs distribute well across cluster slots
const uuid1 = uuidv4();
const uuid2 = uuidv4();
await cluster.set(`session:${uuid1}`, 'data1');
await cluster.set(`session:${uuid2}`, 'data2');
// Use hash tags to keep related data together
const userId = 123;
const sessionUUID = uuidv4();
await cluster.set(`{user:${userId}}:session`, sessionUUID);
await cluster.set(`{user:${userId}}:profile`, 'profile_data');
}
Monitoring and Analytics
UUID-based metrics:
bash
# Count active sessions by pattern
EVAL "return #redis.call('KEYS', 'session:*')" 0
# Get session statistics
EVAL "
local sessions = redis.call('KEYS', 'session:*')
local active = 0
local total = #sessions
for i=1,total do
local ttl = redis.call('TTL', sessions[i])
if ttl > 0 then
active = active + 1
end
end
return {total, active}
" 0
UUID cleanup and maintenance:
lua
-- cleanup_expired.lua
local pattern = KEYS[1]
local batch_size = tonumber(ARGV[1]) or 100
local keys = redis.call('SCAN', 0, 'MATCH', pattern, 'COUNT', batch_size)
local expired = 0
for i=1,#keys[2] do
local ttl = redis.call('TTL', keys[2][i])
if ttl == -1 then -- No expiration set
redis.call('DEL', keys[2][i])
expired = expired + 1
end
end
return expired
UUID Version Comparison
Choose the right UUID version for Redis:
- Version 1 - Time-based, good for ordered data in sorted sets
- Version 3 - MD5 namespace-based, deterministic keys
- Version 4 - Random, most popular for sessions and cache keys
- Version 5 - SHA-1 namespace-based, better than v3 for deterministic keys
- Version 6 - Time-ordered, excellent for time-series data
- Version 7 - Modern time-based, best for ordered operations
For Redis applications:
- Session management: Use Version 4 for maximum randomness
- Cache keys: Use Version 4 for even distribution
- Time-series data: Use Version 7 for chronological ordering
- Deterministic keys: Use Version 5 for consistent resource mapping
How do I generate UUID in other databases?
SQL databases:
- PostgreSQL - Comprehensive UUID support with extensions
- MySQL - Built-in UUID() function
- SQL Server - NEWID() and NEWSEQUENTIALID()
- SQLite - Custom functions and extensions
NoSQL databases: