{"id":16188990,"url":"https://github.com/fogfish/ring","last_synced_at":"2026-01-28T08:38:44.662Z","repository":{"id":56854777,"uuid":"524673753","full_name":"fogfish/ring","owner":"fogfish","description":"consistent hashing data structure","archived":false,"fork":false,"pushed_at":"2022-08-14T13:29:11.000Z","size":259,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-18T16:25:07.777Z","etag":null,"topics":["consistent-hash-algorithm","consistent-hashing","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fogfish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-14T13:04:28.000Z","updated_at":"2024-02-09T12:55:13.000Z","dependencies_parsed_at":"2022-09-22T14:25:38.983Z","dependency_job_id":null,"html_url":"https://github.com/fogfish/ring","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fogfish/ring","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fogfish","download_url":"https://codeload.github.com/fogfish/ring/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fring/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28842868,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T07:39:25.367Z","status":"ssl_error","status_checked_at":"2026-01-28T07:39:24.487Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consistent-hash-algorithm","consistent-hashing","golang"],"created_at":"2024-10-10T07:33:15.275Z","updated_at":"2026-01-28T08:38:44.647Z","avatar_url":"https://github.com/fogfish.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./doc/ring-v1.svg\" height=\"240\" /\u003e\n  \u003ch3 align=\"center\"\u003ering\u003c/h3\u003e\n  \u003cp align=\"center\"\u003e\u003cstrong\u003econsistent hashing data structure\u003c/strong\u003e\u003c/p\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003c!-- Version --\u003e\n    \u003ca href=\"https://github.com/fogfish/ring/releases\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/v/tag/fogfish/ring?label=version\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Documentation --\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/fogfish/ring\"\u003e\n      \u003cimg src=\"https://pkg.go.dev/badge/github.com/fogfish/ring\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Build Status  --\u003e\n    \u003ca href=\"https://github.com/fogfish/ring/actions/\"\u003e\n      \u003cimg src=\"https://github.com/fogfish/ring/workflows/test/badge.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- GitHub --\u003e\n    \u003ca href=\"http://github.com/fogfish/ring\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/last-commit/fogfish/ring.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Coverage --\u003e\n    \u003ca href=\"https://coveralls.io/github/fogfish/ring?branch=main\"\u003e\n      \u003cimg src=\"https://coveralls.io/repos/github/fogfish/ring/badge.svg?branch=main\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Go Card --\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/fogfish/ring\"\u003e\n      \u003cimg src=\"https://goreportcard.com/badge/github.com/fogfish/ring\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n---\n\n\u003e\n\u003e One Ring to rule them all, One Ring to find them,\n\u003e\n\u003e One Ring to bring them all and in the darkness bind them...\n\u003e\n\nThe type `ring` implements consistent hashing data structure to orchestrate the topology without the global coordinator in the distributed environment. The library is developed after [Erlang's consistent hashing data structure](https://github.com/fogfish/datum/blob/master/src/sets/ring.erl), which has been battle tested by author in various contexts. \n\n## Inspiration\n\nThe concept of [consistent hashing](https://en.wikipedia.org/wiki/Consistent_hashing) has been developed in the past to deal with load-balancing in a dynamic environment. It solves the resizing problem of traditional mod-n hashing technique so that only the k/N fraction of keys needs to be reallocated when topology is modified, while the traditional hashing causes entire remapping of key space. The practical adoption of consistent hashing into distributed systems has shown a need for stricter balancing of keys, therefore hashing schema has been enhanced with the concept of virtual nodes. In this schema, each node claims randomly multiple tokens. The tokens of all nodes are placed on the ring according to their values. Every two consecutive tokens frame the arc, which is claimed by the corresponding node. Virtual node partitioning schema works well for load balancing of CPU bound workload but suffers for storage bounded workload due to the randomness in key ranges as it has been [demonstrated by Amazon Dynamo](https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf). Virtual nodes do not guarantee determinism on key range reallocation when topology is modified nor predictability of anti-entropy processes. \n\nThe ultimate consistent hashing uses unrelated algorithms for **partition**, **allocation** and **routing**. The hash address space `2ᵐ-1` is divided into Q equally sized shards. Each node claims about Q/N shards with the help of T pseudo-randomly assigned tokens. The tokens are mapped into the hash address space to claim governance of shards to the node. When a node leaves the system, its shards are consistently distributed to the remaining nodes. Similarly, when a node joins the system it \"steals\" shards from nodes in the system in consistent ways. The request routing procedure maps the key into the hash space to determine the shard and corresponding node.\n\nSee [details about the data structure and algorithm](./doc/consistent-hashing-the-rings-of-power-2.pdf).\n\n## Installing \n\nThe latest version of the library is available at `main` branch. All development, including new features and bug fixes, take place on the `main` branch using forking and pull requests as described in contribution guidelines. The stable version is available via Golang modules.\n\n1. Use `go get` to retrieve the library and add it as dependency to your application.\n\n```bash\ngo get -u github.com/fogfish/ring\n```\n\n2. Import it in your code\n\n```go\nimport (\n  \"github.com/fogfish/ring\"\n)\n```\n\n## Quick Example\n\nHere is a minimal example on creating an instance of the ring, assembling topology from individual nodes and then routing the requests. See the full [example](examples/ringo.go) \n\n```go\npackage main\n\nimport (\n  \"github.com/fogfish/ring\"\n)\n\nfunc main() {\n  /*\n    create new ring instance with m=64, Q=8, T=8\n  */\n  ringo := ring.New(ring.WithM64(), ring.WithQ(8), ring.WithT(8))\n\n  /*\n    when all nodes join the topology is following\n\n    ring: m=64, q=8, t=8\n    |     [0, ffffffffffffffff]\n    |     [ 18.54.73.101 113.181.90.103 102.190.90.78 140.93.207.103 92.106.122.149 ]\n    |\n    |     0: 1fffffffffffffff ⇒     1  ab26472ec2ed62a [18.54.73.101]\n    |     1: 3fffffffffffffff ⇒     0 228ad527296bd2d5 [113.181.90.103]\n    |     2: 5fffffffffffffff ⇒     2 5949b7cc2ac07642 [140.93.207.103]\n    |     3: 7fffffffffffffff ⇒     3 6c13f457b56728ec [18.54.73.101]\n    |     4: 9fffffffffffffff ⇒     0 931fb3cd1fc272eb [18.54.73.101]\n    |     5: bfffffffffffffff ⇒     0 a22176d726c38cb5 [102.190.90.78]\n    |     6: dfffffffffffffff ⇒     1 d613972f28795b25 [140.93.207.103]\n    |     7: ffffffffffffffff ⇒     0 f27d0004a29a8dff [140.93.207.103]\n  */\n  ringo.Join(\"113.181.90.103\")\n  /* ... */\n  ringo.Join(\"18.54.73.101\")\n\n  /*\n    Lookup successor nodes for the key.\n    It returns list of primary \u0026 handoff nodes\n\n    Primary:\n    1. {ffffffffffffffff | 0 - 140.93.207.103}\n    2. {ffffffffffffffff | 1 - 18.54.73.101}\n    3. {ffffffffffffffff | 0 - 113.181.90.103}\n\n    Handoff:\n    - empty\n  */\n  primary, handoff := ringo.SuccessorOf(3, \"One ring to rule them all\")\n\n  // Handoff node and its shards to other\n  ringo.Handoff(\"18.54.73.101\")\n\n  // Permanently leaves the topology\n  ringo.Leave(\"18.54.73.101\")\n}\n```\n\n## How To Contribute\n\nThe library is [Apache 2.0](LICENSE) licensed and accepts contributions via GitHub pull requests:\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n\nThe build and testing process requires [Go](https://golang.org) latest version.\n\n**Build** and **run** in your development console.\n\n```bash\ngit clone https://github.com/fogfish/ring\ncd ring\ngo test\ngo test -run=^$ -bench=. -cpu 1\n```\n\n### commit message\n\nThe commit message helps us to write a good release note, speed-up review process. The message should address two question what changed and why. The project follows the template defined by chapter [Contributing to a Project](http://git-scm.com/book/ch5-2.html) of Git book.\n\n### bugs\n\nIf you experience any issues with the library, please let us know via [GitHub issues](https://github.com/fogfish/ring/issue). We appreciate detailed and accurate reports that help us to identity and replicate the issue. \n\n## License\n\n[![See LICENSE](https://img.shields.io/github/license/fogfish/ring.svg?style=for-the-badge)](LICENSE)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffogfish%2Fring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fring/lists"}