Eu explico como o comportamento da cache de consulta mysql em ambientes de alojamento modernos, porque é que o MySQL 8.0 aboliu a cache de consulta interna e como posso tornar-me visivelmente mais rápido com o Redis ou o Memcached. Mostrarei alavancas claras para Cache de consultas, validação da cache, monitorização e hardware, com os quais os sítios Web são entregues mais frequentemente a partir da cache e as bases de dados funcionam menos.
Pontos centrais
- MySQL 8.0Cache de consulta interna removida, cache externa assumida.
- Na memóriaLeitura frequente de dados da RAM à velocidade da luz.
- InvalidaçãoTTL, eventos e controlo de versões contra dados desactualizados.
- MonitorizaçãoAfinação do controlo da taxa de acerto, da latência e dos despejos.
- 300%O armazenamento em cache correto reduz a carga e aumenta o desempenho.
Breve explicação do comportamento da cache de consulta no alojamento
Quando os pedidos chegam, primeiro verifico se o resultado já está na Cache está localizado. Se estiver lá, respondo sem acesso à base de dados e poupo latência e tempo de CPU no Servidor de base de dados. Se a entrada estiver em falta, crio o resultado, guardo-o na cache e entrego-o para que o próximo acesso seja mais rápido e o Tempo de carregamento da página diminui. Desta forma, reduzo o número de consultas idênticas e reduzo a carga do servidor para acessos recorrentes a Conteúdos populares. Em configurações de alojamento com muitos pedidos semelhantes (página inicial, listas de produtos, estruturas de menus), o comportamento da cache de consulta traz vantagens significativas. Aceleração.
Da MySQL Query Cache para o Redis/Memcached: a forma moderna
A antiga cache de consulta do MySQL tornava mais lento muitos acessos de escrita, então o MySQL 8.0 removeu o Função. Em vez disso, utilizo o Redis ou o Memcached, pois permitem-me utilizar caches independentemente do Base de dados e pode utilizar chaves granulares, TTLs e estratégias de expulsão. Isto reduz visivelmente a carga no MySQL, porque os pedidos de leitura atingem o Cache na memória, enquanto o MySQL se concentra nas transacções reais. Mantenho deliberadamente as chaves da cache pequenas, versiono-as quando são efectuadas alterações e, assim, asseguro um elevado nível de segurança. Taxa de acerto. Esta abordagem permite obter respostas coerentes com uma elevada utilização e escalas em vários Trabalhador ou contentores.
Porque é que a cache de consulta interna foi realmente removida? Bloqueava sistemas altamente paralelizados com bloqueios globais, muitas vezes invalidava áreas de tabelas inteiras quando eram feitas alterações e causava muitas despesas administrativas com cargas de trabalho mistas de leitura/escrita. O resultado: quanto mais acessos de escrita, menor o benefício - até ao travão da rede. As caches modernas estão, portanto, localizadas fora do MySQL, utilizam TTLs isolados por chave, permitem o escalonamento horizontal e podem ser implementadas independentemente. O MySQL em si continua a beneficiar do buffer pool InnoDB, bons índices e declarações preparadas - mas a cache de resultados continua a ser a tarefa do nível da aplicação.
Compreender os níveis de cache: na memória, na base de dados, na aplicação
Faço uma distinção entre três níveis para que o Armazenamento em cache cache relacionada com a aplicação (Redis/Memcached), cache relacionada com a base de dados (por exemplo, buffer pool) e caches de proxy HTTP/reverso. Perto da aplicação, coloco em cache os resultados completos da consulta ou os resultados renderizados Fragmentos, que oferece a maior flexibilidade. Perto da base de dados, beneficio de índices optimizados e do InnoDB Buffer Pool, que armazena páginas lidas frequentemente no RAM mantém. A nível HTTP, minimizo as chamadas dinâmicas quando o conteúdo é realmente estático são. Apresento um breve resumo das tácticas no compacto Guia de estratégias de armazenamento em cache, o que facilita a utilização adequada em função do cenário de aplicação.
Padrões de cache em comparação
Escolho o padrão de acordo com o risco, a frequência da mudança e a necessidade de consistência:
- Cache-Aside (carregamento preguiçoso): A aplicação verifica a cache, carrega a partir da BD em caso de falha, escreve na cache. Simples, flexível, com baixo acoplamento - mas suscetível de ser atacado quando o TTL expira.
- Read-ThroughUma camada de cache é carregada automaticamente a partir da fonte de dados. Comportamento uniforme, mas complexidade adicional na camada intermédia.
- Gravação diretaEm cada escrita, os dados passam primeiro para a cache e depois para a BD. Muito consistente, mas o caminho de escrita é mais longo.
- Escrever-atrásA cache aceita operações de escrita e flui de forma assíncrona para a BD. Rápida, mas complicada em caso de falha; utilizar apenas com garantias claras.
- Paralisar-enquanto-revalidaAs entradas expiradas podem ser brevemente devolvidas como „antigas“ enquanto um trabalho em segundo plano as preenche. Ideal contra picos de carga.
Validação de cache sem erros de dados
Planeio a invalidação da cache de forma a que os dados actuais tenham sempre prioridade e Velocidade permanece. Defino um tempo de vida (TTL) suficientemente curto para mostrar as alterações rapidamente, mas suficientemente longo para que o Taxa de sucesso permanece elevado. Durante as operações de escrita, elimino chaves específicas (write-through/write-behind) ou aumento uma Versão no espaço de nomes da chave, para que os acessos subsequentes obtenham o novo conjunto de dados. Para conteúdos sensíveis (preços, acções, contas), utilizo TTL ou invalidação imediata após as actualizações. Isto evita respostas desactualizadas e mantém a consistência dos dados em centros de dados distribuídos. Sistemas.
Evitar a debandada da cache: stale-while-revalidate, bloqueios e jitter
Para evitar o „problema da pilha de cães“, utilizo mecanismos combinados: a TTL suave, que permite alguns segundos de „stale“ enquanto um trabalhador de voo único actualiza o objeto; um curto Mutex (por exemplo, via Redis SET NX + TTL), para que apenas um processo seja recarregado; e um Jitter a TTLs (desvio aleatório) para que milhares de chaves não expirem ao mesmo tempo. No caso de erros na fonte original, permito que estagnação em caso de erro e proteger a base de dados de avalanches.
Tamanho, TTL e despejo: os parafusos de ajuste certos
Escolho o tamanho da cache para corresponder ao volume de dados, o que vale a pena no RAM para mentir. Demasiado pequeno aumenta as falhas, demasiado grande desperdiça memória, por isso meço continuamente e reajo a Picos de carga. Para a evicção, prefiro utilizar o LRU se os padrões de acesso forem cíclicos, e mudar para o LFU para padrões de acesso claros. Favoritos perenes. Mantenho os TTLs diferenciados: navegação estática mais longa, disponibilidade dinâmica do produto mais curto. O quadro seguinte apresenta valores iniciais típicos, que depois aperfeiçoo através do controlo e ajusto para os valores reais Use personalizar.
| Parâmetros | Objetivo | valor inicial | Variável medida |
|---|---|---|---|
| Tamanho da cache | Orçamento de RAM para caches de consulta ou de fragmentos | 5-15% da RAM do servidor | Despejos/minuto, utilização de RAM |
| TTL estático | Menus, páginas de categorias, listagens frequentes | 300-1800 segundos | Rácio de acerto, necessidade de atualidade |
| TTL dinâmico | Preços, stock, personalização | 10-120 segundos | Taxa de erro, correcções |
| Despejo | LRU/LFU/FIFO por padrão de acesso | LRU de série | Taxa de falha, acessos repetidos |
| Esquema de chaves | Controlo de versões contra dados desactualizados | utilizador:v1:queryhash | Golpe em falta após a implantação |
Também tenho em conta a distribuição do tamanho dos objectos e os limites superiores. Comprimo objectos individuais com mais de 512 KB, por exemplo, ou divido-os em páginas (paginação) para que os despejos não desloquem blocos inteiros de megabytes. Diferentes caches (por exemplo, „quente“ e „fria“) com tamanhos separados impedem que alguns objectos grandes substituam as muitas entradas pequenas e frequentemente lidas.
Conceção e normalização de chaves
As boas chaves determinam a taxa de acerto e a capacidade de invalidação. Normalizo os parâmetros de consulta (ordenação, maiúsculas/minúsculas, valores predefinidos), converto as listas numa ordem canónica e coloco os parâmetros longos num Hash de consulta, para que as chaves permaneçam curtas. Separo as facetas de forma limpa na chave: site:v3:en-EN:category:42:page:2:filter:abc123. A personalização, o cliente, a moeda, a localidade e a categoria do dispositivo pertencem visivelmente ao espaço de nomes. Quantifico os parâmetros numéricos (por exemplo, arredondo os filtros de preços para intervalos significativos) para evitar duplicações. Caches negativos (por exemplo, „sem acerto“) com um TTL muito curto reduzem os acessos à base de dados para acertos repetidos. Menina-procurar.
Escolher corretamente a serialização e a compressão
Escolho os formatos de acordo com a interface e o orçamento da CPU: JSON é universal e legível, MessagePack ou Protobuf poupar RAM/largura de banda. Para objectos grandes, utilizo LZ4 ou Rápido para compressão rápida; Gzip apenas se o tamanho máximo for mais importante que a CPU. Um Limiar (por exemplo, de 4-8 KB) evita que pequenos dados sejam comprimidos desnecessariamente. Presto atenção a esquemas estáveis: se acrescentar campos, aumento o Versão principal, para que os analisadores antigos não se avariem.
Redis vs. memcached: Diferenças de funcionamento
Memcached pontua com a sua arquitetura simples, multithreading e Lajes para uma atribuição eficiente. É a primeira escolha para resultados chave/valor muito simples com QPS extremamente elevado sem necessidade de persistência. Redis oferece estruturas de dados (hashes, conjuntos, conjuntos ordenados), controlo fino de TTL, replicação e capacidade de cluster. O Redis é ideal para listas, tabelas de classificação, contadores e pub/sub. Como uma cache de resultados pura, desativo a persistência (ou defino snapshots esparsos) para economizar E/S. Eu uso Condutas e MGET, para reduzir as viagens de ida e volta, e selecionar a política de despejo para corresponder ao padrão de acesso (allkeys-lfu para hotkeys claras e permanentes, volatile-lru para utilização rigorosa de TTL). Distribuo as hot keys através de sharding/clusters, ou replico-as deliberadamente várias vezes para amortecer os estrangulamentos.
Monitorização e afinação durante o funcionamento
Eu observo o Taxa de sucesso, a latência por operação de cache e a taxa de evicção para reconhecer os estrangulamentos. Se a latência aumentar, verifico os caminhos de rede, a saturação da CPU e a serialização de objectos. Reduzo os objectos grandes, comprimindo-os ou dividindo-os em objectos mais pequenos para Memória para o utilizar melhor. Se a taxa de acerto diminuir, identifico as teclas em falta e ajusto os TTL ou Regimes-chave sobre. O Tuning continua a ser um ciclo de medição, de formulação de hipóteses, de adaptação e Medição.
Números-chave concretos ajudam a analisar as causas: espaço_chave_acertos/erros, chaves_despejadas, recuperado (Memcached), memória_utilizada e RSS-desvios para fragmentação, latências P99 por comando, taxas de erro de rede e Slowlog-entradas. Presto atenção a despejos contínuos e sem sobressaltos, a tamanhos de objectos uniformemente distribuídos e à proporção de „stale served“. Se miss→db→set é mais frequente do que o previsto, ou o TTL não está correto ou as chaves são demasiado variadas (falta de normalização).
Segurança e alta disponibilidade
Eu nunca exponho os servidores de cache publicamente, mas os vinculo a interfaces/VPCs internos, ativo ACLs e sempre que possível TLS. Separo rigorosamente os ambientes de produção, de preparação e de teste para que não haja colisão de chaves nem migração de dados. Bloqueio operações críticas (FLUSH*) através de autorizações. Para Transferência em caso de falha Utilizo a replicação e, dependendo da tecnologia, a comutação automática (por exemplo, watchdog/sentinel/cluster). Como cache de resultado puro, a persistência só é utilizada com moderação ou não é utilizada de todo - se a cache falhar, a aplicação pode ser apenas mais lenta, mas correta. Eu limito os comandos que examinam espaços de chaves inteiros e só planeio backups onde o cache também é usado. Fonte da verdade é (raramente o caso).
WordPress e comércio eletrónico: padrões típicos e armadilhas
Com o WordPress, coloco em cache as estruturas dos menus, os resultados das consultas do WP_Query e as Widgets, enquanto excluo as partes personalizadas. Certifico-me de que os plugins não bloqueiam todos os pedidos. Bypass, definindo sessões ou alterando constantemente os cookies. Para os sistemas de lojas, coloco em cache páginas de categorias, listas de bestsellers e filtro resultados com cookies curtos TTL, enquanto os cestos de compras e as páginas de conta permanecem dinâmicos. Aqueles que confiam na antiga cache de consulta pioram frequentemente o Desempenho; Explico porque é que isso acontece aqui: Cache de consulta do WordPress. É assim que mantenho o equilíbrio entre velocidade e correção Personalização.
Também vario as caches nos sítios certos: Moeda, Idioma, Localização e Grupo de clientes influenciam os preços, a disponibilidade e o conteúdo. Separo a personalização do resto: a página vem da cache, apenas pequenos blocos (por exemplo, a contagem do carrinho de compras) são recarregados dinamicamente. Para filtros altamente variáveis (facetas), normalizo a sequência e crio chaves de página (page=1,2,...) em vez de gerar chaves enormes e confusas. E certifico-me de que as respostas „Sem resultado“ são colocadas em cache durante um curto período de tempo para reduzir as pesquisas na BD.
Planeamento de capacidades e modelo de custos
Faço um cálculo aproximado antecipadamente: Tamanho médio do objeto × número previsto de chaves + despesas gerais (10-30%) dá o Base RAM. Exemplo: 80.000 objectos a 6 KB mais 25% de sobrecarga ≈ 600 MB. Planeio os buffers para o crescimento (por exemplo, 30-50%). No que diz respeito ao débito, estimo o rácio de leitura/escrita, objetivoTaxa de sucesso (70-95%) e a consequente redução da carga da base de dados. Se 60% das leituras anteriores da base de dados forem servidas a partir da cache, não só a carga da CPU e de IOPS é reduzida, como também, muitas vezes, a Replicação-Desfasamentos. Cenários de preços: Tornar a RAM mais cara, poupar núcleos de BD - normalmente o investimento em RAM ganha significativamente porque proporciona tempos de resposta mais consistentes.
Pool de Buffer InnoDB, Plano de Consulta e Índices juntos
Não optimizo isoladamente, mas olho para a cache, Grupo de tampões, plano de consulta e índices como um pacote. Um buffer pool bem dimensionado aumenta os acessos ao InnoDB, reduz a E/S e fortalece cada Cache sobre o assunto. Verifico as consultas lentas, crio índices em falta e mantenho as estatísticas actualizadas para que o optimizador obtenha os melhores resultados. Plano seleciona. Para passos mais pormenorizados, este Otimização da reserva de tampões, que utilizo em paralelo com o caching. Isto resulta em velocidade: menos I/O, mais acessos à RAM e cache mais eficiente. Consultas.
Em termos práticos, isto significa que dimensiono o buffer pool de modo a que as páginas de dados „quentes“ caibam nele sem que o sistema operativo fique sobrecarregado. Os perfis das consultas revelam se as varreduras de tabelas completas, JOINs suboptimizados ou índices de cobertura em falta estão a minar as caches. Verifico se os SELECTs que são demasiado largos (colunas desnecessárias) geram objectos de cache grandes e reduzo-os. Se as consultas variam muito, normalizo os parâmetros na aplicação ou reduzo-os a algumas variantes reutilizáveis.
Utilizar corretamente os recursos de hardware
Reservo RAM suficiente para o Redis/Memcached e para o InnoDB Tampão para que os discos rígidos dificilmente bloqueiem. Presto atenção aos núcleos da CPU para que a aplicação e o servidor de cache possam ser executados simultaneamente. trabalho pode. Os SSDs NVMe reduzem a latência residual se uma falha de cache se tornar um problema. Memória tem efeito. A latência da rede continua a ser importante, e é por isso que coloco os servidores de cache perto do App ou no mesmo anfitrião. Estas decisões poupam muitas vezes custos de alojamento em euros, porque com menos núcleos e menos Carga obter os mesmos tempos de resposta.
Eu também levo em consideração as topologias NUMA e de soquete, fixando processos em núcleos, se necessário, e usando caminhos de rede curtos (ou soquetes Unix no mesmo host). Para configurações de contentores, planeio recursos „garantidos“ para que a cache não seja estrangulada e forneça espaço para picos de carga. Se as hot keys forem inevitáveis, distribuo o tráfego por várias réplicas ou encaminho-o para a cache mais local para evitar latências entre zonas.
Lançamento, testes e aquecimento da cache
Eu testo as alterações de cache com perfis de carga que reflectem dados de utilização reais. Na produção, faço a implementação por fases (Canary), observo o rácio de acerto, as latências e a carga da BD e só depois aumento os TTLs. Para implantações, eu aumento o Versão principal e aquecer as n-keys principais (página inicial, mais vendidos, categorias importantes). As tarefas em segundo plano preenchem a lista e as páginas de pormenor de forma direcionada, para que os primeiros utilizadores não suportem os custos de aquecimento. Simulo expulsões (ambiente de teste) e faço stress nos hot paths para verificar a proteção contra debandadas e o jitter.
Plano passo-a-passo para um melhor desempenho do alojamento
Começo por fazer um inventário: lento Consultas, ficheiros de registo, rácio de acertos, despejos e perfis CPU/RAM. Em seguida, defino chaves de cache para as páginas mais importantes e crio TTLs que equilibram atualidade e rapidez. Incorporo a invalidação por escrito ou baseada em eventos para as alterações, de modo a que Consistência permanece. Em seguida, meço novamente, aumento ou diminuo os TTLs, ajusto o tamanho da cache e removo Excedentes com objectos grandes. Por fim, aperfeiçoo o buffer pool, os índices e os planos até que a entrega de páginas seja percetível. líquido está a correr.
Brevemente resumido
Eu substituo o antigo cache de consulta do MySQL por Redis ou Memcached, controlar conscientemente as chaves, TTLs e evicções e manter os dados fiáveis com uma invalidação clara. Dependendo da aplicação, obtenho 200-300% Velocidade, especialmente quando chegam muitos pedidos idênticos. A monitorização orienta as minhas decisões: Se a taxa de acerto cair ou a latência aumentar, ajusto o tamanho, o TTL e o chave em. Juntamente com um forte conjunto de buffers InnoDB e índices limpos, a plataforma é melhor dimensionada e muito reactiva. rápido. Se compreender o comportamento da cache de consulta mysql como um sistema completo, poupa a carga do servidor, reduz os custos em euros e fornece aos utilizadores um sistema de consulta nítido Experiência do utilizador.


