RedisCluster.Cluster (redis_cluster v0.8.0)

View Source

The main module for interacting with a Redis cluster. Typically you will use the RedisCluster module. Though this module can be used directly for more dynamic use cases, such as connecting to a Redis cluster at runtime or in Livebook demos.

Summary

Types

A Redis command, which is a list of binary strings.

A key in Redis, which can be a binary, atom, or number. It will be converted to a string.

A list of key-value pairs or a map of key-value pairs.

A list of commands. Effectively a list of lists.

The role of a Redis node. Either a master or a replica.

A value in Redis, which can be a binary, atom, or number.

Functions

Sends the given pipeline to all nodes in the cluster. May filter on a specific role if desired, defaults to all nodes.

Similar to broadcast/3 but uses Task.async_stream/3 to send the commands in parallel.

Returns a specification to start this module under a supervisor.

Sends the given command to Redis. This allows sending any command to Redis that isn't already implemented in this module.

WARNING: This command is not a one-to-one mapping to the Redis DEL command. See the set_many/3 function for details why.

Similar to delete_many/3 but uses Task.async_stream/3 to delete the keys in parallel.

Calls the Redis DEL command without waiting for a reply.

WARNING: This command is not a one-to-one mapping to the Redis MGET command. See the set_many/3 function for details why.

Similar to get_many/3 but uses Task.async_stream/3 to fetch the values in parallel.

Sends a sequence of commands to Redis. This allows sending any command to Redis that isn't already implemented in this module. It sends the commands in one batch, reducing the number of round trips.

WARNING: This command is not a one-to-one mapping to the Redis MSET command.

Similar to set_many/3 but uses Task.async_stream/3 to set the values in parallel.

Types

command()

@type command() :: [binary()]

A Redis command, which is a list of binary strings.

key()

@type key() :: binary() | atom() | number()

A key in Redis, which can be a binary, atom, or number. It will be converted to a string.

pairs()

@type pairs() :: [{key(), value()}] | %{required(key()) => value()}

A list of key-value pairs or a map of key-value pairs.

pipeline()

@type pipeline() :: [command()]

A list of commands. Effectively a list of lists.

role()

@type role() :: :master | :replica

The role of a Redis node. Either a master or a replica.

value()

@type value() :: binary() | atom() | number()

A value in Redis, which can be a binary, atom, or number.

Functions

broadcast(config, commands, opts \\ [])

@spec broadcast(RedisCluster.Configuration.t(), pipeline(), Keyword.t()) :: [
  {host :: String.t(), port :: non_neg_integer(), role :: role(),
   result :: {:ok, [Redix.Protocol.redis_value()]} | {:error, any()}}
]

Sends the given pipeline to all nodes in the cluster. May filter on a specific role if desired, defaults to all nodes.

Note that this sends a pipeline instead of a single command. You can issue as many commands as you like and get the raw results back. The pipelines are sent to each node sequentially, so this may take some time. If you want to send the commands in parallel, use broadcast_async/3 instead. This is useful for debugging with commands like DBSIZE or INFO MEMORY. Be sure to only send commands that are safe to run on any node.

Options:

  • :role - The role to use when querying the cluster. Possible values are:
    • :any - Query any node (default).
    • :master - Query the master nodes.
    • :replica - Query the replica nodes.

broadcast_async(config, commands, opts \\ [])

@spec broadcast_async(RedisCluster.Configuration.t(), pipeline(), Keyword.t()) ::
  Enumerable.t()

Similar to broadcast/3 but uses Task.async_stream/3 to send the commands in parallel.

The results are returned as a Stream. You can collect the results into a list. Or you can take the first N items. Be aware ordering is not guaranteed.

Options:

  • :max_concurrency - The maximum number of concurrent tasks to run (default System.schedulers_online()).
  • :timeout - The max time in milliseconds to wait for each task to complete (default 5000).
  • :role - The role to use when querying the cluster. Possible values are:
    • :any - Query any node (default).
    • :master - Query the master nodes.
    • :replica - Query the replica nodes.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

command(config, command, opts)

This function is deprecated. Use `command/4` instead..
@spec command(RedisCluster.Configuration.t(), command(), Keyword.t()) ::
  term() | {:error, any()}

command(config, command, key, opts)

@spec command(RedisCluster.Configuration.t(), command(), key() | :any, Keyword.t()) ::
  term() | {:error, any()}

Sends the given command to Redis. This allows sending any command to Redis that isn't already implemented in this module.

