idgen

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2021 License: MIT Imports: 5 Imported by: 0

README

Distributed unique ID Generator

id-generator is a dirstributed unique ID generator. There are 3 kinds of generators provided by id-generator:

  1. snowflake-like ID generator

    • inspired by Twitter's Snowflake.

    • A snowflake-like ID is composed of

      31 bits for time in units of 1 second (limit: 2**31/3600/24/365 = 68 years)
      22 bits for a sequence number         (limit: 2**22-1 = 4,194,303 per second)
      10 bits for a worker id               (limit: 2**10 = 1024)
      
  2. auto-inremented sequence ID generator

    • id auto-incremented

    • sequence ID is composed of

      53 bits for a sequence number  (limit: 2**53-1 = 9,007,199,254,740,991)
      10 bits for a worker id        (limit: 2**10 = 1024)
      
  3. order ID generator

    • id is of type uint64

    • as a digit string, its head 6 chars are date with layout "YYMMDD"

    • its tail chars form the workerId specified when initing

    • the digit of the whole order id is composed of 3 parts

      • short order id
      parts format: YYMMDDxxxxxxxWW
         YYMMDD  stands for Year, Month, Day.   (upper limit: 991231)
         xxxxxxx stands for order Id sequence.  (upper limit: 10,000,000 per day)
         WW      stands for worker id.          (upper limit: 100)
      
      • long order id
      parts format: YYMMDDhhmmxxxxxxWW
         YYMMDDhhmm  stands for Year, Month, Day, Hour, Minute. (upper limit: 9912312359)
         xxxxxx      stands for order Id sequence.              (upper limit: 1,000,000 per minute)
         WW          stands for worker id.                      (upper limit: 100)
      

Installation

The package is fully go-getable without any dependency, So, just type

go get github.com/rosbit/id-generator

Usage

package main

import (
	"github.com/rosbit/id-generator"
	"time"
)

func main() {
	// 1. for snowflake-like ID
	epochTime := time.Now().AddDate(0, 0, -1) // set your epochTime, a history time
	workerId := uint16(1) // set your own workerId
	sf := idgen.NewFlakeIdGenerator(echochTime, workerId)   // 64bit id
	// sf := idgen.NewFlakeIdGenerator32(echochTime, workerId) // 32bit id, most of time, 32bit is ok.
	for i:=0; i<10; i++ {
		id := sf.NextID()
		// id
	}
	sf.Exit()

	// 2. for order id
	ord := idgen.NewOrderIdGenerator(workerId, "Asia/Shanghai") // any valid tz string is ok
	for i:=0; i<10; i++ {
		id := ord.NextID()
		// id
	}
	ord.Exit()

	ord2 := idgen.NewLongOrderIdGenerator(workerId, "Asia/Shanghai") // any valid tz string is ok
	for i:=0; i<10; i++ {
		id := ord2.NextID()
		// id
	}
	ord2.Exit()

	// 3. for sequence id
	seq := idgen.NewSeqIdGenerator(workerId, 0) // startId, any uint64 is ok
	for i:=0; i<10; i++ {
		id := seq.NextID()
		// id
	}
	seq.Exit()
}

Benchmarks

Under my aliyun-ECS: 1core CPU, Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz

The benchmark result is:

goos: linux
goarch: amd64
pkg: github.com/rosbit/id-generator
Benchmark_orderNextId     	 3000000	       479 ns/op
Benchmark_seqNextId       	 3000000	       469 ns/op
Benchmark_snowFlakeNextId 	 3000000	       472 ns/op
PASS
ok  	github.com/rosbit/id-generator	3.781s

Contribution

Pull requests are welcome! Also, if you want to discuss something, send a pull request with proposal and changes.

Documentation

Overview

generate order id with format:

short id format:   YYMMDDxxxxxxxWW
long id format: YYMMDDhhmmxxxxxxWW

Index

Constants

View Source
const (
	ORD_DATE_FORMAT = "060102"        // 6 chars
	ORD_MAX_SEQ     = uint32(9999999) // 7 digit chars

	L_ORD_DATE_FORMAT = "0601021504"   // 10 chars
	L_ORD_MAX_SEQ     = uint32(999999) // 6 digit chars

	ORD_MAX_WORKER_ID = uint16(99) // 2 digit chars
	ORD_TICKER_UNIT   = 1          // in second
)
View Source
const (
	SHORT_ORDID_IDX = iota
	LONG_ORDID_IDX
)
View Source
const (
	SEQ_BITS_WORKER_ID = 10
	SEQ_BITS_ID        = 63 - SEQ_BITS_WORKER_ID
)
View Source
const (
	SF_BITS_TIME      = 31 // (2**31/3600/24/365 = 68 years)
	SF_BITS_SEQUENCE  = 22
	SF_BITS_WORKER_ID = 63 - SF_BITS_TIME - SF_BITS_SEQUENCE
	SF_TICKER_UNIT    = 1 // 1s

	SF_BITS_TIME32      = 13                                       // (day-count: 2**13/365 = 22.4 years)
	SF_BITS_SEQUENCE32  = 17                                       // (day-limit: 2**17 = 131072)
	SF_BITS_WORKER_ID32 = 32 - SF_BITS_TIME32 - SF_BITS_SEQUENCE32 // 2 (worker-limit: 2**2 = 4)
	SF_TICKER_UNIT32    = 86400                                    // 1d
)
View Source
const (
	SF_64_IDX = iota
	SF_32_IDX
)

