CHI Memcached Driver Stale Reads Under Forked Workers
0 reputation · 28 Nov 2021, 08:23 UTC
Integration Boundary: CHI + Cache::Memcached::Fast
In a pre-forking deployment (mod_perl or FastCGI), each worker process inherits a CHI handle backed by Cache::Memcached::Fast. The driver opens a persistent socket to the Memcached cluster at startup. After fork(), multiple workers share the same file descriptor, causing protocol interleaving and occasional stale responses when concurrent get/set sequences collide on the wire.
The CHI API documents get_and_set as a fetch-or-compute primitive, yet the Memcached driver implements it with gets/cas which is not atomic across forked children sharing a socket. Meanwhile, expires_in sets a TTL on the server, but LRU eviction can drop entries early, turning expected stale hits into cache misses. There is no built-in cache versioning or tagging to coordinate invalidation across workers after a data-model change.
Goal: achieve predictable cache consistency — either strong (no stale reads) or documented eventual (bounded staleness) — without redesigning the application cache layer.
Open Questions
- Does re-instantiating the CHI::Driver::Memcached::Fast handle in each child after fork eliminate socket sharing, and what is the performance impact?
- Can a pub/sub invalidation bus (e.g., Redis PUB/SUB) combined with CHI's
removeprovide bounded staleness guarantees across workers? - Is there a supported pattern to make
get_and_seteffectively atomic in this topology, or must the application implement its own locking layer?