January 24, 2018·4 min read·engineeringvalkeyredismemoryreplication

Redis 4.0.7 corrects list memory accounting and replica scripting

Redis 4.0.7 fixes a list memory estimate that confused elements with storage nodes. It also permits read-only Lua scripts on cluster replicas and preserves replication backlog after promotion.

A memory estimate can be wrong even when it samples the right objects. Redis 4.0.7 fixes precisely that problem for lists. The estimator measures quicklist nodes, then previously multiplied their average size by the number of list elements. Because a node can contain multiple elements, those quantities are not interchangeable. The repair changes the multiplier to the number of quicklist nodes.

The January 24 entry in the Redis 4.0 release notes classifies 4.0.7 as a moderate-urgency maintenance release. Its version-pinned notes also describe read-only scripting on cluster replicas and a replication-backlog repair. Each change corrects a different mismatch between a logical operation and the internal machinery supporting it.

I like Redis for the direct relationship between its data structures and application operations. That makes accurate accounting especially useful. An application can choose a list for sound semantic reasons and still make a poor capacity decision if its memory measurements use the wrong unit.

Elements and storage nodes have different counts

The list-accounting patch changes one line in objectComputeSize. Each sample includes a quicklist node and the ziplist blob associated with it. The estimate then extrapolates that average across the container.

The quicklist definition in this release distinguishes count, the total entries across all ziplists, from len, the number of quicklist nodes. That distinction explains the error without requiring a benchmark. Sampling storage nodes produces a per-node average, so extrapolation needs the node count.

This change affects the answer reported by MEMORY USAGE for list values. It does not claim to change the list's contents or eliminate the storage overhead represented by those nodes. An apparent reduction in the reported size after upgrading can therefore be an accounting correction.

A useful interpretation of such a measurement includes both the logical length and the representation used to store it. Two lists with the same number of elements need not have identical storage costs. Element sizes and packing affect the physical structure. The patch corrects the unit used in the estimate, without making list length a substitute for memory measurement.

The difference is also relevant to comparing data structures. If one candidate's memory figure is overestimated by multiplying a per-container sample by an element count, a capacity comparison is distorted before any application tradeoff is considered. The release repairs that input to the decision.

Cluster replicas can execute read-only scripts

The cluster scripting change adjusts routing for clients that have requested read-only operation. The condition already permits read-only commands on a replica whose primary serves the requested hash slot. It now also admits EVAL and EVALSHA through that routing decision.

Allowing those commands through routing does not grant a script unrestricted writes. The 4.0.7 scripting implementation checks commands invoked by Lua. It rejects write commands against read-only replicas under the corresponding conditions and checks cluster-local key access for the commands the script invokes.

This division of responsibility matters. The outer command identifies a script invocation, but its actual Redis operations occur inside Lua execution. Rejecting every script at the routing step prevents legitimate reads. Admitting the invocation while enforcing command-level restrictions allows the read-only case.

The change is narrower than a general distributed scripting facility. Its routing condition concerns a replica of the primary responsible for the hash slot. Script-internal checks still reject non-local key access. A script does not gain permission to gather arbitrary keys across a cluster simply because it only reads them.

I favor that separation because it preserves the meaning of read-only access while allowing useful composition. The implementation places the detailed write check where the invoked command is known. That makes the release's claim more precise than saying that all Lua scripts now work on replicas.

Promotion needs a fresh backlog lifetime

The replication fix addresses a time-dependent failure after promotion. A replica promoted after more than an hour of uptime could lose its replication backlog at the next periodic replication check. Another replica arriving shortly afterwards could then fail to perform partial synchronization and require full synchronization.

The correction records the time at which the server becomes a primary and loses its attached replicas. That gives the backlog-retention logic a timestamp corresponding to the new role. The old uptime-related state could otherwise make the backlog appear eligible for removal immediately.

The release notes explain that the one-hour condition escaped the unit tests. It is a specific example of behavior depending on process history, beyond the commands used in a short reproduction. The patched timestamp preserves the opportunity for partial synchronization after the role change.

Taken together, these changes improve the information and transitions surrounding ordinary Redis operations. List memory inspection uses the correct physical count. Cluster routing permits scripts whose commands satisfy replica restrictions, and promotion retains the backlog according to the new replication role's timing.