{"id":16188993,"url":"https://github.com/fogfish/guid","last_synced_at":"2025-10-26T16:10:41.095Z","repository":{"id":46290898,"uuid":"247264674","full_name":"fogfish/guid","owner":"fogfish","description":"K-ordered unique identifiers in lock-free and decentralised manner for Golang applications","archived":false,"fork":false,"pushed_at":"2023-05-07T20:33:17.000Z","size":70,"stargazers_count":10,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-18T16:25:49.110Z","etag":null,"topics":["k-ordered","partial-sort","uid","uid-generator","unique-id"],"latest_commit_sha":null,"homepage":null,"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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-14T11:35:30.000Z","updated_at":"2022-10-08T20:55:53.000Z","dependencies_parsed_at":"2024-06-20T23:26:53.441Z","dependency_job_id":"82fe75ca-1818-4e55-8648-9ad3639db7c5","html_url":"https://github.com/fogfish/guid","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fguid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fguid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fguid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fguid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fogfish","download_url":"https://codeload.github.com/fogfish/guid/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243965774,"owners_count":20375917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["k-ordered","partial-sort","uid","uid-generator","unique-id"],"created_at":"2024-10-10T07:33:16.814Z","updated_at":"2025-10-26T16:10:36.059Z","avatar_url":"https://github.com/fogfish.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ch3 align=\"center\"\u003eGUID\u003c/h3\u003e\n  \u003cp align=\"center\"\u003e\u003cstrong\u003eK-ordered unique identifiers in lock-free and\ndecentralized manner for Golang applications\u003c/strong\u003e\u003c/p\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003c!-- Version --\u003e\n    \u003ca href=\"https://github.com/fogfish/guid/releases\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/v/tag/fogfish/guid?label=version\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Documentation --\u003e\n    \u003ca href=\"http://godoc.org/github.com/fogfish/guid\"\u003e\n      \u003cimg src=\"https://godoc.org/github.com/fogfish/guid?status.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Build Status  --\u003e\n    \u003ca href=\"https://github.com/fogfish/guid/actions/\"\u003e\n      \u003cimg src=\"https://github.com/fogfish/guid/workflows/test/badge.svg?branch=main\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- GitHub --\u003e\n    \u003ca href=\"http://github.com/fogfish/guid\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/last-commit/fogfish/guid.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Coverage --\u003e\n    \u003ca href=\"https://coveralls.io/github/fogfish/guid?branch=main\"\u003e\n      \u003cimg src=\"https://coveralls.io/repos/github/fogfish/guid/badge.svg?branch=main\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Go Card --\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/fogfish/guid\"\u003e\n      \u003cimg src=\"https://goreportcard.com/badge/github.com/fogfish/guid\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n---\n\nPackage guid implements interface to generate k-ordered unique identifiers in lock-free and decentralized manner for Golang applications. We says that sequence A is k-ordered if it consists of strictly ordered subsequences of length k:\n\n```\n  𝑨[𝒊 − 𝒌] ≤ 𝑨[𝒊] ≤ 𝑨[𝒊 + 𝒌] for all 𝒊 such that 𝒌 \u003c 𝒊 ≤ 𝒏−𝒌.\n```\n\n## Key features\n\nThis library aims important objectives:\n\n* IDs allocation does not require centralized authority or coordination with other nodes.\n* IDs are suitable for partial event ordering in distributed environment and helps on detection of causality violation.\n* IDs are roughly sortable by allocation order (\"time\").\n* IDs reduce indexes footprints and optimize lookup latency.\n\n\n## Inspiration\n\nThe event ordering in distributed computing is resolved using various techniques, e.g. Lamport timestamps, Universal Unique Identifiers, Twitter Snowflake and many other techniques are offered by open source libraries. `guid` is a Golang port of [Erlang's uid library](https://github.com/fogfish/uid).\n\nAll these solution made a common conclusion, globally unique ID is a triple ⟨𝒕, 𝒍, 𝒔⟩: ⟨𝒕⟩ monotonically increasing clock or timestamp is a primary dimension to roughly sort events, ⟨𝒍⟩ is spatially unique identifier of ID allocator so called node location, ⟨𝒔⟩ sequence is a monotonic integer, which prevents clock collisions. The `guid` library addresses few issues observed in other solutions.\n\nEvery byte counts when application is processing or storing large volume of events. This library implements fixed size 96-bit identity schema, which is castable to 64-bit under certain occasion. It is about 25% improvement to compare with UUID or similar 128-bit identity schemas (only Twitters Snowflake is 64-bit).\n\nMost of identity schemas uses monotonically increasing clock (timestamp) to roughly order events. The resolution of clock varies from nanoseconds to milliseconds. We found that usage of timestamp is not perfectly aligned with the goal of decentralized ID allocations. Usage of time synchronization protocol becomes necessary at distributed systems. Strictly speaking, NTP server becomes an authority to coordinate clock synchronization. This happens because schemas uses time fraction ⟨𝒕⟩ as a primary sorting key. In contrast with other libraries, `guid` do not give priority to single fraction of identity triple ⟨𝒕⟩ or ⟨𝒍⟩. It uses dynamic schema where the location fraction has higher priority than time only at particular precision. It allows to keep ordering consistent even if clocks on other node is skewed.\n\n## Identity Schema\n\nA fixed size of 96-bit is used to implement identity schema\n\n```\n  3bit  47 bit - 𝒅 bit         32 bit      𝒅 bit  14 bit\n   |-|-------------------|----------------|-----|-------|\n   ⟨𝒅⟩        ⟨𝒕⟩                ⟨𝒍⟩         ⟨𝒕⟩     ⟨𝒔⟩\n```\n\n↣ ⟨𝒕⟩ is 47-bit UTC timestamp with millisecond precision. It is derived from nanosecond UNIX timestamp by shifting it by 17 bits (time.Now().UnixNano() \u003c\u003c 17). The library is able to change the base timestamp to any value in-order to address Year 2038 problem.\n\n↣ ⟨𝒍⟩ is 32-bits node/allocator identifier. It is allocated randomly to each node using cryptographic random generator or application provided value. The node identity has higher sorting priority than seconds faction of timestamp. This allows to order events if clock drifts on nodes. The random allocation give an application ability to introduce about 65K allocators before it meets a high probability of collisions.\n\n↣ ⟨𝒅⟩ is 3 drift bits defines allowed clock drift. It shows the value of less important faction of time. The value supports step-wise drift from 30 seconds to 36 minutes.\n\n↣ ⟨𝒔⟩ is 14-bit of monotonic strictly locally ordered integer. It helps to avoid collisions when multiple events happens during single millisecond or when the clock set backwards. The 14-bit value allows to have about 16K allocations per millisecond and over 10M per second on single node. Each instance of application process runs a unique sequence of integers. The implementation ensures that the same integer is not returned more than once on the current\nprocess. Restart of the process resets the sequence.\n\nThe library supports casting of 96-bit identifier to 64-bit by dropping ⟨𝒍⟩ fraction. This optimization reduces a storage footprint if application uses persistent allocators.\n\n```\n  3bit        47 bit            14 bit\n   |-|------------------------|-------|\n   ⟨𝒅⟩           ⟨𝒕⟩              ⟨𝒔⟩\n```\n\n## Getting started\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\nUse `go get` to retrieve the library and add it as dependency to your application.\n\n```bash\ngo get github.com/fogfish/guid/v2\n```\n\nHere is minimal example (also available in [playground](https://go.dev/play/p/zaIM7BXGt8F)):\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"time\"\n\n  \"github.com/fogfish/guid/v2\"\n)\n\nfunc useDefaultClock() {\n  a := guid.G(guid.Clock)\n  time.Sleep(1 * time.Second)\n  b := guid.G(guid.Clock)\n  fmt.Printf(\"%s \u003c %s is %v\\n\", a, b, guid.Before(a, b))\n}\n\nfunc useCustomClock() {\n  clock := guid.NewClock(\n    guid.WithNodeID(0xffffffff),\n  )\n\n  c := guid.G(clock)\n  time.Sleep(1 * time.Second)\n  d := guid.G(clock)\n  fmt.Printf(\"%s \u003c %s is %v\\n\", c, d, guid.Before(c, d))\n}\n\nfunc main() {\n  useDefaultClock()\n  useCustomClock()\n}\n```\n\nThe library [api specification](http://godoc.org/github.com/fogfish/guid) is available via Go doc.\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) version 1.13 or later.\n\n**Build** and **run** in your development console.\n\n```bash\ngit clone https://github.com/fogfish/guid\ncd guid\ngo test\n```\n\n## License\n\n[![See LICENSE](https://img.shields.io/github/license/fogfish/guid.svg?style=for-the-badge)](LICENSE)\n\n\n## References\n\n1. [Lamport timestamps](https://en.wikipedia.org/wiki/Lamport_timestamps)\n2. [Universal Unique Identifiers](https://tools.ietf.org/html/rfc4122),\n3. [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake.html)\n4. [Flake](https://github.com/boundary/flake)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fguid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffogfish%2Fguid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fguid/lists"}