Skip to content

Commit d2eb4cc

Browse files
committed
Release v3.0.0-rc.1 🔖
1 parent a06da33 commit d2eb4cc

File tree

4 files changed

+59
-37
lines changed

4 files changed

+59
-37
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ cache topologies, but this feature will depend on the adapters. Here is where
1515
**"Nebulex Distributed"** comes in. It provides the following adapters to set up
1616
distributed topologies:
1717

18-
* `Nebulex.Adapters.Partitioned` - Partitioned cache topology.
19-
* `Nebulex.Adapters.Multilevel` - Multi-level distributed cache topology.
18+
* [`Nebulex.Adapters.Partitioned`][partitioned] - Partitioned cache topology.
19+
* [`Nebulex.Adapters.Multilevel`][multilevel] - Multi-level or near cache
20+
topology.
2021
* `Nebulex.Adapters.Replicated` - Replicated cache topology (**WIP!**).
2122

2223
These adapters work more as wrappers for an existing local adapter and provide
2324
the distributed topology on top of it. You can optionally set the adapter for
2425
the primary cache storage with the option `:primary_storage_adapter`.
2526

27+
[partitioned]: http://hexdocs.pm/nebulex_distributed/Nebulex.Adapters.Partitioned.html
28+
[multilevel]: http://hexdocs.pm/nebulex_distributed/Nebulex.Adapters.Multilevel.html
29+
2630
## Installation
2731

2832
`:nebulex_distributed` requires Erlang/OTP 25 or later. Then add

lib/nebulex/adapters/partitioned.ex

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ defmodule Nebulex.Adapters.Partitioned do
55
## Features
66
77
* Partitioned cache topology (Sharding Distribution Model).
8-
* Configurable primary storage adapter.
98
* `ExHashRing` for distributing the keys across the cluster members.
109
* Support for transactions via Erlang global name registration facility.
10+
* Configurable primary storage adapter.
1111
1212
## Partitioned Cache Topology
1313
@@ -59,15 +59,34 @@ defmodule Nebulex.Adapters.Partitioned do
5959
`:pg` is used under-the-hood by the adapter to manage the cluster nodes.
6060
When the partitioned cache is started in a node, it creates a group and joins
6161
it (the cache supervisor PID is joined to the group). Then, when a function
62-
is invoked, the adapter picks a node from the group members, and then the
63-
function is executed on that specific node. In the same way, when a
64-
partitioned cache supervisor dies (the cache is stopped or killed for some
65-
reason), the PID of that process is automatically removed from the PG group;
66-
this is why it's recommended to use consistent hashing for distributing the
67-
keys across the cluster nodes.
62+
is invoked, the adapter uses `ExHashRing` to determine which node should
63+
handle the request based on the key's hash value. This ensures consistent
64+
key distribution across the cluster nodes, even when nodes join or leave
65+
the cluster.
66+
67+
The key distribution process works as follows:
68+
69+
1. Each node in the cluster is assigned a set of virtual nodes (vnodes) in
70+
the hash ring.
71+
2. When a key is accessed, `ExHashRing.Ring` is used to find the node
72+
responsible for that key (the hash value is used to find the corresponding
73+
vnode in the hash ring).
74+
3. The request is routed to the physical node that owns that vnode.
75+
76+
This consistent hashing approach provides several benefits:
77+
78+
* Minimal key redistribution when nodes join or leave the cluster.
79+
* Even distribution of keys across the cluster.
80+
* Predictable key-to-node mapping.
81+
* Efficient node lookup for key operations.
82+
83+
When a partitioned cache supervisor dies (the cache is stopped or killed for some
84+
reason), the PID of that process is automatically removed from the PG group.
85+
The hash ring is then automatically rebalanced to ensure keys are properly
86+
distributed among the remaining nodes.
6887
6988
This adapter depends on a local cache adapter (primary storage), it adds
70-
a thin layer on top of it in order to distribute requests across a group
89+
an extra layer on top of it in order to distribute requests across a group
7190
of nodes, where is supposed the local cache is running already. However,
7291
you don't need to define any additional cache module for the primary
7392
storage, instead, the adapter initializes it automatically (it adds the
@@ -502,7 +521,7 @@ defmodule Nebulex.Adapters.Partitioned do
502521
end
503522
end
504523

505-
def do_put_all(action, adapter_meta, entries, ttl, opts) do
524+
defp do_put_all(action, adapter_meta, entries, ttl, opts) do
506525
timeout = Keyword.fetch!(opts, :timeout)
507526
opts = [ttl: ttl] ++ opts
508527

mix.exs

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,14 @@ defmodule NebulexDistributed.MixProject do
3131

3232
# Hex
3333
package: package(),
34-
description: "A generational local cache adapter for Nebulex",
34+
description: "Distributed cache topologies adapters for Nebulex",
3535

3636
# Docs
3737
name: "Nebulex.Distributed",
3838
docs: docs()
3939
]
4040
end
4141