Like pipeline/4, this function needs a key to determine which node to send the command to. If the command is safe to send to any node, you can use :any as the key. This will select a random node.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false). See RedisCluster.Key.hash_slot/2.
  • :role - The role to use when querying the cluster. Possible values are:
    • :master - Query the master node (default).
    • :replica - Query a replica node.
    • :any - Query any node.

delete(config, key, opts \\ [])

@spec delete(RedisCluster.Configuration.t(), key(), Keyword.t()) ::
  integer() | {:error, any()}

Calls the Redis DEL command.

Returns 1 if the key was deleted, 0 if the key was not found.

Since this is a write command, it will always target master nodes.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false).

delete_many(config, keys, opts \\ [])

@spec delete_many(RedisCluster.Configuration.t(), [key()], Keyword.t()) ::
  integer() | :ok | {:error, any()}

WARNING: This command is not a one-to-one mapping to the Redis DEL command. See the set_many/3 function for details why.

Deletes the listed keys and returns the number of keys that were deleted. Only unique DEL commands are sent. If there are duplicate keys, this number deleted will be less than total keys given.

Since this is a write command, it will always target master nodes.

Stops deleting keys if a MOVED error is encountered.

You may instruct the server to not return replies by setting :reply to false. This can save on bandwidth, reduce latency, and reduce processing on the server. If you follow up with GET commands for the same keys, the DEL commands may not have been processed yet. This means you may still get a value for the keys.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :reply - Whether to return replies from the server. (default true)

delete_many_async(config, keys, opts \\ [])

@spec delete_many_async(RedisCluster.Configuration.t(), [key()], Keyword.t()) ::
  integer() | :ok | {:error, any()}

Similar to delete_many/3 but uses Task.async_stream/3 to delete the keys in parallel.

Options:

  • :max_concurrency - The maximum number of concurrent tasks to run (default System.schedulers_online()).
  • :timeout - The max time in milliseconds to wait for each task to complete (default 5000).
  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :reply - Whether to return replies from the server. (default true)

delete_noreply(config, key, opts \\ [])

@spec delete_noreply(RedisCluster.Configuration.t(), key(), Keyword.t()) ::
  :ok | {:error, any()}

Calls the Redis DEL command without waiting for a reply.

This function does not wait for the server to confirm the deletion, which may reduce latency and reduce processing on the server. However, you won't know if the command was successful or not. Furthermore, if you follow up with GET commands for the same key, the DEL command may not have been processed yet.

Since this is a write command, it will always target master nodes.

Unlike delete/3, this function does not return the number of keys deleted. It will always return :ok or an error.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false).

get(config, key, opts \\ [])

@spec get(RedisCluster.Configuration.t(), key(), Keyword.t()) ::
  binary() | nil | {:error, any()}

Calls the Redis GET command.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false).
  • :role - The role to use when querying the cluster. Possible values are:
    • :master - Query the master node (default).
    • :replica - Query a replica node.
    • :any - Query any node.

get_many(config, keys, opts \\ [])

@spec get_many(RedisCluster.Configuration.t(), [key()], Keyword.t()) :: [
  String.t() | nil
]

WARNING: This command is not a one-to-one mapping to the Redis MGET command. See the set_many/3 function for details why.

Returns the values in the same order as the given keys. If a key is not found, nil is returned in its place.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :role - The role to use when querying the cluster. Possible values are:
    • :master - Query the master node (default).
    • :replica - Query a replica node.
    • :any - Query any node.

get_many_async(config, keys, opts \\ [])

@spec get_many_async(RedisCluster.Configuration.t(), [key()], Keyword.t()) :: [
  String.t() | nil
]

Similar to get_many/3 but uses Task.async_stream/3 to fetch the values in parallel.

Options:

  • :max_concurrency - The maximum number of concurrent tasks to run (default System.schedulers_online()).
  • :timeout - The max time in milliseconds to wait for each task to complete (default 5000).
  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :role - The role to use when querying the cluster. Possible values are:
    • :master - Query the master node (default).
    • :replica - Query a replica node.
    • :any - Query any node.

pipeline(config, commands, opts)

This function is deprecated. Use `pipeline/4` instead..
@spec pipeline(RedisCluster.Configuration.t(), pipeline(), Keyword.t()) ::
  [term()] | {:error, any()}

pipeline(config, commands, key, opts)

