{"id":13430611,"url":"https://github.com/segmentio/ksuid","last_synced_at":"2025-05-16T14:03:18.997Z","repository":{"id":37677706,"uuid":"90921999","full_name":"segmentio/ksuid","owner":"segmentio","description":"K-Sortable Globally Unique IDs","archived":false,"fork":false,"pushed_at":"2023-10-04T17:07:15.000Z","size":102,"stargazers_count":5072,"open_issues_count":22,"forks_count":187,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-05-09T14:03:31.456Z","etag":null,"topics":["coordination","go","golang","ksuid","unique-id","uuid"],"latest_commit_sha":null,"homepage":"https://segment.com/blog/a-brief-history-of-the-uuid/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/segmentio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-05-11T01:03:01.000Z","updated_at":"2025-05-09T07:38:29.000Z","dependencies_parsed_at":"2022-07-10T02:00:42.046Z","dependency_job_id":"67bac3ad-11a0-4c38-a026-c6438d62a3e9","html_url":"https://github.com/segmentio/ksuid","commit_stats":{"total_commits":72,"total_committers":24,"mean_commits":3.0,"dds":0.5277777777777778,"last_synced_commit":"b65a0ff7071caf0c8770b63babb7ae4a3c31034d"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/segmentio%2Fksuid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/segmentio%2Fksuid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/segmentio%2Fksuid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/segmentio%2Fksuid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/segmentio","download_url":"https://codeload.github.com/segmentio/ksuid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254544142,"owners_count":22088807,"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":["coordination","go","golang","ksuid","unique-id","uuid"],"created_at":"2024-07-31T02:00:55.628Z","updated_at":"2025-05-16T14:03:18.964Z","avatar_url":"https://github.com/segmentio.png","language":"Go","readme":"# ksuid [![Go Report Card](https://goreportcard.com/badge/github.com/segmentio/ksuid)](https://goreportcard.com/report/github.com/segmentio/ksuid) [![GoDoc](https://godoc.org/github.com/segmentio/ksuid?status.svg)](https://godoc.org/github.com/segmentio/ksuid) [![Circle CI](https://circleci.com/gh/segmentio/ksuid.svg?style=shield)](https://circleci.com/gh/segmentio/ksuid.svg?style=shield)\n\nksuid is an efficient, comprehensive, battle-tested Go library for\ngenerating and parsing a specific kind of globally unique identifier\ncalled a *KSUID*. This library serves as its reference implementation.\n\n## Install\n```sh\ngo get -u github.com/segmentio/ksuid\n```\n\n## What is a KSUID?\n\nKSUID is for K-Sortable Unique IDentifier. It is a kind of globally\nunique identifier similar to a [RFC 4122 UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), built from the ground-up to be \"naturally\"\nsorted by generation timestamp without any special type-aware logic.\n\nIn short, running a set of KSUIDs through the UNIX `sort` command will result\nin a list ordered by generation time.\n\n## Why use KSUIDs?\n\nThere are numerous methods for generating unique identifiers, so why KSUID?\n\n1. Naturally ordered by generation time\n2. Collision-free, coordination-free, dependency-free\n3. Highly portable representations\n\nEven if only one of these properties are important to you, KSUID is a great\nchoice! :) Many projects chose to use KSUIDs *just* because the text\nrepresentation is copy-and-paste friendly.\n\nFor a follow up read on the topic: [A brief history of UUID](https://segment.com/blog/a-brief-history-of-the-uuid/)\n\n### 1. Naturally Ordered By Generation Time\n\nUnlike the more ubiquitous UUIDv4, a KSUID contains a timestamp component\nthat allows them to be loosely sorted by generation time. This is not a strong\nguarantee (an invariant) as it depends on wall clocks, but is still incredibly\nuseful in practice. Both the binary and text representations will sort by\ncreation time without any special sorting logic.\n\n### 2. Collision-free, Coordination-free, Dependency-free\n\nWhile RFC 4122 UUIDv1s *do* include a time component, there aren't enough\nbytes of randomness to provide strong protection against collisions\n(duplicates). With such a low amount of entropy, it is feasible for a\nmalicious party to guess generated IDs, creating a problem for systems whose\nsecurity is, implicitly or explicitly, sensitive to an adversary guessing\nidentifiers.\n\nTo fit into a 64-bit number space, [Snowflake IDs](https://blog.twitter.com/2010/announcing-snowflake)\nand its derivatives require coordination to avoid collisions, which\nsignificantly increases the deployment complexity and operational burden.\n\nA KSUID includes 128 bits of pseudorandom data (\"entropy\"). This number space\nis 64 times larger than the 122 bits used by the well-accepted RFC 4122 UUIDv4\nstandard. The additional timestamp component can be considered \"bonus entropy\"\nwhich further decreases the probability of collisions, to the point of physical\ninfeasibility in any practical implementation.\n\n### 3. Highly Portable Representations\n\nThe text *and* binary representations are lexicographically sortable, which\nallows them to be dropped into systems which do not natively support KSUIDs\nand retain their time-ordered property.\n\nThe text representation is an alphanumeric base62 encoding, so it \"fits\"\nanywhere alphanumeric strings are accepted. No delimiters are used, so\nstringified KSUIDs won't be inadvertently truncated or tokenized when\ninterpreted by software that is designed for human-readable text, a common\nproblem for the text representation of RFC 4122 UUIDs.\n\n## How do KSUIDs work?\n\nBinary KSUIDs are 20-bytes: a 32-bit unsigned integer UTC timestamp and\na 128-bit randomly generated payload. The timestamp uses big-endian\nencoding, to support lexicographic sorting. The timestamp epoch is adjusted\nto May 13th, 2014, providing over 100 years of life. The payload is\ngenerated by a cryptographically-strong pseudorandom number generator.\n\nThe text representation is always 27 characters, encoded in alphanumeric\nbase62 that will lexicographically sort by timestamp.\n\n## High Performance\n\nThis library is designed to be used in code paths that are performance\ncritical. Its code has been tuned to eliminate all non-essential\noverhead. The `KSUID` type is derived from a fixed-size array, which\neliminates the additional reference chasing and allocation involved in\na variable-width type.\n\nThe API provides an interface for use in code paths which are sensitive\nto allocation. For example, the `Append` method can be used to parse the\ntext representation and replace the contents of a `KSUID` value\nwithout additional heap allocation.\n\nAll public package level \"pure\" functions are concurrency-safe, protected\nby a global mutex. For hot loops that generate a large amount of KSUIDs\nfrom a single Goroutine, the `Sequence` type is provided to elide the\npotential contention.\n\nBy default, out of an abundance of caution, the cryptographically-secure\nPRNG is used to generate the random bits of a KSUID. This can be relaxed\nin extremely performance-critical code using the included `FastRander`\ntype. `FastRander` uses the standard PRNG with a seed generated by the\ncryptographically-secure PRNG.\n\n*_NOTE:_ While there is no evidence that `FastRander` will increase the\nprobability of a collision, it shouldn't be used in scenarios where\nuniqueness is important to security, as there is an increased chance\nthe generated IDs can be predicted by an adversary.*\n\n## Battle Tested\n\nThis code has been used in production at Segment for several years,\nacross a diverse array of projects. Trillions upon trillions of\nKSUIDs have been generated in some of Segment's most\nperformance-critical, large-scale distributed systems.\n\n## Plays Well With Others\n\nDesigned to be integrated with other libraries, the `KSUID` type\nimplements many standard library interfaces, including:\n\n* `Stringer`\n* `database/sql.Scanner` and `database/sql/driver.Valuer`\n* `encoding.BinaryMarshal` and `encoding.BinaryUnmarshal`\n* `encoding.TextMarshal` and `encoding.TextUnmarshal`\n  (`encoding/json` friendly!)\n\n## Command Line Tool\n\nThis package comes with a command-line tool `ksuid`, useful for\ngenerating KSUIDs as well as inspecting the internal components of\nexisting KSUIDs. Machine-friendly output is provided for scripting\nuse cases.\n\nGiven a Go build environment, it can be installed with the command:\n\n```sh\n$ go install github.com/segmentio/ksuid/cmd/ksuid\n```\n\n## CLI Usage Examples\n\n### Generate a KSUID\n\n```sh\n$ ksuid\n0ujsswThIGTUYm2K8FjOOfXtY1K\n```\n\n### Generate 4 KSUIDs\n\n```sh\n$ ksuid -n 4\n0ujsszwN8NRY24YaXiTIE2VWDTS\n0ujsswThIGTUYm2K8FjOOfXtY1K\n0ujssxh0cECutqzMgbtXSGnjorm\n0ujsszgFvbiEr7CDgE3z8MAUPFt\n```\n\n### Inspect the components of a KSUID\n\n```sh\n$ ksuid -f inspect 0ujtsYcgvSTl8PAuAdqWYSMnLOv\n\nREPRESENTATION:\n\n  String: 0ujtsYcgvSTl8PAuAdqWYSMnLOv\n     Raw: 0669F7EFB5A1CD34B5F99D1154FB6853345C9735\n\nCOMPONENTS:\n\n       Time: 2017-10-09 21:00:47 -0700 PDT\n  Timestamp: 107608047\n    Payload: B5A1CD34B5F99D1154FB6853345C9735\n```\n\n### Generate a KSUID and inspect its components\n\n```sh\n$ ksuid -f inspect\n\nREPRESENTATION:\n\n  String: 0ujzPyRiIAffKhBux4PvQdDqMHY\n     Raw: 066A029C73FC1AA3B2446246D6E89FCD909E8FE8\n\nCOMPONENTS:\n\n       Time: 2017-10-09 21:46:20 -0700 PDT\n  Timestamp: 107610780\n    Payload: 73FC1AA3B2446246D6E89FCD909E8FE8\n\n```\n\n### Inspect a KSUID with template formatted inspection output\n\n```sh\n$ ksuid -f template -t '{{ .Time }}: {{ .Payload }}' 0ujtsYcgvSTl8PAuAdqWYSMnLOv\n2017-10-09 21:00:47 -0700 PDT: B5A1CD34B5F99D1154FB6853345C9735\n```\n\n### Inspect multiple KSUIDs with template formatted output\n\n```sh\n$ ksuid -f template -t '{{ .Time }}: {{ .Payload }}' $(ksuid -n 4)\n2017-10-09 21:05:37 -0700 PDT: 304102BC687E087CC3A811F21D113CCF\n2017-10-09 21:05:37 -0700 PDT: EAF0B240A9BFA55E079D887120D962F0\n2017-10-09 21:05:37 -0700 PDT: DF0761769909ABB0C7BB9D66F79FC041\n2017-10-09 21:05:37 -0700 PDT: 1A8F0E3D0BDEB84A5FAD702876F46543\n```\n\n### Generate KSUIDs and output JSON using template formatting\n\n```sh\n$ ksuid -f template -t '{ \"timestamp\": \"{{ .Timestamp }}\", \"payload\": \"{{ .Payload }}\", \"ksuid\": \"{{.String}}\"}' -n 4\n{ \"timestamp\": \"107611700\", \"payload\": \"9850EEEC191BF4FF26F99315CE43B0C8\", \"ksuid\": \"0uk1Hbc9dQ9pxyTqJ93IUrfhdGq\"}\n{ \"timestamp\": \"107611700\", \"payload\": \"CC55072555316F45B8CA2D2979D3ED0A\", \"ksuid\": \"0uk1HdCJ6hUZKDgcxhpJwUl5ZEI\"}\n{ \"timestamp\": \"107611700\", \"payload\": \"BA1C205D6177F0992D15EE606AE32238\", \"ksuid\": \"0uk1HcdvF0p8C20KtTfdRSB9XIm\"}\n{ \"timestamp\": \"107611700\", \"payload\": \"67517BA309EA62AE7991B27BB6F2FCAC\", \"ksuid\": \"0uk1Ha7hGJ1Q9Xbnkt0yZgNwg3g\"}\n```\n\n## OrNil functions\n\nThere are times when you are sure your ksuid is correct. But you need to get it from bytes or string and pass it\nit's to the structure. For this, there are OrNil functions that return ksuid.Nil on error and can be called \ndirectly in the structure.\n\n**Functions:**\n- `ParseOrNil()`\n- `FromPartsOrNil()`\n- `FromBytesOrNil()`\n\nAn example of using the function without OrNil:\n```go\nfunc getPosts(before, after []byte) {\n\tb, err := ksuid.FromBytes(before)\n\tif err != nil {\n\t\t// handle error\n\t}\n\n\ta, err := ksuid.FromBytes(after)\n\tif err != nil {\n\t\t// handle error\n\t}\n\n\tsortOptions := SortOptions{Before: b, After: a}\n}\n```\n\nIt is much more convenient to do it like this:\n\n```go\nfunc getPosts(before, after []byte) {\n\tsortOptions := SortOptions{\n\t\tBefore: ksuid.FromBytesOrNil(before),\n\t\tAfter:  ksuid.FromBytesOrNil(after),\n\t}\n}\n```\n\nOrNil functions are also used in many other libraries:\n\n- [satori/go.uuid](https://github.com/satori/go.uuid)\n- [oklog/ulid](https://github.com/oklog/ulid) (panic)\n\n## Implementations for other languages\n\n- Python: [svix-ksuid](https://github.com/svixhq/python-ksuid/)\n- Python: [cyksuid](https://github.com/timonwong/cyksuid)\n- Ruby: [ksuid-ruby](https://github.com/michaelherold/ksuid-ruby)\n- Java: [ksuid](https://github.com/ksuid/ksuid)\n- Java: [ksuid-creator](https://github.com/f4b6a3/ksuid-creator)\n- Rust: [svix-ksuid](https://github.com/svix/rust-ksuid)\n- dotNet: [Ksuid.Net](https://github.com/JoyMoe/Ksuid.Net)\n- dotnet: [KsuidDotNet](https://github.com/steve-warren/ksuid)\n- Erlang: [erl-ksuid](https://github.com/exograd/erl-ksuid)\n- Zig: [zig-ksuid](https://github.com/toffaletti/zig-ksuid)\n\n## License\n\nksuid source code is available under an MIT [License](/LICENSE.md).\n","funding_links":[],"categories":["Go","开源类库","UUID Like","Open source library","golang","Generation"],"sub_categories":["UUID","Packages","Go"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsegmentio%2Fksuid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsegmentio%2Fksuid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsegmentio%2Fksuid/lists"}