42-
defp docs do
43-
[
44-
main: "Nebulex.Distributed",
45-
source_ref: "v#{@version}",
46-
source_url: @source_url,
47-
canonical: "http://hexdocs.pm/nebulex_distributed",
48-
groups_for_modules: [
49-
Adapters: [
50-
Nebulex.Adapters.Multilevel,
51-
Nebulex.Adapters.Partitioned
52-
],
53-
Utilities: [
54-
Nebulex.Distributed.Cluster,
55-
Nebulex.Distributed.RPC
56-
]
57-
]
58-
]
59-
end
60-
6142
defp elixirc_paths(:test), do: ["lib", "test/support"]
6243
defp elixirc_paths(_), do: ["lib"]
6344

@@ -72,7 +53,7 @@ defmodule NebulexDistributed.MixProject do
7253
[
7354
nebulex_dep(),
7455
{:nebulex_local, "~> 3.0.0-rc.1"},
75-
{:ex_hash_ring, "~> 7.0", override: true},
56+
{:ex_hash_ring, "~> 6.0 or ~> 7.0"},
7657
{:telemetry, "~> 0.4 or ~> 1.0", optional: true},
7758

7859
# Test & Code Analysis
@@ -98,7 +79,7 @@ defmodule NebulexDistributed.MixProject do
9879
if path = System.get_env("NEBULEX_PATH") do
9980
{:nebulex, path: path, override: true}
10081
else
101-
{:nebulex, "~> #{@nbx_vsn}", override: true}
82+
{:nebulex, "~> #{@nbx_vsn}"}
10283
end
10384
end
10485

@@ -122,17 +103,35 @@ defmodule NebulexDistributed.MixProject do
122103

123104
defp package do
124105
[
125-
name: :nebulex_local,
106+
name: :nebulex_distributed,
126107
maintainers: [
127-
"Carlos Bolanos",
128-
"Felipe Ripoll"
108+
"Carlos Bolanos"
129109
],
130110
licenses: ["MIT"],
131111
links: %{"GitHub" => @source_url},
132112
files: ~w(lib .formatter.exs mix.exs README* CHANGELOG* LICENSE*)
133113
]
134114
end
135115

116+
defp docs do
117+
[
118+
main: "Nebulex.Distributed",
119+
source_ref: "v#{@version}",
120+
source_url: @source_url,
121+
canonical: "http://hexdocs.pm/nebulex_distributed",
122+
groups_for_modules: [
123+
Adapters: [
124+
Nebulex.Adapters.Multilevel,
125+
Nebulex.Adapters.Partitioned
126+
],
127+
Utilities: [
128+
Nebulex.Distributed.Cluster,
129+
Nebulex.Distributed.RPC
130+
]
131+
]
132+
]
133+
end
134+
136135
defp dialyzer do
137136
[
138137
plt_add_apps: [:nebulex, :mix],

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
1313
"ex2ms": {:hex, :ex2ms, "1.7.0", "45b9f523d0b777667ded60070d82d871a37e294f0b6c5b8eca86771f00f82ee1", [:mix], [], "hexpm", "2589eee51f81f1b1caa6d08c990b1ad409215fe6f64c73f73c67d36ed10be827"},
1414
"ex_doc": {:hex, :ex_doc, "0.38.2", "504d25eef296b4dec3b8e33e810bc8b5344d565998cd83914ffe1b8503737c02", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "732f2d972e42c116a70802f9898c51b54916e542cc50968ac6980512ec90f42b"},
15-
"ex_hash_ring": {:hex, :ex_hash_ring, "7.0.0", "2d92d90669019536abaab7db6ccf00cb33c323e43a1fb44f1f16177a3d777a99", [:mix], [], "hexpm", "9f61f33f043a69e9df9febe6df05ddb0ec78227a43aad8407503e2cd81715c5b"},
15+
"ex_hash_ring": {:hex, :ex_hash_ring, "6.0.4", "bef9d2d796afbbe25ab5b5a7ed746e06b99c76604f558113c273466d52fa6d6b", [:mix], [], "hexpm", "89adabf31f7d3dfaa36802ce598ce918e9b5b33bae8909ac1a4d052e1e567d18"},
1616
"excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"},
1717
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
1818
"ham": {:hex, :ham, "0.3.0", "7cd031b4a55fba219c11553e7b13ba73bd86eab4034518445eff1e038cb9a44d", [:mix], [], "hexpm", "7d6c6b73d7a6a83233876cc1b06a4d9b5de05562b228effda4532f9a49852bf6"},

0 commit comments

Comments
 (0)