Redis 6.0.4 removes meaningful replication offsets
Redis 6.0.4 removes an optimisation implicated in chained-replication corruption. Its upgrade guidance distinguishes the affected topology from direct replication and explains a hazardous transition window.
An optimisation intended to avoid full resynchronisation has made early Redis 6 replication harder to trust. Redis 6.0.4 removes the meaningful-offset feature entirely after the maintainers found multiple bugs, including data corruption in chained replication. The change accepts the cost of more full synchronisations in cases the optimisation tried to improve.
The release notes date 6.0.4 to May 28, 2020 and mark the upgrade critical. The tagged announcement explains both the original goal and the decision to remove the implementation. This is not a small correction that retains the feature. The maintainers judged its complexity too expensive and took it out.
I have used Redis since its release, and I value a replication mechanism whose state can be explained precisely. Avoiding an RDB transfer is useful, but the decision to reuse a history needs a trustworthy definition of where that history ends. This release is interesting because the maintainers explicitly give up an optimisation when that definition becomes difficult to reason about.
Why PING commands affected reuse of history
The removed feature addressed a particular failover case. A primary disconnected from the rest of its topology could continue sending PING commands to replicas. If another replica became primary, the old primary might later be demoted and asked to follow it. Its replication offset could have advanced beyond the promoted replica because of those final PING commands.
The optimisation trimmed trailing PINGs from the replication backlog. According to the release explanation, that let the old primary continue within the same replication history and receive only the missing difference. The intended benefit was avoiding a full synchronisation using an RDB snapshot.
This goal depends on distinguishing stream progress that matters to the dataset from progress consisting only of replication PINGs. The release called the resulting position a meaningful offset. The name described the intended distinction, but implementing it required adjusting the state used to identify and serve replication history.
That is a substantial place to add complexity. A replication offset participates in deciding whether another process can continue from its current data. It is not simply a number displayed in an informational response. Changing how it advances or how the backlog is trimmed changes the conditions under which reuse of existing data is accepted.
Partial synchronisation checks identity and coverage
The 6.0.4 replication implementation makes the surviving checks visible. When a replica asks to synchronise partially, the server parses the requested offset and checks the supplied replication identifier. The current identifier is acceptable. A secondary identifier can also be accepted, but only up to its recorded offset boundary.
That secondary identity supports a history transition. When a replica is promoted, the implementation retains the previous identifier as the secondary identifier and creates a new current one. It sets the old history's valid boundary to the current offset plus one because the requesting replica asks for the first byte it has not received.
The source gives a simple example. If the common history extends through byte fifty, a request starting at fifty-one can continue. The plus-one boundary expresses that request convention. It does not mean the replicas already share an additional byte of data.
Identity is only the first check. The server also requires a backlog containing the requested offset. A matching history identifier cannot help if the bytes needed to continue are no longer retained. The implementation rejects partial synchronisation when the backlog is missing or the requested position falls outside its coverage.
When both checks succeed, the server marks the connection as an online replica, sends a continuation response and transmits the relevant backlog data. Otherwise it takes the full-resynchronisation path. These checks explain the optimisation's appeal because successful reuse avoids sending an entire dataset, while also explaining why inaccurate history state can affect correctness.
Chained replication is the disclosed corruption case
The release notes identify chained replication as the dangerous topology. In that arrangement one replica follows another replica, so an intermediate process receives a replication stream and also supplies one to a downstream process. The disclosed risk applies to versions 6.0.0 through 6.0.3 in that arrangement.
The maintainers say they had not found a 6.0.3 bug affecting a topology with replicas attached directly to the primary. They still recommend upgrading older 6.0 deployments because confidence in the implementation has been damaged. Those statements need to remain distinct. The identified corruption case has a topology condition, while the upgrade recommendation is broader.
The announcement explicitly says Redis 5 users are unaffected and that starting directly with 6.0.4 is safe with respect to this issue. It also distinguishes upgrading from Redis 5 to 6.0.4 from the transition out of affected Redis 6 versions. Those are boundaries supplied by the release, not an inference that every replication problem in every version has been resolved.
Chaining matters to the implementation because a replica can also serve downstream history. The partial-synchronisation code updates replication identifiers after following a primary whose identity changes, and disconnects downstream replicas so they learn the new history. A process in the middle of a chain therefore participates on both sides of the protocol.
This is enough to explain why the topology deserves separate treatment without inventing the final corruption sequence. The release author says the team did not fully understand the last discovered bug even after fixing it. A more detailed causal account would require evidence beyond the announcement. The decision documented today is removal of the whole feature.
The upgrade has an intermediate state
For affected chained deployments, installing a fixed binary as a replica of an older primary is not the end of the transition. The release guidance says to wait for the first full synchronisation and then promote the new 6.0.4 instance promptly. It warns against allowing an intervening link failure to lead to another partial synchronisation while the older upstream remains in place.
The distinction is between a fully synchronised new instance and that instance's subsequent interactions with the old replication implementation. A transition can still include old behaviour even when the new process itself runs the fixed release. The topology and order of operations determine which implementation is producing the stream.
The notes offer an additional precaution involving a very large replication PING period. They also say that careful execution of the primary transition step makes this unnecessary and require restoring the default afterwards if the precaution is used. This should not become a permanent recommendation to disable ordinary liveness traffic.
The general implication is specific to this upgrade. A fixed destination version does not by itself describe the intermediate topology. The release therefore supplies transition guidance alongside its affected-version list. Both are needed to represent the maintainer's instructions accurately.
The patch also tightens replication input handling
The tagged notes record another replication change. Redis disconnects its upstream when it detects a protocol error and no longer accepts the inline protocol from that upstream. This is a separate check on the stream being consumed. It should not be presented as the mechanism that replaces meaningful offsets.
The release also improves PSYNC2 tests. Test changes can provide evidence about the cases they exercise, but the announcement does not claim an exhaustive proof of replication correctness. Its explanation is unusually explicit about the limits of the team's confidence in the removed feature.
There are other fixes in the patch, including TLS changes and restoration of thirty-two-bit testing. They do not dilute the main upgrade reason. The critical designation is tied to a replication bug, and the announcement gives affected chained deployments an immediate version and transition path.
I support the removal because the benefit has a narrower scope than the correctness obligation. Saving a full synchronisation helps a particular history-reuse case, while corruption affects the data the topology is supposed to preserve. Redis 6.0.4 restores the simpler choice when continuation cannot be established, with explicit guidance for leaving the affected chained configurations.
The surviving protocol still uses replication identities and offset coverage to decide when a partial transfer is possible. Its implementation documents the boundary retained after promotion and the bytes required in the backlog. Those are the conditions a reader can inspect in this release when explaining why a replica continues incrementally or requests a full dataset.