View Source NebulexRedisAdapter (NebulexRedisAdapter v2.4.2)
Nebulex adapter for Redis. This adapter is implemented using Redix,
a Redis driver for Elixir.
NebulexRedisAdapter provides three setup alternatives:
Standalone - The adapter establishes a pool of connections with a single Redis node. The
:standaloneis the default mode.Redis Cluster - Redis Cluster is a built-in feature in Redis since version 3, and it may be the most convenient and recommendable way to set up Redis in a cluster and have a distributed cache storage out-of-box. This adapter provides the
:redis_clustermode to set up Redis Cluster from the client-side automatically and be able to use it transparently.Built-in client-side cluster based on sharding - This adapter provides a simple client-side cluster implementation based on Sharding distribution model via
:client_side_clustermode.
Standalone
We can define a cache to use Redis as follows:
defmodule MyApp.RedisCache do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: NebulexRedisAdapter
endThe configuration for the cache must be in your application environment,
usually defined in your config/config.exs:
config :my_app, MyApp.RedisCache,
conn_opts: [
host: "127.0.0.1",
port: 6379
]Redis Cluster
We can define a cache to use Redis Cluster as follows:
defmodule MyApp.RedisClusterCache do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: NebulexRedisAdapter
endThe config:
config :my_app, MyApp.RedisClusterCache,
mode: :redis_cluster,
redis_cluster: [
configuration_endpoints: [
endpoint1_conn_opts: [
host: "127.0.0.1",
port: 6379,
# Add the password if 'requirepass' is on
password: "password"
],
...
]
]Client-side Cluster
We can define a cache with "client-side cluster mode" as follows:
defmodule MyApp.ClusteredCache do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: NebulexRedisAdapter
endThe config:
config :my_app, MyApp.ClusteredCache,
mode: :client_side_cluster,
client_side_cluster: [
nodes: [
node1: [
pool_size: 10,
conn_opts: [
host: "127.0.0.1",
port: 9001
]
],
node2: [
pool_size: 4,
conn_opts: [
url: "redis://127.0.0.1:9002"
]
],
node3: [
conn_opts: [
host: "127.0.0.1",
port: 9003
]
],
...
]
]Configuration options
In addition to Nebulex.Cache config options, the adapter supports the
following options:
:mode- Redis configuration mode.:standalone- A single Redis instance. See the "Standalone" section in the module documentation for more options.:redis_cluster- Redis Cluster setup. See the "Redis Cluster" section in the module documentation for more options.:client_side_cluster- See the "Client-side Cluster" section in the module documentation for more options.
The default value is
:standalone.:pool_size(pos_integer/0) - The number of connections that will be started by the adapter (based on the:mode). The default value isSystem.schedulers_online().:serializer- Custom serializer module implementing theNebulexRedisAdapter.Serializerbehaviour.:serializer_opts(keyword/0) - Custom serializer options. The default value is[].:encode_key(keyword/0) - Options for encoding the key. The default value is[].:encode_value(keyword/0) - Options for encoding the value. The default value is[].:decode_key(keyword/0) - Options for decoding the key. The default value is[].:decode_value(keyword/0) - Options for decoding the value. The default value is[].
:conn_opts(keyword/0) - Redis client options. SeeRedixdocs for more information about the options. The default value is[host: "127.0.0.1", port: 6379].:redis_cluster- Required only when:modeis set to:redis_cluster. A keyword list of options.See "Redis Cluster options" section below.
:client_side_cluster- Required only when:modeis set to:client_side_cluster. A keyword list of options.See "Client-side Cluster options" section below.
Redis Cluster options
The available options are:
:configuration_endpoints- Required. A keyword list of named endpoints where the key is an atom as an identifier and the value is another keyword list of options (same as:conn_opts).See "Redis Cluster" for more information.
:override_master_host(boolean/0) - Defines whether the given master host should be overridden with the configuration endpoint or not. Defaults tofalse.The adapter uses the host returned by the "CLUSTER SHARDS" (Redis >= 7) or "CLUSTER SLOTS" (Redis < 7) command. One may consider set it to
truefor tests when using Docker for example, or when Redis nodes are behind a load balancer that Redis doesn't know the endpoint of. See Redis docs for more information.The default value is
false.:keyslot- The module implementing theNebulex.Adapter.Keyslotbehaviour, which is used to compute the node where the command will be applied to. The default value isNebulexRedisAdapter.RedisCluster.Keyslot.
Client-side Cluster options
The available options are:
:nodes- Required. A keyword list of named nodes where the key is an atom as an identifier and the value is another keyword list of options (same as:conn_opts).See "Client-side Cluster" for more information.
:keyslot- The module implementing theNebulex.Adapter.Keyslotbehaviour, which is used to compute the node where the command will be applied to. The default value isNebulexRedisAdapter.ClientCluster.Keyslot.
Shared runtime options
Since the adapter runs on top of Redix, all commands accept their options
(e.g.: :timeout, and :telemetry_metadata). See Redix docs for more
information.
Redis Cluster runtime options
The following options apply to all commands:
:lock_retries- This option is specific to the:redis_clustermode. When the config manager is running and setting up the hash slot map, all Redis commands get blocked until the cluster is properly configured and the hash slot map is ready to use. This option defines the max retry attempts to acquire the lock and execute the command in case the configuration manager is running and all commands are locked. Defaults to:infinity.
Custom Keyslot
As it is mentioned in the configuration options above, the :redis_cluster
and :client_side_cluster modes have a default value for the :keyslot
option. However, you can also provide your own implementation by implementing
the Nebulex.Adapter.Keyslot and configuring the :keyslot option.
For example:
defmodule MyApp.ClusteredCache.Keyslot do
use Nebulex.Adapter.Keyslot
@impl true
def hash_slot(key, range) do
# your implementation goes here
end
endAnd the config:
config :my_app, MyApp.ClusteredCache,
mode: :client_side_cluster,
client_side_cluster: [
keyslot: MyApp.ClusteredCache.Keyslot,
nodes: [
...
]
]NOTE: For
:redis_clustermode, the:keyslotimplementation must follow the Redis cluster specification.
TTL or Expiration Time
As is explained in Nebulex.Cache, most of the write-like functions support
the :ttl option to define the expiration time, and it is defined in
milliseconds. Despite Redis work with seconds, the conversion logic
is handled by the adapter transparently, so when using a cache even with the
Redis adapter, be sure you pass the :ttl option in milliseconds.
Data Types
Currently. the adapter only works with strings, which means a given Elixir
term is encoded to a binary/string before executing a command. Similarly,
a returned binary from Redis after executing a command is decoded into an
Elixir term. The encoding/decoding process is performed by the adapter
under-the-hood. However, it is possible to provide a custom serializer via the
option :serializer. The value must be module implementing the
NebulexRedisAdapter.Serializer behaviour.
NOTE: Support for other Redis Data Types is in the roadmap.
Queryable API
Since the queryable API is implemented by using KEYS command,
keep in mind the following caveats:
- Only keys can be queried.
- Only strings and predefined queries are allowed as query values.
Predefined queries
nil- All keys are returned.{:in, [term]}- Only the keys in the given key list ([term]) are returned. This predefined query is only supported forNebulex.Cache.delete_all/2. This is the recommended way of doing bulk delete of keys.
Examples
iex> MyApp.RedisCache.put_all(%{
...> "firstname" => "Albert",
...> "lastname" => "Einstein",
...> "age" => 76
...> })
:ok
iex> MyApp.RedisCache.all("**name**")
["firstname", "lastname"]
iex> MyApp.RedisCache.all("a??")
["age"]
iex> MyApp.RedisCache.all()
["age", "firstname", "lastname"]
iex> stream = MyApp.RedisCache.stream("**name**")
iex> stream |> Enum.to_list()
["firstname", "lastname"]
# get the values for the returned queried keys
iex> "**name**" |> MyApp.RedisCache.all() |> MyApp.RedisCache.get_all()
%{"firstname" => "Albert", "lastname" => "Einstein"}Deleting multiple keys at once (bulk delete)
iex> MyApp.RedisCache.delete_all({:in, ["foo", "bar"]})
2Transactions
This adapter doesn't provide support for transactions. However, in the future,
it is planned support Redis Transactions by using the
commands MULTI, EXEC, DISCARD and WATCH.
Running Redis commands and/or pipelines
Since NebulexRedisAdapter works on top of Redix and provides features like
connection pools and "Redis Cluster" support, it may be seen also as a sort of
Redis client, but it is meant to be used mainly with the Nebulex cache API.
However, Redis API is quite extensive and there are a lot of useful commands
we may want to run taking advantage of the NebulexRedisAdapter features.
Therefore, the adapter provides two additional/extended functions to the
defined cache: command!/2 and pipeline!/2.
command!(command, opts \\ [])
iex> MyCache.command!(["LPUSH", "mylist", "world"], key: "mylist")
1
iex> MyCache.command!(["LPUSH", "mylist", "hello"], key: "mylist")
2
iex> MyCache.command!(["LRANGE", "mylist", "0", "-1"], key: "mylist")
["hello", "world"]
pipeline!(commands, opts \\ [])
iex> [
...> ["LPUSH", "mylist", "world"],
...> ["LPUSH", "mylist", "hello"],
...> ["LRANGE", "mylist", "0", "-1"]
...> ]
...> |> cache.pipeline!(key: "mylist")
[1, 2, ["hello", "world"]]
Options for command!/2 and pipeline!/2:
:key- It is required when used the adapter in mode:redis_clusteror:client_side_clusterso that the node where the commands will take place can be selected properly. For:standalonemode is not required (optional).:name- The name of the cache in case you are using dynamic caches, otherwise it is not required.
Since these functions run on top of Redix, they also accept their options
(e.g.: :timeout, and :telemetry_metadata). See Redix docs for more
information.
Telemetry
This adapter emits the recommended Telemetry events.
See the "Telemetry events" section in Nebulex.Cache
for more information.
Adapter-specific telemetry events for the :redis_cluster mode
Aside from the recommended Telemetry events by Nebulex.Cache, this adapter
exposes the following Telemetry events for the :redis_cluster mode:
telemetry_prefix ++ [:config_manager, :setup, :start]- This event is specific to the:redis_clustermode. Before the configuration manager calls Redis to set up the cluster shards, this event should be invoked.The
:measurementsmap will include the following::system_time- The current system time in native units from calling:System.system_time().
A Telemetry
:metadatamap including the following fields::adapter_meta- The adapter metadata.:pid- The configuration manager PID.
telemetry_prefix ++ [:config_manager, :setup, :stop]- This event is specific to the:redis_clustermode. After the configuration manager set up the cluster shards, this event should be invoked.The
:measurementsmap will include the following::duration- The time spent configuring the cluster. The measurement is given in the:nativetime unit. You can read more about it in the docs forSystem.convert_time_unit/3.
A Telemetry
:metadatamap including the following fields::adapter_meta- The adapter metadata.:pid- The configuration manager PID.:status- The cluster setup status. If the cluster was configured successfully, the status will be set to:ok, otherwise, will be set to:error.:error- The status reason. When the status is:ok, the reason is:succeeded, otherwise, it is the error reason.
telemetry_prefix ++ [:config_manager, :setup, :exception]- This event is specific to the:redis_clustermode. When an exception is raised while configuring the cluster, this event should be invoked.The
:measurementsmap will include the following::duration- The time spent configuring the cluster. The measurement is given in the:nativetime unit. You can read more about it in the docs forSystem.convert_time_unit/3.
A Telemetry
:metadatamap including the following fields::adapter_meta- The adapter metadata.:pid- The configuration manager PID.:kind- The type of the error::error,:exit, or:throw.:reason- The reason of the error.:stacktrace- The stacktrace.