跪拜 Guibai
← All articles
Frontend · Backend · Interview

Redis Cache Aside for Product Details: A Frontend Dev's Guide to Backend Caching

By swipe ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Product detail pages are the most-read, least-changed surface in e-commerce, and a poorly designed cache can silently serve stale data to every anonymous user. This walkthrough shows how to treat Redis as a disposable acceleration layer with explicit state handling, fail-open degradation, and self-healing—patterns that apply to any read-heavy API.

Summary

The `fullstack-mall` project adds a Redis Cache Aside layer to its public product detail endpoint to stop read-heavy traffic from hammering MySQL. The implementation models explicit cache states—HIT, MISS, NULL_HIT, DEGRADED, and BYPASS—so the business layer never guesses what a null return means. Null values for non-existent products are cached with a short TTL to prevent cache penetration, and any Redis failure triggers a fail-open degradation that falls back to the database instead of throwing a 500 error.

On the write side, product creation, status changes, and subtitle updates all delete the relevant cache key after a successful MySQL commit, rather than trying to update the cached JSON in place. This avoids field-assembly bugs and keeps the cache a discardable performance layer, not a second source of truth. Bad JSON in Redis is detected and deleted automatically, letting the next read self-heal by rebuilding from MySQL.

The article maps every backend concept to a frontend analogue—React Query cache, stale time, query keys—and provides curl commands, Redis CLI checks, and test strategies to verify the full MISS → PUT → HIT → EVICT → MISS lifecycle.

Takeaways
Cache Aside means the application code, not Redis or MySQL, decides when to read, backfill, or evict the cache.
Five explicit cache states (HIT, MISS, NULL_HIT, DEGRADED, BYPASS) replace a single null return, making business logic readable and debuggable.
Null-value caching with a short TTL (30s default) stops repeated requests for non-existent IDs from hitting the database.
Redis read exceptions are caught and converted to DEGRADED, allowing the request to fall back to MySQL instead of failing with a 500 error.
Write operations delete the cache after a successful MySQL commit, never update it in place, to avoid partial or inconsistent JSON assembly.
Bad JSON in Redis is detected on read, deleted, and treated as a MISS so the next request self-heals by rebuilding from the database.
Cache keys include a version segment (v1) so that future response-structure changes can roll out under a new key without complex migration logic.
Disabling the cache via a configuration flag (BYPASS) lets developers isolate whether stale data comes from Redis or from the database layer itself.
Conclusions

Explicit cache-state modeling is undervalued. Most systems collapse MISS, error, and disabled-cache into a single null, forcing callers to guess the system's health. A small enum eliminates that ambiguity.

The decision to delete rather than update the cache on writes is a deliberate trade-off: it accepts one extra database read on the next request in exchange for never assembling a broken or partial cached response from multiple write paths.

Self-healing from bad JSON is a cheap, high-leverage pattern. A single corrupted key can poison every subsequent request; deleting it on detection turns a persistent failure into a one-time blip.

TTL asymmetry between real values and null markers is a practical detail that many tutorials skip. A null TTL that's too long blocks newly created resources; one that's too short fails to prevent penetration.

Fail-open for a read cache is the correct default for most product-detail use cases. The database is the source of truth; a slower response is always better than a hard failure.

Concepts & terms
Cache Aside (Look-Aside Caching)
A caching strategy where the application checks the cache first; on a miss, it loads data from the database, writes it to the cache, and returns it. Writes go to the database first, then invalidate the cache. The cache never proactively syncs with the database.
Cache Penetration
A scenario where requests for data that will never exist (e.g., a non-existent product ID) consistently bypass the cache and hit the database, because the cache has no entry for that key. Mitigated by caching a short-TTL null marker.
Fail-Open (Degradation)
A resilience pattern where a system component failure (like a Redis outage) does not cause the overall operation to fail. Instead, the system falls back to a slower but functional path, such as querying the database directly.
Null Value Caching
Storing a special marker (e.g., `__NULL__:PRODUCT_NOT_FOUND`) in the cache with a short TTL to represent the confirmed absence of a resource, preventing repeated database queries for the same missing key.
Self-Healing (Bad JSON Eviction)
A cache maintenance technique where a value that fails deserialization is automatically deleted from the cache. The next request treats it as a cache miss, falls back to the database, and writes a fresh, valid entry.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