关于 magento-indexing-caching
面向 Magento 开发者和运维人员的索引与缓存配置技能,涵盖索引器管理、Varnish 全页缓存、Redis 应用缓存及缓存失效排查。
主要功能
- 01查看和管理索引器状态与模式
- 02执行单个或批量重建索引
- 03配置 Varnish 全页缓存
- 04配置 Redis 缓存与会话存储
- 05使用缓存标签失效相关页面
适用场景
- 01排查商品价格错误或商品不可见
- 02为生产环境配置 Varnish 和 Redis
- 03管理大型商品目录的计划索引
- 04在目录或 CMS 更新后清理相关缓存
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill magento-indexing-caching安装后在 Claude Code 中输入/magento-indexing-caching确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/custom-module-cache-tag-invalidation/criteria.jsontask.mdevals/indexer-production-configuration/criteria.jsontask.mdevals/redis-cache-and-session-configuration/criteria.jsontask.md详细介绍
Magento 索引与缓存
概述
Magento 的性能架构依赖两个不同的层:索引器会将反规范化数据(产品价格、搜索索引、类别路径)预先计算并存入扁平表;整页缓存(FPC)则存储完整渲染后的 HTML 页面。生产环境推荐使用 Varnish 作为 FPC 后端,取代 Magento 内置的基于文件的缓存。推荐使用 Redis 作为应用缓存、会话存储和默认缓存(区块 HTML、配置、布局)的后端。索引配置错误或数据过期,是导致价格错误和产品不可见问题的最常见原因之一。
适用场景
- 商品目录更新后,产品显示的价格错误或不可见时
- 首次在 Magento 生产服务上部署 Varnish 时
- 排查因实时计算价格导致的类别页面加载缓慢问题时
- 为 Magento 配置 Redis,用于会话和区块缓存存储时
- 通过 Magento 的缓存标签,在商品目录或 CMS 更新后设置缓存失效时
- 管理大型商品目录(> 50,000 个产品)的索引器计划,避免全量重新索引造成锁定时
核心说明
-
了解 Magento 的索引器及其模式
# List all indexers and their status bin/magento indexer:info bin/magento indexer:status # Example output: # catalog_category_product Category Products valid Update on Save # catalog_product_category Product Categories valid Update on Save # catalog_product_price Product Price invalid Update by Schedule # catalogsearch_fulltext Catalog Search valid Update by Schedule # catalogrule_product Catalog Rule Product invalid Update on Save将所有生产环境索引器设为
Update by Schedule模式,以避免阻塞结账流程:bin/magento indexer:set-mode schedule catalog_category_product bin/magento indexer:set-mode schedule catalog_product_price bin/magento indexer:set-mode schedule catalogsearch_fulltext bin/magento indexer:set-mode schedule catalog_product_flat bin/magento indexer:set-mode schedule catalog_category_flat # Verify modes bin/magento indexer:show-mode -
管理索引器和部分重新索引
# Reindex a single indexer (less disruptive than full reindex) bin/magento indexer:reindex catalog_product_price # Reindex all (avoid on production during business hours) bin/magento indexer:reindex # Reset indexer to "invalid" to force next scheduled run bin/magento indexer:reset catalog_product_price # Check mview (materialized view) changelog tables — lists pending rows to process bin/magento indexer:show-changelog对于超大型商品目录,请使用并行索引:
# app/etc/env.php — enable parallel processing # In Admin → System → Index Management → Indexers → Configure # Or via config: bin/magento config:set dev/grid/async_indexing 1<?php // app/etc/env.php return [ // ... 'indexer' => [ 'batch_size' => [ 'catalog_product_price' => ['simple' => 200, 'configurable' => 50], 'catalogsearch_fulltext' => ['simple' => 500], ], ], ]; -
将 Varnish 配置为整页缓存
# In Admin → System → Configuration → Advanced → System → Full Page Cache # Set Caching Application: Varnish Cache # Export Varnish configuration: bin/magento varnish:vcl:generate --export-version=6 --output-file=/etc/varnish/magento.vcl生成的 VCL 中需要了解的关键部分:
# /etc/varnish/magento.vcl (excerpts from generated config) sub vcl_recv { # Do not cache if private cookie is set (logged-in customer) if (req.http.cookie ~ "X-Magento-Vary=") { # Magento sets this cookie to vary cache by context (customer group, currency) # The cookie value changes only when the context changes — not per session } # Strip _ga, fbclid, utm_* params from cache key to prevent cache fragmentation set req.url = regsuball(req.url, "(\?|&)(utm_[^&]+|fbclid|gclid|mc_[^&]+)(&|$)", "\1"); } sub vcl_hash { # Include Magento's context cookie in the cache hash if (req.http.cookie ~ "X-Magento-Vary=") { hash_data(regsub(req.http.cookie, ".*X-Magento-Vary=([^;]+).*", "\1")); } } sub vcl_backend_response { # Respect Magento's Cache-Control headers if (beresp.http.Cache-Control ~ "no-store") { set beresp.uncacheable = true; set beresp.ttl = 120s; } # Strip Set-Cookie on cacheable responses if (beresp.ttl > 0s) { unset beresp.http.set-cookie; } } -
为应用缓存和会话配置 Redis
<?php // app/etc/env.php — Redis cache and session configuration return [ 'cache' => [ 'frontend' => [ 'default' => [ 'id_prefix' => 'b0c_', 'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis', 'backend_options' => [ 'server' => '127.0.0.1', 'database' => '0', 'port' => '6379', 'password' => '', 'compress_data' => '1', 'compression_lib' => 'gzip', 'persistent' => 'mgto_cache', ], ], 'page_cache' => [ 'id_prefix' => 'b0c_', 'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis', 'backend_options' => [ 'server' => '127.0.0.1', 'database' => '1', // Separate DB for FPC 'port' => '6379', 'compress_data' => '0', // FPC data is already compressed HTML ], ], ], ], 'session' => [ 'save' => 'redis', 'redis' => [ 'host' => '127.0.0.1', 'port' => '6379', 'password' => '', 'timeout' => '2.5', 'persistent_identifier' => 'mgto_sessions', 'database' => '2', // Separate DB for sessions 'compression_threshold' => '2048', 'compression_library' => 'gzip', 'log_level' => '1', 'max_concurrency' => '6', 'break_after_frontend' => '5', 'max_lifetime' => '7200', 'disable_locking' => '1', // Improves performance but reduces session safety ], ], ]; -
为自定义模块实现缓存标签失效
Magento 使用缓存标签,在数据变更时有选择地使缓存页面失效。自定义模块应正确添加标签并清理缓存:
<?php // Declare cache tags in your block/model namespace MyVendor\CustomModule\Block; use Magento\Framework\View\Element\Template; use Magento\Framework\DataObject\IdentityInterface; class CustomProductWidget extends Template implements IdentityInterface { private array $productIds = []; public function getIdentities(): array { // Return cache tags so Magento invalidates this block when any of these products change $tags = [\Magento\Catalog\Model\Product::CACHE_TAG]; foreach ($this->productIds as $id) { $tags[] = \Magento\Catalog\Model\Product::CACHE_TAG . '_' . $id; } return $tags; } }<?php // In your observer or command — flush only relevant pages after product update namespace MyVendor\CustomModule\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\App\Cache\TypeListInterface; use Magento\PageCache\Model\Cache\Type as PageCacheType; class ProductSaveObserver implements ObserverInterface { public function __construct( private readonly TypeListInterface $cacheTypeList, private readonly \Magento\Framework\App\Cache\Tag\Resolver $tagResolver ) {} public function execute(\Magento\Framework\Event\Observer $observer): void { $product = $observer->getEvent()->getProduct(); // Invalidate only pages tagged with this product's cache tag // Varnish will purge via PURGE request using X-Magento-Tags-Pattern header $this->cacheTypeList->invalidate(PageCacheType::TYPE_IDENTIFIER); } }
示例
诊断索引延迟导致价格错误的问题
# Check if mview changelog has pending rows
bin/magento indexer:show-changelog
# If catalog_product_price has > 0 pending rows, prices are stale
# Run the indexer to catch up
bin/magento indexer:reindex catalog_product_price
# Check cron_schedule table for missed cron jobs (should run indexers every minute)
bin/magento cron:run --group index &
# Or manually via:
mysql -u root -e "SELECT job_code, status, finished_at FROM magento.cron_schedule WHERE job_code LIKE '%index%' ORDER BY finished_at DESC LIMIT 20;"
部署后预热 FPC
#!/bin/bash
# scripts/warm-cache.sh — warm the FPC after deploy
set -e
MAGENTO_BASE_URL="https://www.mystore.com"
SITEMAP_URL="$MAGENTO_BASE_URL/sitemap.xml"
echo "Flushing Magento caches..."
bin/magento cache:flush
echo "Warming FPC via sitemap..."
# Download sitemap and curl each URL with a warm-cache header
curl -s "$SITEMAP_URL" | \
grep -oP '<loc>\K[^<]+' | \
head -500 | \
xargs -P 10 -I {} curl -s -o /dev/null -w "%{http_code} {}\n" \
-H "X-Warm-Cache: 1" {}
echo "Cache warming complete."
最佳实践
- 在生产环境始终使用
Update by Schedule模式 —Update on Save会在管理员保存时同步重新索引,大型商品目录可能因此超时 - 为缓存、FPC 和会话使用独立的 Redis 数据库 — 所有内容都使用数据库 0 会导致键冲突,也无法单独清理某一类缓存
- 使用
IdentityInterface为自定义区块添加标签 — 这样在数据变更时,Varnish 和 Magento 的 FPC 才能使正确的页面失效 - 监控索引器变更日志表的大小 —
catalog_product_price_cl表中有数百万行,说明 cron 未运行;应在表过大导致重新索引超时前修复 cron - 使用
bin/magento cache:clean,而不是cache:flush—clean只会移除无效的缓存条目(安全);flush会清空所有内容,包括与其共用 Redis 的其他框架缓存 - 为每个环境设置不同的
id_prefix— 如果每个环境都使用唯一前缀,预发布环境和生产环境可以共用 Redis 服务,从而防止缓存污染 - 使用
curl -I和X-Cache标头测试 Varnish — 响应为HIT表示 Varnish 正在从缓存提供内容;MISS表示每个请求都在访问 Magento
常见问题
| 问题 | 解决方案 |
|---|---|
| 导入后商品不可见或价格错误 | 批量导入后运行 bin/magento indexer:reindex——如果直接使用 ResourceModel\Product::save,以编程方式保存商品并不总会触发索引器 |
| Varnish 向已登录的客户提供过时页面 | 确保 Varnish VCL 的哈希中包含 X-Magento-Vary cookie;已登录的客户会获得不同的 vary 值,从而绕过共享缓存 |
| Redis 内存不足 | 对缓存数据库,在 redis.conf 中设置 maxmemory-policy allkeys-lru;对会话数据库,使用 noeviction 以防会话静默丢失 |
| 保存商品后 FPC 未失效 | 检查 Varnish 的 PURGE ACL 是否允许来自 Magento 服务 IP 的请求;使用 curl -X PURGE http://varnish-ip/ 进行测试 |
| 全量重新索引耗时数小时并锁定表 | 在 env.php 中启用索引器批次大小,并使用 --mode realtime 运行以进行部分重新索引;安排在非高峰时段执行 |
| Cron 索引器未运行 | 检查 var/log/magento.cron.log 中的错误;确认系统 crontab 条目会以 Web 服务器用户身份每分钟运行一次 bin/magento cron:run |
相关技能
- @magento-module-development
- @magento-graphql
- @magento-multi-store
- @caching-strategies
- @infrastructure-performance
评论
支持 Markdown