Variables

View Source
var (
	ORD_WORKID_CHARS = len(fmt.Sprintf("%d", ORD_MAX_WORKER_ID)) // 2
	ORD_SEQ_MULTIPLE = uint32(math.Pow10(ORD_WORKID_CHARS))      // 100
	ORD_BLANK_ITEM   = struct{}{}

	ORD_DATE_CHARS  = len(ORD_DATE_FORMAT)                                            // 6
	ORD_SEQ_CHARS   = len(fmt.Sprintf("%d", ORD_MAX_SEQ))                             // 7
	ORD_TOTAL_CHARS = ORD_DATE_CHARS + ORD_WORKID_CHARS + ORD_SEQ_CHARS               // 15
	ORD_ID_FORMAT   = fmt.Sprintf("%%s%%0%dd%%0%dd", ORD_SEQ_CHARS, ORD_WORKID_CHARS) // "%s%07d%02d"

	L_ORD_DATE_CHARS  = len(L_ORD_DATE_FORMAT)                                            // 10
	L_ORD_SEQ_CHARS   = len(fmt.Sprintf("%d", L_ORD_MAX_SEQ))                             // 6
	L_ORD_TOTAL_CHARS = L_ORD_DATE_CHARS + ORD_WORKID_CHARS + L_ORD_SEQ_CHARS             // 18
	L_ORD_ID_FORMAT   = fmt.Sprintf("%%s%%0%dd%%0%dd", L_ORD_SEQ_CHARS, ORD_WORKID_CHARS) // "%s%06d%02d"
)
View Source
var (
	SEQ_MAX_SEQ       = uint64(1<<SEQ_BITS_ID - 1)        // (2**53-1 = 9,007,199,254,740,991)
	SEQ_MAX_WORKER_ID = uint16(1<<SEQ_BITS_WORKER_ID - 1) // (2**10-1 = 1023)
	SEQ_BLANK_ITEM    = struct{}{}
)
View Source
var (
	SF_BLANK_ITEM = struct{}{}

	SF_MAX_SEQ              = uint64(1<<SF_BITS_SEQUENCE - 1)  // (2**22-1 = 4,194,303 per second)
	SF_MAX_WORKER_ID        = uint16(1<<SF_BITS_WORKER_ID - 1) // (2**10-1 = 1023)
	ELAPSED_TIME_SHIFT_BITS = uint64(SF_BITS_SEQUENCE + SF_BITS_WORKER_ID)

	SF_MAX_SEQ32              = uint64(1<<SF_BITS_SEQUENCE32 - 1)  // (2**17-1 = 131071 per day)
	SF_MAX_WORKER_ID32        = uint16(1<<SF_BITS_WORKER_ID32 - 1) // (2**2-1  = 3)
	ELAPSED_TIME_SHIFT_BITS32 = uint64(SF_BITS_SEQUENCE32 + SF_BITS_WORKER_ID32)
)

Functions

func DecomposeLongOrd added in v0.0.5

func DecomposeLongOrd(id uint64) (datetime uint32, workerId uint16, sequence uint32)

func DecomposeOrd added in v0.0.2

func DecomposeOrd(id uint64) (datetime uint32, workerId uint16, sequence uint32)

func DecomposeSF

func DecomposeSF(id uint64) (elaspedTime uint32, workerId uint16, sequence uint32)

func DecomposeSF32 added in v0.0.3

func DecomposeSF32(id uint32) (elaspedTime uint32, workerId uint16, sequence uint32)

func DecomposeSeq

func DecomposeSeq(id uint64) (workerId uint16, sequence uint64)

Types

type FlakeIdGenerator

type FlakeIdGenerator struct {
	// contains filtered or unexported fields
}

func NewFlakeIdGenerator

func NewFlakeIdGenerator(epochTime time.Time, workerId uint16) *FlakeIdGenerator

func NewFlakeIdGenerator32 added in v0.0.3

func NewFlakeIdGenerator32(epochTime time.Time, workerId uint16) *FlakeIdGenerator

func (*FlakeIdGenerator) Exit

func (ig *FlakeIdGenerator) Exit()

func (*FlakeIdGenerator) NextID

func (ig *FlakeIdGenerator) NextID() uint64

func (*FlakeIdGenerator) NextID32 added in v0.0.3

func (ig *FlakeIdGenerator) NextID32() uint32

type OrderIdGenerator added in v0.0.2

type OrderIdGenerator struct {
	// contains filtered or unexported fields
}

func NewLongOrderIdGenerator added in v0.0.5

func NewLongOrderIdGenerator(workerId uint16, tz string) *OrderIdGenerator

func NewOrderIdGenerator added in v0.0.2

func NewOrderIdGenerator(workerId uint16, tz string) *OrderIdGenerator

func (*OrderIdGenerator) Exit added in v0.0.2

func (og *OrderIdGenerator) Exit()

func (*OrderIdGenerator) NextID added in v0.0.2

func (og *OrderIdGenerator) NextID() uint64

type SeqIdGenerator

type SeqIdGenerator struct {
	// contains filtered or unexported fields
}

func NewSeqIdGenerator

func NewSeqIdGenerator(workerId uint16, startId uint64) *SeqIdGenerator

func (*SeqIdGenerator) Exit

func (ig *SeqIdGenerator) Exit()

func (*SeqIdGenerator) NextID

func (ig *SeqIdGenerator) NextID() uint64

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL