Strategia di Archiviazione: Valkey vs JSON vs NumPy
Questo articolo spiega perché utilizziamo diverse tecnologie di archiviazione per diversi tipi di dati nel pipeline SEO e nel servizio di ricerca.
Il Problema: Una Soluzione Non Va Bene per Tutto
Dati diversi hanno pattern di accesso diversi:
-
Embedding (5K x 384 float): Necessitano di operazioni vettoriali veloci (similarità del coseno)
-
Mappature di frasi (2500+ frasi): Necessitano di editing umano, controllo delle versioni
-
Cache delle query (query in tempo reale): Necessitano di ricerche chiave-valore veloci, scadenza TTL
-
Dati dei prodotti (64K prodotti): Necessitano di accesso strutturato, regole di compatibilità
Usare la stessa archiviazione per tutto sarebbe inefficiente.
Tre Tecnologie di Archiviazione
1. Array NumPy: Operazioni Vettoriali
Caso d'uso: Embedding (prodotti, query, frasi)
Perché NumPy:
-
Matematica vettoriale veloce: Librerie C/Fortran ottimizzate per operazioni matriciali
-
File mappati in memoria: Carica array di grandi dimensioni senza copiarli nella RAM
-
Operazioni in batch: Elabora migliaia di vettori in millisecondi
-
Formato standard: Compatibile con librerie ML (scikit-learn, TensorFlow)
Formato file: File binari .npy
Caricamento:
import numpy as np
# Mappato in memoria (non carica l'intero file nella RAM)
embeddings = np.load('embeddings.npy', mmap_mode='r')
# Calcola la similarità del coseno
from sklearn.metrics.pairwise import cosine_similarity
similarities = cosine_similarity(query_embedding, embeddings)
Prestazioni: ricerche di similarità massicce a velocità adatte per inferenza in tempo reale.
2. File JSON: Dati Editabili dall'Uomo
Caso d'uso: Configurazione, mappature, metadati
Perché JSON:
-
Leggibile dall'uomo: Facile da ispezionare e debuggare
-
Controllo delle versioni: Le differenze Git mostrano esattamente cosa è cambiato
-
Editing manuale: Possibilità di correggere errori senza codice
-
Formato universale: Ogni linguaggio può analizzare JSON
Cosa archiviamo:
-
Mappature frase-filtro: frasi → regole di filtro
-
Caratteristiche del prodotto: prodotti → dizionari di caratteristiche
-
Metadati delle query: query → clic, impressioni, sorgenti
-
Configurazione del pipeline: Parametri degli step, soglie
Formato file: File di testo .json
Caricamento:
import json
with open('phrase_mappings.json') as f:
mappings = json.load(f)
# Accesso ai dati
filters = mappings['mini pc'] # ['form_factor:mini', 'category:pc']
3. Valkey (Redis): Cache Chiave-Valore Veloce
Caso d'uso: Ricerca in tempo reale, autocompletamento, query popolari
Perché Valkey:
-
In memoria: Latenza in microsecondi per le ricerche
-
RediSearch: Ricerca di similarità vettoriale con indici
-
Scadenza TTL: Invalidazione automatica della cache
-
Pub/sub: Aggiornamenti in tempo reale tra server
-
Persistenza: Snapshot su disco opzionali per durabilità
Cosa archiviamo:
-
Cache degli embedding delle query: Query recenti → embedding
-
Query popolari: Top 1000 query per traffico
-
Indice di autocompletamento: Prefisso → suggerimenti di query
-
Cache di estrazione filtri: Query → filtri estratti
-
Cache di ricerche correlate: Query → query correlate
Strutture dati:
-
Stringhe: Semplice chiave-valore (query → embedding)
-
Set ordinati: Dati classificati (query popolari per punteggio)
-
Indici RediSearch: Ricerca di similarità vettoriale
-
Hash: Dati strutturati (metadati query)
Caricamento:
from app.shared.valkey_cache import get_valkey
valkey = get_valkey()
# ... (dettagli implementativi omessi)
Matrice Decisionale
Quando Usare NumPy
Criteri:
-
I dati sono numerici (float, int)
-
Necessità di operazioni vettoriali veloci (prodotto scalare, similarità del coseno)
-
I dati sono prevalentemente in lettura (raramente aggiornati)
-
I dati sono di grandi dimensioni (milioni di numeri)
-
Elaborazione in batch (elabora molti elementi contemporaneamente)
Esempi:
-
Embedding (prodotti, query, frasi)
-
Vettori di caratteristiche
-
Matrici di similarità
Quando Usare JSON
Criteri:
-
I dati sono strutturati (oggetti, array)
-
Necessità di leggibilità umana
-
Necessità di controllo delle versioni (Git)
-
I dati cambiano occasionalmente (modifiche manuali)
-
I dati sono piccoli-medio (<100 MB)
Esempi:
-
File di configurazione
-
Mappature di frasi
-
Metadati del prodotto
-
Parametri del pipeline
Quando Usare Valkey
Criteri:
-
Necessità di ricerche veloci (microsecondi)
-
I dati cambiano frequentemente (query in tempo reale)
-
Necessità di scadenza TTL (invalidazione cache)
-
Necessità di pub/sub (aggiornamenti in tempo reale)
-
Necessità di ricerca vettoriale (RediSearch)
Esempi:
-
Cache delle query
-
Autocompletamento
-
Query popolari
-
Dati di sessione
-
Limitazione della frequenza
Approccio Ibrido
Combiniamo tutti e tre per prestazioni ottimali:
Pipeline (Elaborazione Offline)
NumPy: Calcola embedding, matrici di similarità
JSON: Archivia mappature, metadati, configurazione
Valkey: Non utilizzato (la pipeline funziona offline)
Servizio di Ricerca (Query in Tempo Reale)
NumPy: Carica embedding dal disco (mappati in memoria)
JSON: Carica mappature dal disco (cache in memoria)
Valkey: Cache delle query in tempo reale, autocompletamento, query popolari
Flusso dei Dati
graph LR
Pipeline[Pipeline SEO
Offline]
subgraph Storage
NP[File NumPy
embeddings.npy]
JS[File JSON
mappings.json]
end
Search[Servizio di Ricerca
Live]
VK[Valkey
Cache]
Pipeline --> NP
Pipeline --> JS
NP --> Search
JS --> Search
Search --> VK
VK --> SearchConfronto delle Prestazioni
NumPy (mappato in memoria):
-
Tempo di caricamento: Istantaneo (mappatura zero-copy nella memoria virtuale)
-
Tempo di ricerca: Quasi zero (puntatore CPU diretto all'indice dell'array)
-
Memoria: Minima (cache di pagine gestita dal SO, non residente nella RAM del processo)
JSON:
-
Tempo di caricamento: Latenza elevata (analisi sequenziale e creazione oggetti)
-
Tempo di ricerca: Efficiente (overhead standard della mappa hash)
-
Memoria: Sostanziale (l'intera struttura serializzata risiede nell'heap)
Valkey:
-
Tempo di caricamento: Persistente (residente nel servizio in background)
-
Tempo di ricerca: Moderato (include round-trip di rete e serializzazione del protocollo)
-
Memoria: Esternalizzata (isolata all'interno del processo del database)
Vincitore: NumPy per l'elaborazione in batch ad alta velocità, Valkey per l'accesso distribuito a chiave singola
Ricerca di Similarità Vettoriale
NumPy (cosine_similarity):
-
Operazioni in batch: Rapide (ottimizzate tramite algebra lineare vettoriale/SIMD)
-
Parallelizzabile: Alta (si adatta a tutti i core CPU fisici disponibili)
-
Memoria: Lineare (si adatta direttamente alle dimensioni degli embedding)
Valkey (RediSearch):
-
Velocità di ricerca: Superiore (utilizza indicizzazione vettoriale HNSW/specializzata)
-
Parallelizzabile: Limitata (vincolata dal modello di threading del motore)
-
Memoria: Intensiva (richiede embedding grezzi più metadati di indicizzazione)
Vincitore: Valkey per la ricerca live sub-percettiva, NumPy per l'elaborazione analitica offline pesante
Ricerca di Configurazione
JSON:
-
Tempo di caricamento: Variabile (proporzionale alla complessità della configurazione)
-
Tempo di ricerca: Veloce (accesso al dizionario nativo)
-
Tempo di modifica: Senza attrito (modifica del testo leggibile dall'uomo)
Valkey:
-
Tempo di caricamento: Immediato (attivo alla connessione)
-
Tempo di ricerca: Vincolato dalla rete (dipendente dall'overhead della richiesta)
-
Tempo di modifica: Programmabile (richiede comandi CLI o SET del client)
Vincitore: JSON per configurazioni statiche, Valkey per stato condiviso dinamico
Riferimenti
Tecnologie
-
NumPy - Libreria per il calcolo con array
-
JSON - Formato di interscambio dati
-
Valkey - Archivio dati in memoria (fork di Redis)
-
RediSearch - Modulo per ricerca vettoriale
Concetti Tecnici
-
File mappato in memoria - Wikipedia
-
Database chiave-valore - Wikipedia
-
Database vettoriale - Wikipedia
Articoli Correlati
-
Panoramica del Pipeline SEO - Architettura completa del pipeline
-
Architettura del Servizio di Ricerca - Ricerca live con Valkey
-
Architettura Multi-Server - Archiviazione per server
-
Elaborazione Incrementale - Strategia di caching
Riepilogo
Utilizziamo tre tecnologie di archiviazione ottimizzate per diversi casi d'uso:
NumPy (embedding):
-
Operazioni vettoriali veloci (similarità del coseno)
-
Mappato in memoria
-
Elaborazione in batch
-
Formato ML standard
JSON (configurazione):
-
Leggibile dall'uomo (facile debug)
-
Controllo delle versioni (differenze Git)
-
Modifica manuale (nessun codice necessario)
-
Formato universale
Valkey (cache live):
-
Ricerche veloci (microsecondi)
-
Ricerca vettoriale (RediSearch)
-
Scadenza TTL (auto-invalidazione)
-
Pub/sub (aggiornamenti in tempo reale)
Approccio ibrido: Usa lo strumento giusto per ogni lavoro, combinali per prestazioni ottimali.