All Projects → bitwalker → Libring

bitwalker / Libring

Licence: other
A fast consistent hash ring implementation in Elixir

Programming Languages

elixir
2628 projects

Labels

Projects that are alternatives of or similar to Libring

Lodestar
🌟 Ethereum 2.0: TypeScript Implementation of the Beacon Chain
Stars: ✭ 363 (+124.07%)
Mutual labels:  sharding
Chainspace Prototype
Chainspace is a distributed ledger platform for high-integrity and transparent processing of transactions within a decentralized system.
Stars: ✭ 41 (-74.69%)
Mutual labels:  sharding
Redis Tools
my tools working with redis
Stars: ✭ 104 (-35.8%)
Mutual labels:  sharding
Weaver
An Advanced HTTP Reverse Proxy with Dynamic Sharding Strategies
Stars: ✭ 510 (+214.81%)
Mutual labels:  sharding
Mango
Distributed ORM Framework for Java
Stars: ✭ 906 (+459.26%)
Mutual labels:  sharding
Zanredisdb
Yet another distributed kvstore support redis data and index. moved to: https://github.com/youzan/ZanRedisDB
Stars: ✭ 64 (-60.49%)
Mutual labels:  sharding
Shards
Partitioned ETS tables for Erlang and Elixir
Stars: ✭ 266 (+64.2%)
Mutual labels:  sharding
Wotrd Cloud
基于nacos包含网关、认证授权、服务注册、发现、断路降级、限流、配置中心、分库分表等基础组件
Stars: ✭ 135 (-16.67%)
Mutual labels:  sharding
Lighthouse
Rust Ethereum 2.0 Client
Stars: ✭ 971 (+499.38%)
Mutual labels:  sharding
Dble Docs Cn
Documents for dble in Chinese
Stars: ✭ 80 (-50.62%)
Mutual labels:  sharding
Citus
Distributed PostgreSQL as an extension
Stars: ✭ 5,580 (+3344.44%)
Mutual labels:  sharding
Dble
A High Scalability Middle-ware for MySQL Sharding
Stars: ✭ 774 (+377.78%)
Mutual labels:  sharding
Cetus
Cetus is a high performance middleware that provides transparent routing between your application and any backend MySQL Servers.
Stars: ✭ 1,199 (+640.12%)
Mutual labels:  sharding
Sharding
Sharding manager contract, and related software and tests
Stars: ✭ 461 (+184.57%)
Mutual labels:  sharding
Mosaic Contracts
Mosaic-0: Gateways and anchors on top of Ethereum to scale DApps
Stars: ✭ 119 (-26.54%)
Mutual labels:  sharding
Harmony
The core protocol of harmony
Stars: ✭ 351 (+116.67%)
Mutual labels:  sharding
Mixed gauge
A simple and robust database sharding with ActiveRecord.
Stars: ✭ 58 (-64.2%)
Mutual labels:  sharding
Ton
Telegram Open Network research group. Telegram: https://t.me/ton_research
Stars: ✭ 146 (-9.88%)
Mutual labels:  sharding
Lealone
极具创新的面向微服务和 OLTP/OLAP 场景的单机与分布式关系数据库
Stars: ✭ 1,802 (+1012.35%)
Mutual labels:  sharding
Cypress Parallel
Reduce up to 40% your Cypress suite execution time parallelizing the test run on the same machine.
Stars: ✭ 78 (-51.85%)
Mutual labels:  sharding

libring - A fast consistent hash ring for Elixir

Hex.pm Version

This library implements a stateful consistent hash ring. It's extremely fast (in benchmarks it's faster than all other implementations I've tested against, namely voicelayer/hash-ring and sile/hash_ring), it has no external dependencies, and is written in Elixir.

The algorithm is based on libketama. Nodes on the ring are broken into shards and each one is assigned an integer value in the keyspace, which is the set of integers from 1 to 2^32-1. The distribution of these shards is random, but deterministic.

Keys are then mapped to a shard by converting the key to a binary, hashing it with SHA-256, converting the hash to an integer in the keyspace, then finding the shard which is assigned the next highest value, if there is no next highest value, the lowest integer is used, which is how the "ring" is formed.

