Spiego come il comportamento della cache delle query di mysql negli ambienti di hosting moderni, perché MySQL 8.0 ha abolito la cache interna delle query e come posso diventare sensibilmente più veloce con Redis o Memcached. Vi mostrerò leve chiare per Caching delle query, la convalida della cache, il monitoraggio e l'hardware, grazie ai quali i siti web vengono consegnati più spesso dalla cache e i database lavorano meno.
Punti centrali
- MySQL 8.0: Rimossa la cache interna delle query, sostituita da cache esterne.
- In memoriaLeggere frequentemente i dati dalla RAM alla velocità della luce.
- InvalidazioneTTL, eventi e versioning contro i dati obsoleti.
- MonitoraggioRegolazione di Hit ratio, latenza e controllo degli sfratti.
- 300%Una cache corretta riduce il carico e aumenta le prestazioni.
Il comportamento della cache delle query nell'hosting spiegato brevemente
Quando arrivano le richieste, per prima cosa verifico se il risultato è già presente nel file Cache si trova. Se si trova lì, rispondo senza accedere al database e risparmio latenza e tempo di CPU sul computer. Server di database. Se la voce è mancante, creo il risultato, lo salvo nella cache e lo consegno in modo che il prossimo hit sia più veloce e il Tempo di caricamento della pagina diminuisce. In questo modo, si riduce il numero di query identiche e si riduce il carico del server per gli accessi ricorrenti a Contenuti popolari. Nelle configurazioni di hosting con molte richieste simili (pagina iniziale, elenchi di prodotti, strutture di menu), il comportamento della cache delle query porta vantaggi significativi. Accelerazione.
Dalla Query Cache di MySQL a Redis/Memcached: la via moderna
La vecchia cache delle query di MySQL rallentava molti accessi in scrittura, quindi MySQL 8.0 ha rimosso la cache di MySQL. Funzione. Mi affido invece a Redis o Memcached, perché mi permettono di utilizzare le cache indipendentemente dal sistema di gestione delle risorse. Banca dati e può utilizzare chiavi, TTL e strategie di eviction granulari. Questo riduce sensibilmente il carico su MySQL, perché le richieste di lettura colpiscono più frequentemente il server di MySQL. Cache in memoria, mentre MySQL si concentra sulle transazioni reali. Mantengo deliberatamente le chiavi della cache di piccole dimensioni, le modifico quando vengono apportate delle modifiche e garantisco così un elevato livello di sicurezza. Tasso di successo. Questo approccio fornisce risposte coerenti ad alto utilizzo e su scala diversa. Lavoratore o contenitori.
Perché è stata rimossa la cache interna delle query? Bloccava i sistemi altamente parallelizzati attraverso i lock globali, spesso invalidava intere aree di tabelle quando venivano apportate modifiche e causava un notevole overhead amministrativo con carichi di lavoro misti di lettura/scrittura. Il risultato: maggiore è il numero di accessi in scrittura, minore è il beneficio, fino al freno di rete. Le cache moderne si trovano quindi al di fuori di MySQL, utilizzano TTL isolati per chiave, consentono una scalabilità orizzontale e possono essere distribuite in modo indipendente. MySQL stesso continua a beneficiare del pool di buffer InnoDB, di buoni indici e di prepared statements, ma la cache dei risultati rimane un compito del livello applicativo.
Comprensione dei livelli di cache: in-memory, database, applicazione
Distinguo tre livelli in modo che il Caching cache relativa all'applicazione (Redis/Memcached), cache relativa al database (ad es. buffer pool) e cache HTTP/reverse proxy. Vicino all'applicazione, memorizzo nella cache i risultati completi delle query o i file renderizzati Frammenti, che offre la massima flessibilità. Vicino al database, posso beneficiare di indici ottimizzati e del buffer pool InnoDB, che memorizza le pagine lette più di frequente nella cartella di memoria InnoDB. RAM stive. A livello di HTTP, riduco al minimo le chiamate dinamiche quando il contenuto è veramente statico sono. Offro una rapida panoramica delle tattiche nel compact Guida alle strategie di caching, che facilita l'uso appropriato a seconda dello scenario applicativo.
Modelli di cache a confronto
Scelgo il modello in base al rischio, alla frequenza dei cambiamenti e alla necessità di coerenza:
- Cache-Aside (caricamento pigro): L'applicazione controlla la cache, carica dal DB in caso di errore, scrive nella cache. Semplice, flessibile, a basso accoppiamento, ma suscettibile di timbri quando il TTL scade.
- LetturaUn livello di cache viene caricato automaticamente dall'origine dei dati. Comportamento uniforme, ma complessità aggiuntiva nel livello intermedio.
- Write-ThroughAd ogni scrittura, i dati passano prima nella cache e poi nel DB. Molto coerente, ma il percorso di scrittura è più lungo.
- Scrivere dietroLa cache accetta le operazioni di scrittura e scorre in modo asincrono nel DB. Veloce, ma complicata in caso di guasto; da usare solo con chiare garanzie.
- Stallo durante la convalidaLe voci scadute possono essere brevemente restituite „vecchie“ mentre un lavoro in background riempie le voci nuove. Ideale contro i picchi di carico.
Convalida della cache senza errori di dati
Pianifico l'invalidazione della cache in modo tale che i dati attuali abbiano sempre la priorità e Velocità rimane. Ho impostato un tempo di vita (TTL) sufficientemente breve da mostrare prontamente le modifiche, ma abbastanza lungo da far sì che il Hit ratio rimane alto. Durante le operazioni di scrittura, cancello chiavi specifiche (write-through/write-behind) o aumento una chiave di Versione nello spazio dei nomi delle chiavi, in modo che gli accessi successivi possano prelevare il nuovo set di dati. Per i contenuti sensibili (prezzi, azioni, conti), uso un file più breve TTL o l'invalidazione immediata dopo gli aggiornamenti. In questo modo si evitano risposte obsolete e si mantiene la coerenza dei dati nei data center distribuiti. Sistemi.
Prevenire la fuga dalla cache: stale-while-revalidate, lock e jitter
Per evitare il „problema del mucchio di cani“, utilizzo meccanismi combinati: un TTL morbido, che consente alcuni secondi di „stallo“ mentre un worker a volo singolo aggiorna l'oggetto; una breve Mutex (ad esempio tramite Redis SET NX + TTL), in modo da ricaricare solo un processo; e una Jitter ai TTL (deviazione casuale) in modo che migliaia di chiavi non scadano nello stesso momento. In caso di errori nella fonte originale, permetto a stale-if-error e proteggere il database dalle valanghe.
Dimensioni, TTL e sfratto: le viti di regolazione giuste
Scelgo la dimensione della cache in modo che corrisponda al volume dei dati, il che è utile nella RAM di mentire. Troppo piccoli aumentano le mancanze, troppo grandi sprecano memoria, quindi misuro continuamente e reagisco a Picchi di carico. Per lo sfratto, preferisco usare LRU se gli accessi sono ciclici e passare a LFU per gli accessi netti. I preferiti di sempre. Mantengo i TTL differenziati: navigazione statica più lunga, disponibilità dinamica del prodotto più breve. La tabella seguente mostra i valori di partenza tipici, che poi perfeziono con il monitoraggio e regolo in base ai valori reali. Utilizzare personalizzare.
| Parametri | Scopo | valore iniziale | Variabile misurata |
|---|---|---|---|
| Dimensione della cache | Budget di RAM per cache di query o frammenti | 5-15% della RAM del server | Sfratti/minuto, utilizzo della RAM |
| TTL statico | Menu, pagine di categoria, elenchi frequenti | 300-1800 secondi | Hit ratio, requisito di tempestività |
| Dinamica TTL | Prezzi, stock, personalizzazione | 10-120 secondi | Tasso di errore, correzioni |
| Sfratto | LRU/LFU/FIFO per schema di accesso | LRU di serie | Tasso di mancata risposta, accessi ripetuti |
| Schema chiave | Versioning contro i dati obsoleti | utente:v1:queryhash | Colpo mancante dopo la distribuzione |
Tengo anche conto della distribuzione delle dimensioni degli oggetti e dei limiti superiori. Ad esempio, comprimo i singoli oggetti oltre i 512 KB o li divido in pagine (paging) in modo che le evacuazioni non spostino interi blocchi di megabyte. Cache diverse (ad esempio „calde“ e „fredde“) con dimensioni separate impediscono a pochi oggetti di grandi dimensioni di spostare le molte voci piccole e di frequente lettura.
Progettazione e normalizzazione delle chiavi
Le chiavi valide determinano il tasso di successo e la capacità di invalidazione. Normalizzo i parametri della query (ordinamento, maiuscole/minuscole, valori predefiniti), converto gli elenchi in un ordine canonico e faccio l'hash dei parametri lunghi in un file di tipo Query hash, in modo che le chiavi rimangano corte. Separo le sfaccettature in modo netto nella chiave: site:v3:en-EN:category:42:page:2:filter:abc123. Personalizzazione, cliente, valuta, locale e categoria del dispositivo appartengono visibilmente allo spazio dei nomi. Quantizzo i parametri numerici (ad esempio, arrotondo i filtri di prezzo in bucket significativi) per evitare duplicazioni. Cache negative (ad esempio, „nessun riscontro“) con un TTL molto breve riducono gli accessi al DB per i riscontri ripetuti. Signorina-Ricerca.
Scegliere correttamente la serializzazione e la compressione
Seleziono i formati in base all'interfaccia e al budget della CPU: JSON è universale e leggibile, Pacchetto messaggi oppure Protobuf risparmiare RAM/larghezza di banda. Per gli oggetti di grandi dimensioni uso LZ4 oppure Scattante per una compressione veloce; Gzip solo se la dimensione massima è più importante della CPU. Uno Soglia (ad esempio, da 4 a 8 KB) evita che i dati piccoli vengano compressi inutilmente. Presto attenzione agli schemi stabili: se aggiungo campi, aumento la Versione chiave, in modo che i vecchi parser non si rompano.
Redis vs. memcached: Differenze di funzionamento
Memcached con la sua architettura semplice, il multithreading e il Lastre per un'allocazione efficiente. È la prima scelta per risultati chiave/valore molto semplici con QPS estremamente elevati, senza necessità di persistenza. Redis offre strutture di dati (hash, insiemi, insiemi ordinati), controllo TTL fine, replica e capacità di cluster. Redis è ideale per liste, classifiche, contatori e pub/sub. Come pura cache di risultati, disattivo la persistenza (o imposto snapshot sparse) per risparmiare I/O. Uso Condotte e MGET, per ridurre i viaggi di andata e ritorno, e selezionare la politica di sfratto in base al modello di accesso (allkeys-lfu per hotkey chiari e permanenti, volatile-lru per un uso rigoroso del TTL). Distribuisco i tasti di scelta rapida tramite sharding/cluster o li replico deliberatamente più volte per attenuare i colli di bottiglia.
Monitoraggio e messa a punto durante il funzionamento
Osservo il Hit ratio, la latenza per operazione di cache e il tasso di evasione per riconoscere i colli di bottiglia. Se la latenza aumenta, verifico i percorsi di rete, la saturazione della CPU e il serializzazione di oggetti. Riduco gli oggetti di grandi dimensioni comprimendoli o dividendoli in oggetti più piccoli, al fine di Memoria per utilizzarlo meglio. Se la percentuale di successo diminuisce, identifico le chiavi mancanti e regolo i TTL o le Schemi chiave su. La messa a punto rimane un ciclo di misurazioni, ipotesi, adattamenti e poi Misurazione.
Le cifre chiave concrete aiutano ad analizzare le cause: spazio_chiavi_colpiti/mancati, chiavi sfrattate, bonificato (Memcached), memoria_usata e RSS-per la frammentazione, le latenze di P99 per comando, i tassi di errore della rete e le Slowlog-ingressi. Presto attenzione alle evacuazioni continue e non accidentate, alle dimensioni degli oggetti distribuite in modo uniforme e alla percentuale di „stale served“. Se miss→db→set è più frequente del previsto, o il TTL non è corretto o le chiavi variano troppo (mancanza di normalizzazione).
Sicurezza e alta disponibilità
Non espongo mai i server di cache pubblicamente, ma li lego a interfacce interne/VPC, attivo ACL e dove possibile TLS. Separo rigorosamente gli ambienti di produzione, staging e test in modo che nessuna chiave si scontri e nessun dato migri. Blocco le operazioni critiche (FLUSH*) tramite autorizzazioni. Per Failover Utilizzo la replica e, a seconda della tecnologia, la commutazione automatica (ad esempio, watchdog/sentinel/cluster). Come pura cache di risultato, la persistenza è usata solo con parsimonia o per niente - se la cache fallisce, l'applicazione può essere solo più lenta, ma corretta. Limito i comandi che scansionano interi keyspace e pianifico solo i backup in cui viene utilizzata anche la cache. Fonte di verità è (raramente).
WordPress e l'e-commerce: modelli tipici e insidie
Con WordPress, memorizzo nella cache le strutture dei menu, i risultati delle interrogazioni di WP_Query e importanti Widget, mentre escludo le parti personalizzate. Mi assicuro che i plugin non blocchino ogni richiesta. Bypass, impostando sessioni o cambiando continuamente i cookie. Per i sistemi di negozio, metto in cache le pagine delle categorie, le liste dei bestseller e filtro i risultati con brevi TTL, mentre i cestini degli acquisti e le pagine degli account rimangono dinamici. Coloro che si affidano alla vecchia query cache spesso peggiorano la Prestazioni; Qui spiego perché questo è il caso: Query Cache di WordPress. In questo modo mantengo l'equilibrio tra velocità e correttezza. Personalizzazione.
Inoltre, ho variato le cache nei posti giusti: Valuta, Lingua, Posizione e Gruppo di clienti influenzare prezzi, disponibilità e contenuti. Disaccoppio la personalizzazione dal resto: la pagina proviene dalla cache, solo piccoli blocchi (ad esempio il conteggio del carrello) vengono ricaricati dinamicamente. Per i filtri altamente variabili (facet), normalizzo la sequenza e creo chiavi di pagina (page=1,2,...) invece di generare chiavi enormi e confuse. E mi assicuro che le risposte „Nessun risultato“ siano memorizzate nella cache per un breve periodo di tempo, per ridurre le scansioni del DB.
Pianificazione della capacità e modello dei costi
Faccio un calcolo approssimativo in anticipo: la dimensione media dell'oggetto × il numero di chiavi previsto + l'overhead (10-30%) dà il risultato di Base RAM. Esempio: 80.000 oggetti à 6 KB più 25% di overhead ≈ 600 MB. Pianifico i buffer per la crescita (ad esempio 30-50%). Per quanto riguarda il throughput, stimo il rapporto lettura/scrittura, obiettivoHit ratio (70-95%) e la conseguente riduzione del carico del database. Se 60% delle precedenti letture del DB vengono servite dalla cache, non solo si riduce il carico della CPU e degli IOPS, ma spesso anche il carico del database. Replica-Lags. Scenari di prezzo: Rendere più costosa la RAM, risparmiare i core DB - di solito l'investimento in RAM è nettamente vincente perché porta a tempi di risposta più costanti.
Pool di buffer InnoDB, piano di query e indici insieme
Non ottimizzo in modo isolato, ma guardo alla cache, Pool di buffer, piano di query e indici come un pacchetto. Un pool di buffer ben dimensionato aumenta le visite di InnoDB, riduce l'I/O e rafforza ciascun Cache a questo proposito. Controllo le query lente, creo gli indici mancanti e mantengo le statistiche aggiornate in modo che l'ottimizzatore ottenga i risultati migliori. Piano seleziona. Per una procedura più approfondita, questo Ottimizzazione del pool di buffer, che uso in parallelo con la cache. Tutto ciò si traduce in velocità: meno I/O, più RAM e cache più efficiente. Domande.
In termini pratici, ciò significa dimensionare il buffer pool in modo che le pagine di dati „calde“ vi entrino senza affamare il sistema operativo. I profili delle query rivelano se le scansioni di tabelle complete, le JOIN non ottimali o gli indici di copertura mancanti stanno compromettendo le cache. Verifico se le SELECT troppo ampie (colonne non necessarie) generano oggetti di cache di grandi dimensioni e le riduco. Se le query variano notevolmente, normalizzo i parametri nell'applicazione o li riduco a poche varianti riutilizzabili.
Utilizzo corretto delle risorse hardware
Riservo abbastanza RAM per Redis/Memcached e per InnoDB Buffer in modo che i dischi rigidi non si blocchino quasi mai. Presto attenzione ai core della CPU in modo che l'applicazione e il server di cache possano funzionare contemporaneamente. lavoro possono. Le unità SSD NVMe riducono la latenza residua se la mancanza di cache diventa un problema. Memoria ha effetto. La latenza di rete rimane importante, per questo motivo posiziono i server della cache vicino alla rete. App o nello stesso host. Queste decisioni spesso consentono di risparmiare sui costi di hosting in euro, perché con un numero inferiore di core e di Carico ottenere gli stessi tempi di risposta.
Tengo anche conto delle topologie NUMA e dei socket, se necessario appiccico i processi ai core e uso percorsi di rete brevi (o socket Unix sullo stesso host). Per le configurazioni dei container, pianifico le risorse „garantite“ in modo che la cache non venga strozzata e fornisca spazio per i picchi di carico. Se le hot key sono inevitabili, distribuisco il traffico su più repliche o lo instrado verso la cache più locale per evitare latenze trasversali.
Rollout, test e riscaldamento della cache
Collaudo le modifiche alla cache con profili di carico che riflettono i dati di utilizzo reali. In produzione, eseguo il roll-out in più fasi (Canary), osservo l'hit ratio, le latenze e il carico del DB e solo successivamente aumento i TTL. Per le implementazioni, aumento il TTL Versione chiave e scaldare gli n-tasti principali (homepage, top seller, categorie importanti). I lavori in background riempiono le pagine degli elenchi e dei dettagli in modo mirato, in modo che i primi utenti non debbano sostenere i costi di riscaldamento. Simulo gli sfratti (ambiente di test) e metto sotto stress i percorsi caldi per verificare la protezione contro gli sfratti e il jitter.
Un piano passo dopo passo per migliorare le prestazioni dell'hosting
Inizio con un inventario: lento Domande, file di log, hit ratio, evasioni e profili CPU/RAM. Definisco quindi le chiavi di cache per le pagine più importanti e creo TTL che bilanciano tempestività e velocità. Incorporo l'invalidazione delle modifiche tramite scrittura o basata su eventi, in modo che Coerenza rimane. Poi misuro di nuovo, aumento o diminuisco il TTL, regolo la dimensione della cache e rimuovo I valori fuori norma con oggetti di grandi dimensioni. Infine, perfeziono il pool di buffer, gli indici e i piani fino a quando la consegna delle pagine è notevole. liquido sta correndo.
Riassumendo brevemente
Sostituisco la vecchia cache della query di MySQL con Redis o memcached, controllare consapevolmente le chiavi, i TTL e gli svuotamenti e mantenere i dati affidabili con una chiara invalidazione. A seconda dell'applicazione, ottengo 200-300% Velocità, soprattutto quando arrivano molte richieste identiche. Il monitoraggio guida le mie decisioni: Se il rapporto di successo diminuisce o la latenza aumenta, regolo la dimensione, il TTL e la velocità di risposta. chiave su. Insieme a un solido pool di buffer InnoDB e a indici puliti, la piattaforma è più scalabile e molto reattiva. veloce. Se si comprende il comportamento della cache delle query mysql come un sistema completo, si risparmia il carico del server, si riducono i costi in euro e si fornisce agli utenti un'immagine nitida. Esperienza dell'utente.


