Redix.Cluster (Redix v1.5.3)

Copy Markdown View Source

Main API for using Redis Cluster.

For a higher-level guide, see the Cluster guide.

The design of this module follows the same low-level philosophy as the rest of Redix: it builds on existing Redix connections (one per cluster node), uses ETS for fast slot lookups, and mostly mirrors the Redix API.

Usage

You can start connections to a Redis Cluster similarly to how you'd start a single Redix connection, but specifying a list of seed nodes and a name:

{:ok, cluster} = Redix.Cluster.start_link(
  name: :my_cluster,
  nodes: ["redis://localhost:7000"]
)

Redix.Cluster.command(:my_cluster, ["SET", "mykey", "myvalue"])
#=> {:ok, "OK"}
Redix.Cluster.command(:my_cluster, ["GET", "mykey"])
#=> {:ok, "myvalue"}

Pipelines

Pipelines that span multiple hash slots are transparently split across nodes, executed in parallel, and reassembled in the original order:

Redix.Cluster.pipeline(:my_cluster, [
  ["SET", "key1", "a"],
  ["SET", "key2", "b"],
  ["GET", "key1"],
  ["GET", "key2"]
])
#=> {:ok, ["OK", "OK", "a", "b"]}

Transactions

MULTI/EXEC transactions require all keys to be in the same hash slot. Use hash tags to ensure this:

Redix.Cluster.transaction_pipeline(:my_cluster, [
  ["SET", "{user:1}.name", "Alice"],
  ["SET", "{user:1}.email", "alice@example.com"]
])

Limitations

  • Only database 0 is supported (Redis Cluster does not support SELECT).
  • Only primary nodes are used for reads (no replica reads).
  • Pub/Sub is not supported through the cluster interface (yet).
  • The :noreply_* functions are not supported in cluster mode.

Telemetry

Redix.Cluster emits cluster-specific Telemetry events for topology changes and redirections. See Redix.Telemetry for details.

Summary

Types

A node endpoint.

Functions

Returns a child spec for use in supervision trees.

Issues a command on the Redis Cluster.

Same as command/3 but raises on errors.

Issues a pipeline of commands on the Redis Cluster.

Starts a connection to a Redis Cluster.

Stops the cluster and all its connections.

Executes a MULTI/EXEC transaction on the Redis Cluster.

Types

endpoint()

(since 1.6.0)
@type endpoint() :: String.t() | [host: String.t(), port: :inet.port_number()]

A node endpoint.

It can be either a Redis URI string (such as "redis://localhost:7000") or a keyword list with :host and :port keys (such as [host: "localhost", port: 7000]).

Functions

child_spec(opts)

(since 1.6.0)
@spec child_spec(keyword()) :: Supervisor.child_spec()

Returns a child spec for use in supervision trees.

Examples

children = [
  {Redix.Cluster, name: :my_cluster, nodes: ["redis://localhost:7000"]}
]

command(cluster, command, opts \\ [])

(since 1.6.0)
@spec command(atom(), Redix.command(), keyword()) ::
  {:ok, Redix.Protocol.redis_value()}
  | {:error, atom() | Redix.Error.t() | Redix.ConnectionError.t()}

Issues a command on the Redis Cluster.

The command is routed to the correct node based on the key's hash slot. If the command has no key (PING), it is sent to a random node.

Returns {:ok, response} or {:error, reason}.

Options

  • :timeout - request timeout in milliseconds. Defaults to 5_000.

Examples

Redix.Cluster.command(:my_cluster, ["SET", "mykey", "foo"])
#=> {:ok, "OK"}

Redix.Cluster.command(:my_cluster, ["GET", "mykey"])
#=> {:ok, "foo"}

command!(cluster, command, opts \\ [])

(since 1.6.0)
@spec command!(atom(), Redix.command(), keyword()) :: Redix.Protocol.redis_value()

Same as command/3 but raises on errors.

pipeline(cluster, commands, opts \\ [])

(since 1.6.0)
@spec pipeline(atom(), [Redix.command()], keyword()) ::
  {:ok, [Redix.Protocol.redis_value()]}
  | {:error, atom() | Redix.Error.t() | Redix.ConnectionError.t()}

Issues a pipeline of commands on the Redis Cluster.

Commands are grouped by target node based on key hash slots, sent in parallel to the respective nodes, and results are reassembled in the original order.

Returns {:ok, results} or {:error, reason}.

Options

  • :timeout - request timeout in milliseconds. Defaults to 5_000.

Examples

Redix.Cluster.pipeline(:my_cluster, [["SET", "a", "1"], ["SET", "b", "2"]])
#=> {:ok, ["OK", "OK"]}

pipeline!(cluster, commands, opts \\ [])

(since 1.6.0)
@spec pipeline!(atom(), [Redix.command()], keyword()) :: [
  Redix.Protocol.redis_value()
]

Same as pipeline/3 but raises on errors.

start_link(opts)

(since 1.6.0)
@spec start_link(keyword()) :: Supervisor.on_start()

Starts a connection to a Redis Cluster.

Options

These are cluster-specific options:

  • :name (atom/0) - Required. An atom to register the cluster process under. All internal resources (ETS tables, Registry, connection supervisor) are named deterministically based on this name. You use this name to issue commands:

    Redix.Cluster.start_link(name: :my_cluster, nodes: [...])
    Redix.Cluster.command(:my_cluster, ["GET", "key"])
  • :nodes (list of endpoint/0) - Required. A list of seed nodes to connect to. Only one reachable node is needed: the full cluster topology is discovered automatically via CLUSTER SLOTS.

  • :topology_refresh_interval (timeout/0) - How often (in milliseconds) to refresh the cluster topology. The default value is 30000.

All other standard Redix connection options (:password, :ssl, :socket_opts, :timeout, and so on) are passed through to each underlying node connection.

Examples

Redix.Cluster.start_link(
  name: :my_cluster,
  nodes: ["redis://localhost:7000", "redis://localhost:7001"]
)

Redix.Cluster.start_link(
  name: :my_cluster,
  nodes: [[host: "redis1.example.com", port: 6379]],
  password: "secret"
)

stop(cluster, timeout \\ 60000)

(since 1.6.0)
@spec stop(atom(), timeout()) :: :ok

Stops the cluster and all its connections.

Examples

Redix.Cluster.stop(:my_cluster)

transaction_pipeline(cluster, commands, opts \\ [])

(since 1.6.0)
@spec transaction_pipeline(atom(), [Redix.command()], keyword()) ::
  {:ok, [Redix.Protocol.redis_value()]}
  | {:error, atom() | Redix.Error.t() | Redix.ConnectionError.t()}

Executes a MULTI/EXEC transaction on the Redis Cluster.

All commands must target the same hash slot (use hash tags to ensure this). Returns {:error, %Redix.Error{message: "CROSSSLOT" <> _}} if commands span multiple slots. At least one command must contain a key to route the transaction on; a pipeline of only keyless commands (such as PING) returns an error since there's no slot to send it to.

Options

  • :timeout - request timeout in milliseconds. Defaults to 5_000.

Examples

Redix.Cluster.transaction_pipeline(:my_cluster, [
  ["SET", "{user:1}.name", "Alice"],
  ["SET", "{user:1}.email", "alice@example.com"]
])
#=> {:ok, ["OK", "OK"]}

transaction_pipeline!(cluster, commands, opts \\ [])

(since 1.6.0)
@spec transaction_pipeline!(atom(), [Redix.command()], keyword()) :: [
  Redix.Protocol.redis_value()
]

Same as transaction_pipeline/3 but raises on errors.