Redis::ReplicationClient
Inherits Redis::Commands::Immediate < Redis::Commands < Redis::Commands::Vector < Redis::Commands::HyperLogLog < Redis::Commands::Geo < Redis::Commands::Stream < Redis::Commands::SortedSet < Redis::Commands::Set < Redis::Commands::List < Redis::Commands::Hash < Reference < Object
If you're using Redis replication, you can use ReplicationClient to send
read commands to replicas and reduce load on the primary. This can be important
when your Redis primary is CPU-bound.
The commands that will be routed to replicas are listed in
Redis::READ_ONLY_COMMANDS.
NOTE: Redis replication does not provide consistency guarantees. Every
mechanism in Redis to improve consistency, such as
WAIT, is best-effort,
but not guaranteed. If you require strong consistency from Redis, stick to
using Redis::Client. if you require strong consistency but your Redis primary
is CPU-bound, you may need to either choose between consistency and performance
or move that workload out of Redis.
This client is useful for operations where strong consistency isn't typically
needed, such as caching, full-text search with Redis::FullText#search,
querying time-series data with Redis::TimeSeries#mrange, checking the current
state of larger data structures without blocking the primary, etc.
Explicitly routing commands to a primary or replica
This class provides on_primary and on_replica methods to ensure your
command is routed to the server type you want. This is useful in several
scenarios:
- you want to ensure you retrieve a value that is consistent with the state of the primary server — for example a value that changes frequently and you need the canonical state for observability purposes
- a read-only command is routed to a primary because this client does not yet
know about it
- You can add commands to
Redis::READ_ONLY_COMMANDSin one-off cases - Feel free to open an issue or pull request to add it, as well
- You can add commands to
Topology changes
If the replication topology changes (for example, new replicas are added,
existing ones removed, or the primary failed over), ReplicationClient will
automatically pick up the changes. You can set how often it checks for these
changes with the topology_ttl argument to the constructor or leave it at its
default of 10 seconds.
Constants
Constructors
Have the ReplicationClient discover the master and replicas on its own
when given the URI of a single entrypoint. The cluster topology will be
refreshed with a max staleness of topology_ttl.
redis = Redis::ReplicationClient.new(
Initialize the client with known master and replica URIs, keeping the
toplogy up to date with at most topology_ttl staleness. If you don't wish
to keep the replication topology up to date, you can simply set
topology_ttl to 0.seconds.
Instance methods
Route one or more commands to the primary to avoid consistency issues arising from replication latency.
require "redis/replication_client"
redis = Redis::ReplicationClient.new
redis.incr "counter"
value = redis.on_primary &.get("counter")
This is useful for pipelining commands or executing transactions:
redis.on_primary &.transaction do |txn|
txn.incr "counter:#{queue}"
txn.sadd "queues", queue
txn.lpush "queue:#{queue}", job_data
end
… which is shorthand for this and removes the need for nesting blocks:
redis.on_primary do |primary|
primary.transaction do |txn|
txn.incr "counter:#{queue}"
txn.sadd "queues", queue
txn.lpush "queue:#{queue}", job_data
end
end
If you need to route many commands to the primary without necessarily
pipelining or opening transactions, you can omit the &.transaction and
call methods directly on the primary's Redis::Client in the block:
redis.on_primary do |primary|
counter = primary.incr "counter:#{queue}"
primary.sadd "queues", queue
end
NOTE: The object yielded to the block is a Redis::Client, but if you try
to use it outside the block you may run into errors because the replication
topology could change, in which case this Redis::Client might not be the
primary anymore.
Route one or more commands to replicas. This should rarely be necessary since
read-only commands (which can only be executed on replicas) are automatically
routed to replicas, but if it's a command this shard does not know about (see
Redis::READ_ONLY_COMMANDS) this may be necessary. Alternatively, you can
shovel additional commands into Redis::READ_ONLY_COMMANDS to avoid having to
perform this explicit routing.
Execute the given command and return the result from the server. Commands
must be an Enumerable and its size method must be re-entrant.
run({"set", "foo", "bar"})