March 31, 2020·4 min read·engineeringvalkeyredistimeouts

Redis RC3 orders blocked-client deadlines explicitly

Redis 6.0 RC3 fixes a critical connection-management crash and introduces ordered timeout tracking for blocking commands. The timeout implementation separates request waiting from idle-connection handling.

The number of connected clients should not determine how precisely a blocking operation reaches its timeout. Redis 6.0 RC3 changes that part of the server by tracking blocked-client deadlines in a radix tree ordered by expiration time. The release also carries a critical connection-management fix associated with the SSL refactoring. This candidate is therefore both a correctness update and a change in how the server schedules waiting clients.

The release notes date RC3 to March 31, 2020. The versioned copy marks upgrade urgency critical because the connection bug can easily crash Redis. That description is stronger than a general statement that the candidate prepares new networking features. Users testing earlier candidates have a concrete crash fix to account for.

I have used Redis since its release, and its compact command model remains attractive to me. Blocking operations show how much scheduling behaviour can sit behind a small command interface. A timeout argument needs an implementation that can find the relevant client without making its precision depend on an unrelated population of connections.

Deadlines become an ordered set

The RC3 timeout implementation constructs sixteen-byte keys for its timeout tree. Its first eight bytes encode the expiration time in big-endian form. The remaining portion holds the client pointer, with padding on a thirty-two-bit target. The timestamp at the start of the key gives the tree an ordering by deadline.

The source comments still use client-ID terminology in places, but the encoding and decoding functions copy the pointer directly. That detail matters when explaining what the structure contains. The implementation gives each deadline entry enough information to find the client that needs attention.

Clients with a zero timeout are not added to the tree. In this path zero means waiting indefinitely, so there is no deadline to schedule. When a client blocks with a finite timeout, insertion marks it with a flag indicating that it is present in the table.

Removal also has an explicit path. When a client unblocks for a reason other than expiration, the server removes its entry and clears the flag. This is necessary because a waiting operation can complete before its deadline. A timeout index must stop representing a wait that has already ended.

The scan stops at the first future deadline

The handler begins at the start of the radix tree and decodes the earliest entry. If the stored timeout is greater than or equal to the current time, the scan stops. Every subsequent entry is also in the future because the timestamp is the leading part of the sorted key.

For an expired entry, the handler checks whether the client is still blocked with an expired nonzero timeout. It then sends the operation-specific timeout response and unblocks the client when appropriate. The processed tree entry is removed, and iteration returns to the start of the tree.

The source says this handling runs in the event loop's before-sleep phase. The release notes describe the resulting precision as HZ resolution independent of the number of connected clients. That is a statement about the scheduling granularity the release supplies. It should not be translated into a hard real-time guarantee under every execution delay.

Ordering the deadlines makes the relevant work identifiable. The server can stop when it reaches a future timeout instead of treating every connected client as equally relevant to the current deadline check. This explains the mechanism behind the release-note claim without inventing a latency measurement.

Idle connections are a different case

The same file retains idle-client handling in the client cron function. That path checks the configured maximum idle time and the client's last interaction. It excludes replication connections, blocked clients and publish-subscribe clients from ordinary idle disconnection.

Those exclusions show why a blocking-command timeout is not simply the server's idle-connection timeout. A client waiting on a blocking operation can be doing exactly what its command requested. Closing its connection for inactivity would express a different result from returning the command-specific timeout response.

The timeout parser also preserves this distinction. It converts the supplied duration to milliseconds and then to an absolute expiration time for positive values. Negative durations produce an error. A zero value remains zero, preserving the indefinite-wait interpretation used by insertion into the deadline table.

Candidate fixes affect client-visible semantics

RC3 includes changes beyond scheduling. Its release notes say that a read-only error now aborts transactions, and that the default ACL user is treated as disabled when marked off regardless of the passwordless flag. These are rules about whether a request may continue. They are not interchangeable with a general performance improvement.

The candidate also fixes threaded-I/O bugs and a crash related to resizing the event loop after changing the maximum client count. These items make the connection-management urgency relevant to testing the new networking implementation. The candidate label still describes the stage of the release being evaluated.

I value the timeout change because the source makes the waiting state inspectable. Finite deadlines enter an ordered structure, early completion removes them, and the event loop handles expired entries. RC3 pairs that mechanism with an explicitly critical crash fix, giving users of earlier candidates a specific reason to replace their test build.