---
title: "Redis Cache"
description: "Redis caching implementation and configuration"
keywords: [redis, cache, performance, in-memory]
---

# Redis Cache

Redis caching implementation for TraceRTM.

## Redis Setup

### Connection

```python
import redis.asyncio as redis

redis_client = redis.from_url(
    "redis://localhost:6379",
    decode_responses=True
)
```

### Connection Pool

```python
redis_pool = redis.ConnectionPool.from_url(
    "redis://localhost:6379",
    max_connections=50
)
redis_client = redis.Redis(connection_pool=redis_pool)
```

## Basic Operations

### Set/Get

```python
# Set value
await redis_client.set("key", "value")

# Get value
value = await redis_client.get("key")

# Set with expiration
await redis_client.setex("key", 3600, "value")  # 1 hour TTL
```

### JSON Data

```python
import json

# Store JSON
await redis_client.set(
    "item:123",
    json.dumps({"id": "123", "title": "Item"})
)

# Retrieve JSON
cached = await redis_client.get("item:123")
if cached:
    item = json.loads(cached)
```

## Advanced Operations

### Hash Operations

```python
# Store hash
await redis_client.hset(
    "item:123",
    mapping={
        "title": "Item Title",
        "status": "active",
        "view": "requirements"
    }
)

# Get hash
item = await redis_client.hgetall("item:123")

# Get single field
title = await redis_client.hget("item:123", "title")
```

### Sets

```python
# Add to set
await redis_client.sadd("project:123:items", "item_1", "item_2")

# Get set members
items = await redis_client.smembers("project:123:items")

# Check membership
is_member = await redis_client.sismember("project:123:items", "item_1")
```

### Sorted Sets

```python
# Add with score
await redis_client.zadd(
    "items:by_created",
    {"item_1": 1234567890, "item_2": 1234567900}
)

# Get range
recent = await redis_client.zrange(
    "items:by_created",
    0,
    9,
    desc=True
)
```

## Cache Patterns

### Cache-Aside with Redis

```python
async def get_item_cached(item_id: str):
    """Get item with Redis cache."""
    # Try cache
    cached = await redis_client.get(f"item:{item_id}")
    if cached:
        return json.loads(cached)
    
    # Cache miss
    item = await item_repo.get_by_id(item_id)
    
    if item:
        # Cache for 1 hour
        await redis_client.setex(
            f"item:{item_id}",
            3600,
            json.dumps(item)
        )
    
    return item
```

### Cache Invalidation

```python
async def invalidate_item_cache(item_id: str):
    """Invalidate item cache."""
    await redis_client.delete(f"item:{item_id}")
    
    # Invalidate related caches
    pattern = f"items:*:{item_id}"
    keys = await redis_client.keys(pattern)
    if keys:
        await redis_client.delete(*keys)
```

## Configuration

### Redis Settings

```python
REDIS_CONFIG = {
    "host": "localhost",
    "port": 6379,
    "db": 0,
    "password": None,
    "max_connections": 50,
    "socket_timeout": 5,
    "socket_connect_timeout": 5,
    "retry_on_timeout": True
}
```

### Environment Variables

```bash
REDIS_URL=redis://localhost:6379/0
REDIS_PASSWORD=your_password
REDIS_MAX_CONNECTIONS=50
```

## Monitoring

### Cache Statistics

```python
# Get info
info = await redis_client.info("stats")

# Get memory usage
memory = await redis_client.info("memory")

# Get keyspace
keyspace = await redis_client.info("keyspace")
```

## Best Practices

### 1. Use Appropriate TTL

```python
# Short TTL for frequently changing data
await redis_client.setex("item:123", 300, data)  # 5 minutes

# Long TTL for stable data
await redis_client.setex("config:app", 86400, data)  # 24 hours
```

### 2. Handle Cache Failures

```python
async def get_item_safe(item_id: str):
    """Get item with cache failure handling."""
    try:
        cached = await redis_client.get(f"item:{item_id}")
        if cached:
            return json.loads(cached)
    except Exception as e:
        logger.warning(f"Cache read failed: {e}")
    
    # Fallback to database
    return await item_repo.get_by_id(item_id)
```

### 3. Batch Operations

```python
# Batch get
keys = [f"item:{id}" for id in item_ids]
items = await redis_client.mget(keys)

# Batch set
pipeline = redis_client.pipeline()
for item in items:
    pipeline.setex(f"item:{item['id']}", 3600, json.dumps(item))
await pipeline.execute()
```

## Related Documentation

- [Caching](./06-caching) - Caching overview
- [Performance Optimization](./03a-query-optimization) - Performance tips
