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"}
]
endNebulexLocalMultilevelAdapter 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
endThen 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.Localadapter - Other levels must be global for nodes, meaning they behave like a shared
storage. The simplest example is
NebulexRedisAdapter, butReplicatedandPartitionedshould 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.setupmake sure epmd is running:
epmd -daemonFrom this it should be business as usual:
mix deps.get
mix test