This implementation uses a general balanced tree, via Erlang's :gb_tree module. Each shard is inserted into the tree, and we use this data structure to efficiently lookup next-highest key and smallest key. I suspect this is why libring is faster than other implementations I've benchmarked against.

Usage

Add :libring to your deps, and run mix deps.get.

def deps do
  [{:libring, "~> 1.0"}]
end

You have two choices for managing hash rings in your application:

HashRing

This API works with the raw ring datastructure. It is the fastest implementation, and is best suited for when you have a single process which will need to access the ring, and which can hold the ring in it's internal state.

ring = HashRing.new()
       |> HashRing.add_node("a")
       |> HashRing.add_node("b")

"a" = HashRing.key_to_node(ring, {:myworker, 123})

You can also specify the weight of each node, and add nodes in bulk:

ring = HashRing.new()
       |> HashRing.add_nodes(["a", {"b", 64}])
       |> HashRing.add_node("c", 200)
"c" = HashRing.key_to_node(ring, {:myworker, 123})

NOTE: Node names do not have to be strings, they can be atoms, tuples, etc.

HashRing.Managed

This API works with rings which are held in the internal state of a GenServer process. It supports the same API as HashRing. Because of this, there is a performance overhead due to the messaging, and the GenServer can be a potential bottleneck. If this is the case you are better off exploring ways to use the raw HashRing API. However this API is best suited for situations where you have multiple processes accessing the ring, or need to maintain multiple rings.

NOTE: You must have the :libring application started to use this API.

{:ok, pid} = HashRing.Managed.new(:myring)
:ok = HashRing.Managed.add_node(:myring, "a")
:ok = HashRing.Managed.add_node(:myring, "b", 64)
:ok = HashRing.Managed.add_node(:myring, "c", 200)
"c" = HashRing.Managed.key_to_node(:myring, {:myworker, 123})

You can configure managed rings in config.exs, and they will be created and initialized when the :libring application starts. Configured rings take two shapes, static and dynamic rings. Static rings are simply those where the nodes are provided up front, although you can always add/remove nodes manually at runtime; dynamic rings have Erlang node monitoring enabled, and add or remove nodes on the ring based on cluster membership.

You can whitelist/blacklist nodes when using dynamic rings, so that only those nodes which you actually want to distribute work to are used in calculations. This configuration is shown below as well.

If you provide a whitelist, the blacklist will have no effect, and only nodes matching the whitelist will be added. If you do not provide a whitelist, the blacklist will be used to filter nodes. If you do not provide either, a default blacklist containing the ~r/^remsh.*$/ pattern from the example below, which is a good default to prevent remote shell sessions (at least those done via releases) from causing the ring to change.

The whitelist and blacklist only have an effect when monitor_nodes: true.

Configuration

Below is an example configuration:

config :libring,
  rings: [
    # A ring which automatically changes based on Erlang cluster membership,
    # but does not allow nodes named "a" or "remsh*" to be added to the ring
    ring_a: [monitor_nodes: true,
             node_blacklist: ["a", ~r/^remsh.*$/]],
    # A ring which is composed of three nodes, of which "c" has a non-default weight of 200
    # The default weight is 128
    ring_b: [nodes: ["a", "b", {"c", 200}]]
  ]

Contributing

To run the test suite you will need to run mix eqc.install --mini once you've cloned the repo and fetched dependencies.

If you have changes in mind that are significant or potentially time consuming, please open a RFC-style PR first, where we can discuss your plans first. I don't want you to spend all your time crafting a PR that I ultimately reject because I don't think it's a good fit or is too large for me to review. Not that I plan to reject PRs in general, but I have to be careful to balance features with maintenance burden, or I will quickly be unable to manage the project.

Please ensure that you adhere to a commit style where logically related changes are in a single commit, or broken up in a way that eases review if necessary. Keep commit subject lines informative, but short, and provide additional detail in the extended message text if needed. If you can, mention relevant issue numbers in either the subject or the extended message.

License

MIT

Please see the LICENSE file for more info.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].