Follower reads are a key feature that developers wanting to use multi-region databases should understand. We originally introduced them in this blog post, and later documented their use here.
In this post, we’ll quickly review the basics of follower reads, highlight some potential issues, and propose a new type of follower reads that we’re exploring to address those issues: bounded staleness reads.
What are follower reads?
Follower reads allow read-only queries to be served by any replica for a piece of data, not just the data’s leaseholder. In global deployments of CockroachDB, this ensures low-latency read access to all data in a database, regardless of data homing.
CockroachDB began by exposing only a simple form of follower reads, called exact staleness reads. These reads select how far in the past (“how stale”) to read ahead of time and then send the read request to the nearest copy of the requested data. If the requested data is fresh enough to satisfy the predetermined staleness, it is returned. This works well in most cases.
Potential issues with this approach
However, this strategy of guessing how far in the past to run a query ahead of time isn’t foolproof, and it can cause issues when the guess is wrong.
For instance, if a follower replica’s replication stream happens to lag momentarily, the follower may not be caught up enough to serve the read. As a result, the follower read must redirect to the leaseholder, incurring additional latency. The same thing happens in the more severe case of a follower replica that is disconnected entirely from its leaseholder due to a network partition.
Proposing a new option: bounded staleness reads
For these reasons, CockroachDB is exploring the addition of a second, slightly more complex form of follower reads, called bounded staleness reads. Bounded staleness reads invert the relationship between choosing the query timestamp and performing the read during follower reads. Instead of choosing the timestamp first, bounded staleness reads look at the data first to dynamically determine the optimal timestamp to read at. This minimizes staleness while also ensuring that the query is served locally and without blocking:
Bounded staleness reads are a form of historical read-only queries that use a dynamic, system-determined timestamp, subject to a user-provided staleness bound, to read nearby replicas while minimizing data staleness. They provide a new way to perform follower reads off local replicas to minimize query latency in multi-region clusters.
By dynamically determining the query timestamp, bounded staleness reads are more predictable than exact staleness reads in the presence of replication slowdown. However, their dynamic nature comes at a small performance cost. Additionally, they can also only be used in single-statement transactions, because they need to know the full set of rows that will be read ahead of time. As with everything, there are tradeoffs.
For readers who would like to dig deeper, we have published the full technical proposal here.