Skip to content

Commit 8d65fb3

Browse files
committed
Release v1.1.0.
1 parent 8140add commit 8d65fb3

File tree

3 files changed

+18
-19
lines changed

3 files changed

+18
-19
lines changed

README.md

+15-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<img src="./.github/logo_200x200.png" alt="sno logo" title="sno" align="left" height="200" />
22

3-
A spec for **unique IDs in distributed systems** based on the Snowflake design, e.g. a coordination-based ID variant.
3+
A spec for **unique IDs in distributed systems** based on the Snowflake design, i.e. a coordination-based ID variant.
44
It aims to be friendly to both machines and humans, compact, *versatile* and fast.
55

66
This repository contains a **Go** package for generating such IDs.
@@ -29,10 +29,10 @@ go get -u github.com/muyo/sno
2929
(256 combinations) per tick-tock (1 bit adjustment for clock drifts ➜ [Time and sequence](#time-and-sequence)).
3030
**549,755,813,888,000** is the global pool **per second** when the metabyte, partition and tick-tock are
3131
taken into account.
32-
- Data layout straightforward to inspect or encode/decode (➜ [Layout](#layout))
32+
- **Simple data layout** - straightforward to inspect or encode/decode (➜ [Layout](#layout))
3333
- Configuration and coordination optional (➜ [Usage](#usage))
34-
- Fast, wait-free, safe for concurrent use (➜ [Benchmarks](#benchmarks))
35-
- Fills a niche (➜ [Alternatives](#alternatives))
34+
- **Fast**, wait-free, safe for concurrent use (➜ [Benchmarks](#benchmarks))
35+
<br />Clocks in at just over 500 LoC, has no external dependencies and minimal dependencies on std.
3636

3737
### Non-features / cons
3838

@@ -46,7 +46,7 @@ unpredictability of IDs is a must. They still, however, meet the common requirem
4646

4747
<br />
4848

49-
## Usage
49+
## Usage (➜ [API reference](https://pkg.go.dev/github.com/muyo/sno?tab=doc))
5050

5151
**sno** comes with a package-level generator on top of letting you configure your own generators.
5252

@@ -57,15 +57,14 @@ id := sno.New(0)
5757
```
5858

5959
Where `0` is the ➜ [Metabyte](#metabyte).<br />
60-
Vide [godoc](https://pkg.go.dev/github.com/muyo/sno?tab=doc) for the entire API.
6160

6261
The global generator is immutable and private. It's therefore also not possible to restore it using a Snapshot.
63-
It uses 2 random bytes as its partition, meaning its partition changes across restarts.
62+
It uses 2 pseudo random bytes as its partition, meaning its partition changes across restarts.
6463

6564
*As soon as you run more than 1 generator, you **should** start coordinating* the creation of generators to
6665
actually *guarantee* a collision-free ride. This applies to all ID specs of the Snowflake variant.
6766

68-
### Partitions
67+
### Partitions (➜ [doc](https://pkg.go.dev/github.com/muyo/sno?tab=doc#Partition))
6968

7069
Partitions are one of several friends you have to get you those guarantees. A partition is 2 bytes.
7170
What they mean and how you define them is up to you.
@@ -79,7 +78,7 @@ generator, err := sno.NewGenerator(&sno.GeneratorSnapshot{
7978
Multiple generators can share a partition by dividing the sequence pool between
8079
them (➜ [Sequence sharding](#sequence-sharding)).
8180

82-
### Snapshots
81+
### Snapshots (➜ [doc](https://pkg.go.dev/github.com/muyo/sno?tab=doc#GeneratorSnapshot))
8382

8483
Snapshots happen to serve both as configuration and a means of saving and restoring generator data. They are
8584
optional - simply pass `nil` to `NewGenerator()`, and what you get will be configured like the package-level generator,
@@ -91,7 +90,7 @@ Snapshots can be taken at runtime:
9190
s := generator.Snapshot()
9291
```
9392

94-
This exposes most of a generator's internal bookkeeping data. In an ideal world where programmers are not lazy even
93+
This exposes most of a generator's internal bookkeeping data. In an ideal world where programmers are not lazy
9594
until their system runs into an edge case - you'd persist that snapshot across restarts and restore generators
9695
instead of just creating them from scratch each time. This will keep you safe both if a large clock drift happens
9796
during the restart -- or before, and you just happen to come back online again "in the past", relative to IDs that
@@ -202,7 +201,7 @@ generators.
202201

203202
It is safe for a range previously used by another generator to be assigned to a different generator under the
204203
following conditions:
205-
- it happens in a different timeframe *in the future*, e.g. no sooner than after 4msec have passed (no orchestrator
204+
- it happens in a different timeframe *in the future*, i.e. no sooner than after 4msec have passed (no orchestrator
206205
is fast enough to get a new container online to replace a dead one for this to be a worry);
207206
- if you can guarantee the new Generator won't regress into a time the previous Generator was running in.
208207

@@ -322,7 +321,7 @@ without requiring slew mode nor having to worry about even large drifts.
322321
**sno** attempts to eliminate the issue *entirely* - both despite and because of its small pool of bits to work with.
323322

324323
The approach it takes is simple - each generator keeps track of the highest wall clock time it got from the OS\*,
325-
each time it generates a new timestamp. If we get a time that is lower than the one we recorded, e.g. the clock
324+
each time it generates a new timestamp. If we get a time that is lower than the one we recorded, i.e. the clock
326325
drifted backwards and we'd risk generating colliding IDs, we toggle a bit - stored from here on out in
327326
each **sno** generated *until the next regression*. Rinse, repeat - tick, tock.
328327

@@ -344,7 +343,7 @@ So this is a **sno-go**.
344343
(I will show myself out...)
345344

346345
The simplistic approach of tick-tocking *entirely eliminates* that collision chance - but with a rigorous assumption:
347-
regressions happen at most once into a specific period, e.g. from the highest recorded time into the past
346+
regressions happen at most once into a specific period, i.e. from the highest recorded time into the past
348347
and never back into that particular timeframe (let alone even further into the past).
349348

350349
This *generally* is exactly the case but oddities as far as time synchronization, bad clocks and NTP client
@@ -412,7 +411,7 @@ And simple constants tend to do the trick.
412411
</summary>
413412
<p>
414413

415-
Untyped integers can pass as `uint8` (e.g. `byte`) in Go, so the following would work and keep things tidy:
414+
Untyped integers can pass as `uint8` (i.e. `byte`) in Go, so the following would work and keep things tidy:
416415

417416
```go
418417
const (
@@ -605,15 +604,15 @@ unexpected in the parallel test (branch prediction?) but remained consistent.
605604

606605
**Snowflakes**
607606

608-
What does `Unbounded` mean? [xid], for example, is unbounded, e.g. it does not prevent you from generating more IDs
607+
What does `Unbounded` mean? [xid], for example, is unbounded, i.e. it does not prevent you from generating more IDs
609608
than it has a pool for (nor does it account for time). In other words - at high enough throughput you simply and
610609
silently start overwriting already generated IDs. *Realistically* you are not going to fill its pool of
611610
a 16,777,216 capacity. But it does reflect in synthetic benchmarks. [Sandflake] does not bind nor handle clock
612611
drifts either. In both cases their results are `WYSIWYG`.
613612

614613
The implementations that do bind, approach this issue (and clock drifts) differently. [Sonyflake] goes to sleep,
615614
[Snowflake] spins aggressively to get the OS time. **sno**, when about to overflow, starts a single timer and
616-
locks all overflowing requests on a condition, waking them up when the sequence resets, e.g. time changes.
615+
locks all overflowing requests on a condition, waking them up when the sequence resets, i.e. time changes.
617616

618617
Both of the above are edge cases, *realistically* - Go's benchmarks happen to saturate the capacities and hit
619618
those cases. **Most of the time what you get is the unbounded overhead**. Expect said overhead of the

cmd/sno/go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module github.com/muyo/sno/cmd/sno
22

33
go 1.14
44

5-
require github.com/muyo/sno v1.0.0
5+
require github.com/muyo/sno v1.1.0
66
require github.com/muyo/rush v0.0.0-20200227160314-2d77be2a525b
77

8-
replace github.com/muyo/sno => ../../
8+
replace github.com/muyo/sno => ../../

cmd/sno/version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
)
66

77
const (
8-
ver = "1.0.0"
8+
ver = "1.1.0"
99
)
1010

1111
func version() {

0 commit comments

Comments
 (0)