@spec pipeline(RedisCluster.Configuration.t(), pipeline(), key() | :any, Keyword.t()) ::
  [term()] | {:error, any()}

Sends a sequence of commands to Redis. This allows sending any command to Redis that isn't already implemented in this module. It sends the commands in one batch, reducing the number of round trips.

Responses are returned as a list in the same order as the commands.

The key is used to determine the hash slot which is mapped to a node. Commands like GET and SET only work with keys assigned to that node. Other commands like DBSIZE and INFO MEMORY can be sent to any node. If all commmands in the pipeline are safe to send to any node, you can use :any as the key. This will select a random node.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false). See RedisCluster.Key.hash_slot/2.
  • :role - The role to use when querying the cluster. Possible values are:
    • :master - Query the master node (default).
    • :replica - Query a replica node.
    • :any - Query any node.

set(config, key, value, opts \\ [])

@spec set(RedisCluster.Configuration.t(), key(), value(), Keyword.t()) ::
  :ok | {:error, any()}

Calls the Redis SET command.

By default doesn't set an expiration time for the key. Only :expire_seconds or :expire_milliseconds can be set, not both.

Since this is a write command, it will always target master nodes.

You may instruct the server to not wait for replies by setting :reply to false. This may reduce latency and reduce processing on the server. Be aware that you won't know if the command was successful or not. If you are using :only_new or :only_overwrite, you also won't know if the key was set. Furthermore, if you follow up with GET commands for the same key, the SET command may not have been processed yet.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default false).
  • :expire_seconds - The number of seconds until the key expires.
  • :expire_milliseconds - The number of milliseconds until the key expires.
  • :reply - Whether to wait for replies from the server. (default true)
  • :set - Controls when the key should be set. Possible values are:
    • :always - Always set the key (default).
    • :only_overwrite - Only set the key if it already exists.
    • :only_new - Only set the key if it doesn't exist.

set_many(config, pairs, opts \\ [])

@spec set_many(RedisCluster.Configuration.t(), pairs(), Keyword.t()) ::
  :ok | [{:error, any()}]

WARNING: This command is not a one-to-one mapping to the Redis MSET command.

All the keys in the list must hash to the same slot. This means they must hash to the exact value. It doesn't matter if those values map to the same node. If any key doesn't hash to the same value, the MSET command will fail.

The only way to guarantee keys hash to the same slot is to use a hash tag. Because of this, :compute_hash_tag is set to true by default.

Rather than use MSET this command sends a SET command for each key-value pair. Where possible, the SET commands are sent in a pipeline, saving one or more round trips.

Since SET is used, this function offers expiration and write options like set/3.

The downside to this approach is if the cluster reshards. The function will attempt all the SET commands, even if some of them will fail. Then it tries to rediscover the cluster if any of the commands failed. Though you will need to try your command again to ensure all the keys are set.

Since this sends write commands, it will always be target master nodes.

This function cannot guarantee which value is set when a key is included multiple times in one call.

The key-value pairs can be given as a list of tuples or a map.

Commands are sent sequentially for simplicity. This means the function will be slower than sending commands in parallel. If you need to set many keys in parallel, consider using set_many_async/3 instead.

You may instruct the server to not return replies by setting :reply to false. This can save on bandwidth, reduce latency, and reduce processing on the server. Be aware that you won't know if the commands were successful or not. If you are using :only_new or :only_overwrite, you also won't know which keys were set. Furthermore, if you follow up with GET commands for the same keys, the SET commands may not have been processed yet.

Options:

  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :expire_seconds - The number of seconds until the key expires.
  • :expire_milliseconds - The number of milliseconds until the key expires.
  • :reply - Whether to return replies from the server. (default true)
  • :set - Controls when the key should be set. Possible values are:
    • :always - Always set the key (default).
    • :only_overwrite - Only set the key if it already exists.
    • :only_new - Only set the key if it doesn't exist.

set_many_async(config, pairs, opts \\ [])

@spec set_many_async(RedisCluster.Configuration.t(), pairs(), Keyword.t()) ::
  :ok | [{:error, any()}]

Similar to set_many/3 but uses Task.async_stream/3 to set the values in parallel.

Options:

  • :max_concurrency - The maximum number of concurrent tasks to run (default System.schedulers_online()).
  • :timeout - The max time in milliseconds to wait for each task to complete (default 5000).
  • :compute_hash_tag - Whether to compute the hash tag of the key (default true).
  • :reply - Whether to return replies from the server. (default true)