A variation of
Multilevel
adapter that assumes Level 1 being Local
cache running in a distributed
cluster.
Add nebulex_local_multilevel_adapter
to your list of dependencies in mix.exs
:
def deps do
[
{:nebulex_local_multilevel_adapter, "~> 0.2.0"}
]
end
NebulexLocalMultilevelAdapter
setup resembles Nebulex.Adapters.Multilevel
with two exceptions: model
option is always
:inclusive
and the first level is autocreated:
defmodule MyApp.Cache do
use Nebulex.Cache,
otp_app: :slab,
adapter: NebulexLocalMultilevelAdapter
end
# This can be shared cache, e.g. Partitioned, Replicated, Memcached
defmodule MyApp.Cache.Redis do
use Nebulex.Cache,
otp_app: :slab,
adapter: NebulexRedisAdapter
end
Then configure MyApp.Cache
levels just like normal Multilevel
:
config :my_app, MyApp.Cache,
local_opts: [],
levels: [
{MyApp.Cache.Redis, []},
]
The adapter will automatically create MyApp.Cache.Local
L1 cache using options
provided in local_opts
.
LocalMultilevelAdapter
is different from Nebulex.Adapters.Multilevel
in a couple of ways:
- L1 is created automatically and uses
Nebulex.Adapters.Local
adapter - Other levels must be global for nodes, meaning they behave like a shared
storage. The simplest example is
NebulexRedisAdapter
, butReplicated
andPartitioned
should work too. - All write operations are asynchronously broadcasted to other nodes which invalidate affected keys in their local L1 caches.
There are several important things to keep in mind when working with a multilevel cache in a clustered environment:
- Always update the underlying storage (e.g. Ecto repo) first and invalidate the cache after to avoid a potential race condition when another client can write a stale value to the cache. The adapter follows this pattern moving from higher to lower levels with deletes.
- Keep in mind that invalidation messages are broadcasted without any confirmation from recipient nodes, so there is always a small chance of reading a stale value from the cache.
NebulexLocalMultilevelAdapter
relies on shared test code from Nebulex
repository, so you'll need to fetch it first
export NEBULEX_PATH=nebulex
mix nbx.setup
make sure epmd
is running:
epmd -daemon
From this it should be business as usual:
mix deps.get
mix test