1 min read
BackendRedis Stack: In-Memory Vector Database für AI
Redis als Vector Database nutzen. RediSearch, RedisJSON, Vector Set und High-Performance AI-Anwendungen.
Redis StackVector DatabaseRediSearchRedisJSONIn-Memory DatabaseAI Cache

Redis Stack: In-Memory Vector Database für AI
Meta-Description: Redis als Vector Database nutzen. RediSearch, RedisJSON, Vector Set und High-Performance AI-Anwendungen.
Keywords: Redis Stack, Vector Database, RediSearch, RedisJSON, In-Memory Database, AI Cache, Semantic Search
Einführung
Redis 8 vereint alle Module in einem Package: Vector Search, JSON, Full-Text Search und mehr. Als In-Memory Database bietet Redis ultra-niedrige Latenz für AI-Anwendungen – ideal für Caching, Session Management und Echtzeit-Suche.
Redis 8 Stack
┌─────────────────────────────────────────────────────────────┐
│ REDIS 8 STACK │
├─────────────────────────────────────────────────────────────┤
│ │
│ Core Data Structures: │
│ ├── Strings, Lists, Sets, Hashes, Sorted Sets │
│ ├── Streams (Event Streaming) │
│ └── HyperLogLog, Bitmaps │
│ │
│ New in Redis 8: │
│ ├── Vector Set (Beta) - Similarity Search │
│ ├── JSON - Native JSON Document Store │
│ ├── Time Series - Metrics & Monitoring │
│ └── Probabilistic Structures │
│ ├── Bloom Filter │
│ ├── Cuckoo Filter │
│ ├── Count-Min Sketch │
│ ├── Top-K │
│ └── T-Digest │
│ │
│ Search Capabilities: │
│ ├── Full-Text Search │
│ ├── Vector Search (FLAT, HNSW, SVS-VAMANA) │
│ ├── Numeric/Tag Filtering │
│ └── Geospatial Queries │
│ │
│ Performance: │
│ └── Sub-Millisecond Latency (In-Memory) │
│ │
└─────────────────────────────────────────────────────────────┘Setup
# Docker
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
# Redis Cloud (Managed)
# https://redis.com/try-free/// lib/redis.ts
import { createClient } from 'redis';
const redis = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379'
});
redis.on('error', (err) => console.error('Redis Client Error', err));
await redis.connect();
export default redis;Vector Search mit Hash
import redis from '@/lib/redis';
import { SchemaFieldTypes, VectorAlgorithms } from 'redis';
// 1. Index erstellen
async function createVectorIndex() {
try {
await redis.ft.create('idx:docs', {
'$.title': {
type: SchemaFieldTypes.TEXT,
AS: 'title'
},
'$.content': {
type: SchemaFieldTypes.TEXT,
AS: 'content'
},
'$.category': {
type: SchemaFieldTypes.TAG,
AS: 'category'
},
'$.embedding': {
type: SchemaFieldTypes.VECTOR,
AS: 'embedding',
ALGORITHM: VectorAlgorithms.HNSW,
TYPE: 'FLOAT32',
DIM: 1536,
DISTANCE_METRIC: 'COSINE'
}
}, {
ON: 'JSON',
PREFIX: 'doc:'
});
console.log('Index created');
} catch (e) {
if ((e as Error).message.includes('Index already exists')) {
console.log('Index already exists');
} else {
throw e;
}
}
}
// 2. Document speichern (JSON)
async function saveDocument(
id: string,
title: string,
content: string,
category: string,
embedding: number[]
) {
await redis.json.set(`doc:${id}`, '$', {
title,
content,
category,
embedding
});
}
// 3. Vector Search
async function searchSimilar(
queryEmbedding: number[],
limit: number = 5
) {
const results = await redis.ft.search('idx:docs', '*=>[KNN $K @embedding $BLOB AS score]', {
PARAMS: {
K: limit.toString(),
BLOB: Buffer.from(new Float32Array(queryEmbedding).buffer)
},
RETURN: ['title', 'content', 'score'],
SORTBY: {
BY: 'score',
DIRECTION: 'ASC' // Lower = more similar for COSINE
},
DIALECT: 2
});
return results.documents.map(doc => ({
id: doc.id,
title: doc.value.title,
content: doc.value.content,
score: 1 - parseFloat(doc.value.score as string) // Convert to similarity
}));
}
// 4. Hybrid Search (Vector + Filter)
async function searchWithFilter(
queryEmbedding: number[],
category: string,
limit: number = 5
) {
const results = await redis.ft.search(
'idx:docs',
`(@category:{${category}})=>[KNN $K @embedding $BLOB AS score]`,
{
PARAMS: {
K: limit.toString(),
BLOB: Buffer.from(new Float32Array(queryEmbedding).buffer)
},
RETURN: ['title', 'content', 'category', 'score'],
DIALECT: 2
}
);
return results.documents;
}Vector Set (Redis 8 Beta)
// Neuer Datentyp in Redis 8 - Inspiriert von Sorted Sets
// Vector hinzufügen
await redis.sendCommand([
'VADD', 'products',
'VECTOR', ...embedding.map(v => v.toString()),
'product:123'
]);
// Ähnliche Vektoren finden
const similar = await redis.sendCommand([
'VSIM', 'products',
'VECTOR', ...queryEmbedding.map(v => v.toString()),
'COUNT', '10'
]);
// Vorteile von Vector Set:
// - Einfachere API als RediSearch
// - Optimiert für Similarity Search
// - Von Salvatore Sanfilippo (Redis Creator) entwickeltSession Cache mit Vector Search
// Kombination: Session Management + Semantic Search
interface UserSession {
userId: string;
lastQuery: string;
queryEmbedding: number[];
searchHistory: string[];
createdAt: number;
expiresAt: number;
}
// Session speichern
async function saveSession(session: UserSession) {
const key = `session:${session.userId}`;
await redis.json.set(key, '$', session);
await redis.expireAt(key, session.expiresAt);
}
// Ähnliche Queries aus History finden
async function findSimilarPastQueries(
userId: string,
currentQueryEmbedding: number[]
) {
// Alle Sessions mit Query-History durchsuchen
const results = await redis.ft.search(
'idx:sessions',
'*=>[KNN 5 @queryEmbedding $BLOB AS score]',
{
PARAMS: {
BLOB: Buffer.from(new Float32Array(currentQueryEmbedding).buffer)
},
RETURN: ['userId', 'lastQuery', 'score'],
DIALECT: 2
}
);
return results.documents;
}Full-Text + Vector Hybrid Search
// Index mit Text + Vector
await redis.ft.create('idx:articles', {
'$.title': {
type: SchemaFieldTypes.TEXT,
AS: 'title',
WEIGHT: 2.0
},
'$.body': {
type: SchemaFieldTypes.TEXT,
AS: 'body'
},
'$.tags': {
type: SchemaFieldTypes.TAG,
AS: 'tags'
},
'$.embedding': {
type: SchemaFieldTypes.VECTOR,
AS: 'embedding',
ALGORITHM: VectorAlgorithms.HNSW,
TYPE: 'FLOAT32',
DIM: 1536,
DISTANCE_METRIC: 'COSINE'
}
}, {
ON: 'JSON',
PREFIX: 'article:'
});
// Hybrid Search: Text + Vector
async function hybridSearch(
textQuery: string,
queryEmbedding: number[],
limit: number = 10
) {
// Full-Text Search
const textResults = await redis.ft.search(
'idx:articles',
`@title|body:(${textQuery})`,
{
RETURN: ['title', 'body'],
LIMIT: { from: 0, size: limit }
}
);
// Vector Search
const vectorResults = await redis.ft.search(
'idx:articles',
'*=>[KNN $K @embedding $BLOB AS vector_score]',
{
PARAMS: {
K: limit.toString(),
BLOB: Buffer.from(new Float32Array(queryEmbedding).buffer)
},
RETURN: ['title', 'body', 'vector_score'],
DIALECT: 2
}
);
// Scores kombinieren (RRF - Reciprocal Rank Fusion)
const combined = new Map<string, { doc: any; score: number }>();
const k = 60; // RRF constant
textResults.documents.forEach((doc, rank) => {
const score = 1 / (k + rank + 1);
combined.set(doc.id, {
doc: doc.value,
score: score
});
});
vectorResults.documents.forEach((doc, rank) => {
const vectorScore = 1 / (k + rank + 1);
const existing = combined.get(doc.id);
if (existing) {
existing.score += vectorScore;
} else {
combined.set(doc.id, {
doc: doc.value,
score: vectorScore
});
}
});
return Array.from(combined.values())
.sort((a, b) => b.score - a.score)
.slice(0, limit);
}Caching für AI Embeddings
// Embedding Cache - vermeidet wiederholte API-Calls
async function getOrCreateEmbedding(
text: string,
generateFn: (text: string) => Promise<number[]>
): Promise<number[]> {
// Hash als Cache Key
const hash = await crypto.subtle.digest(
'SHA-256',
new TextEncoder().encode(text)
);
const cacheKey = `emb:${Buffer.from(hash).toString('hex').slice(0, 16)}`;
// Cache Check
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
// Generate & Cache
const embedding = await generateFn(text);
await redis.set(cacheKey, JSON.stringify(embedding), {
EX: 60 * 60 * 24 * 7 // 7 Tage TTL
});
return embedding;
}
// RAG Response Cache
async function getCachedRAGResponse(
queryEmbedding: number[],
threshold: number = 0.95
) {
// Suche nach sehr ähnlichen vorherigen Queries
const results = await redis.ft.search(
'idx:rag_cache',
'*=>[KNN 1 @queryEmbedding $BLOB AS score]',
{
PARAMS: {
BLOB: Buffer.from(new Float32Array(queryEmbedding).buffer)
},
RETURN: ['query', 'response', 'score'],
DIALECT: 2
}
);
if (results.documents.length > 0) {
const similarity = 1 - parseFloat(results.documents[0].value.score as string);
if (similarity >= threshold) {
return results.documents[0].value.response;
}
}
return null;
}Pub/Sub für Real-Time Updates
// Vector Search + Real-Time Updates
// Publisher
async function publishNewDocument(doc: Document) {
// In Redis speichern
await saveDocument(doc.id, doc.title, doc.content, doc.category, doc.embedding);
// Event publishen
await redis.publish('documents:new', JSON.stringify({
id: doc.id,
title: doc.title,
category: doc.category
}));
}
// Subscriber
const subscriber = redis.duplicate();
await subscriber.connect();
await subscriber.subscribe('documents:new', (message) => {
const doc = JSON.parse(message);
console.log('New document:', doc.title);
// UI Update, Cache Invalidation, etc.
});Fazit
Redis Stack bietet:
- Sub-Millisecond Latency: In-Memory für Echtzeit-AI
- Unified Platform: Vector, JSON, Full-Text in einem System
- Vector Set: Neuer Datentyp für einfache Similarity Search
- Caching Layer: Ideal für Embedding-Caches
Perfekt als High-Performance Layer vor AI-Anwendungen.
Bildprompts
- "In-memory database with vectors flowing at high speed, performance concept"
- "Redis logo with vector arrows and AI neural network, modern database"
- "Cache layer between AI model and application, latency optimization"