github.com/zooyer/miskit@v1.0.71/zuid/zuid.go (about)

     1  package zuid
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math/rand"
     7  	"strconv"
     8  	"sync"
     9  	"time"
    10  )
    11  
    12  type Bits struct {
    13  	Rand int64 // 随机位数
    14  	Time int64 // 时间位数
    15  	Node int64 // 节点位数
    16  	Step int64 // 序列位数
    17  }
    18  
    19  type Sort struct {
    20  	Rand int64 // 随机位权重
    21  	Time int64 // 时间位权重
    22  	Node int64 // 节点位权重
    23  	Step int64 // 序列位权重
    24  }
    25  
    26  type Node struct {
    27  	mutex sync.Mutex
    28  	rand  *rand.Rand
    29  
    30  	bits  Bits
    31  	sort  Sort
    32  	node  int64
    33  	step  int64
    34  	time  int64
    35  	ms    int64
    36  	epoch time.Time
    37  
    38  	randMax   int64
    39  	timeMax   int64
    40  	nodeMax   int64
    41  	stepMax   int64
    42  	randMask  int64
    43  	timeMask  int64
    44  	nodeMask  int64
    45  	stepMask  int64
    46  	randShift int64
    47  	timeShift int64
    48  	nodeShift int64
    49  	stepShift int64
    50  }
    51  
    52  type ID int64
    53  
    54  func NewBits(rand, time, node, step int64) Bits {
    55  	var bits = Bits{
    56  		Rand: rand,
    57  		Time: time,
    58  		Node: node,
    59  		Step: step,
    60  	}
    61  
    62  	if total := bits.Total(); total < 5 || total > 63 {
    63  		panic(fmt.Errorf("total bits must between 5 and 63"))
    64  	}
    65  
    66  	return bits
    67  }
    68  
    69  func NewSort(rand, time, node, step int64) Sort {
    70  	var sort = Sort{
    71  		Rand: rand,
    72  		Time: time,
    73  		Node: node,
    74  		Step: step,
    75  	}
    76  
    77  	if sort.Count() < 3 {
    78  		panic(fmt.Errorf("sort counts must greater than or equal to 3"))
    79  	}
    80  
    81  	return sort
    82  }
    83  
    84  func bitShift(bits Bits, sorts Sort, sort int64) (bit int64) {
    85  	if sorts.Rand < sort {
    86  		bit += bits.Rand
    87  	}
    88  	if sorts.Time < sort {
    89  		bit += bits.Time
    90  	}
    91  	if sorts.Node < sort {
    92  		bit += bits.Node
    93  	}
    94  	if sorts.Step < sort {
    95  		bit += bits.Step
    96  	}
    97  	return
    98  }
    99  
   100  func NewNode(epoch, ms, node int64, bits Bits, sort Sort) *Node {
   101  	// 校验失败则panic
   102  	bits = NewBits(bits.Rand, bits.Time, bits.Node, bits.Step)
   103  	sort = NewSort(sort.Rand, sort.Time, sort.Node, sort.Step)
   104  
   105  	var n Node
   106  	var now = time.Now()
   107  
   108  	n.rand = rand.New(rand.NewSource(now.UnixNano()))
   109  
   110  	n.bits = bits
   111  	n.sort = sort
   112  	n.node = node
   113  	n.epoch = now.Add(time.Unix(epoch/1000, epoch%1000*1000000).Sub(now))
   114  	n.ms = ms
   115  
   116  	n.randMax = -1 ^ (-1 << bits.Rand)
   117  	n.timeMax = -1 ^ (-1 << bits.Time)
   118  	n.nodeMax = -1 ^ (-1 << bits.Node)
   119  	n.stepMax = -1 ^ (-1 << bits.Step)
   120  
   121  	n.randShift = bitShift(bits, sort, sort.Rand)
   122  	n.timeShift = bitShift(bits, sort, sort.Time)
   123  	n.nodeShift = bitShift(bits, sort, sort.Node)
   124  	n.stepShift = bitShift(bits, sort, sort.Step)
   125  
   126  	n.randMask = n.randMax << n.randShift
   127  	n.nodeMask = n.nodeMax << n.nodeShift
   128  	n.timeMask = n.timeMax << n.timeShift
   129  	n.stepMask = n.stepMax << n.stepShift
   130  
   131  	if node < 0 || node > n.nodeMax {
   132  		panic(fmt.Errorf("node number must be between 0 and %v", n.nodeMax))
   133  	}
   134  
   135  	return &n
   136  }
   137  
   138  // 短ID雪花算法
   139  func Shotflake(epoch, node int64) *Node {
   140  	var bits = Bits{
   141  		Rand: 0,
   142  		Time: 30,
   143  		Node: 2,
   144  		Step: 2,
   145  	}
   146  	var sort = Sort{
   147  		Rand: 4,
   148  		Time: 3,
   149  		Node: 2,
   150  		Step: 1,
   151  	}
   152  	return NewNode(epoch, 1000, node, bits, sort)
   153  }
   154  
   155  // 标准雪花算法 - Twitter
   156  func Snowflake(epoch, node int64) *Node {
   157  	var bits = Bits{
   158  		Rand: 0,
   159  		Time: 41,
   160  		Node: 10,
   161  		Step: 12,
   162  	}
   163  	var sort = Sort{
   164  		Rand: 4,
   165  		Time: 3,
   166  		Node: 2,
   167  		Step: 1,
   168  	}
   169  	return NewNode(epoch, 1, node, bits, sort)
   170  }
   171  
   172  // 索尼雪花算法
   173  func Sonyflake(epoch, node int64) *Node {
   174  	var bits = Bits{
   175  		Rand: 0,
   176  		Time: 39,
   177  		Node: 8,
   178  		Step: 16,
   179  	}
   180  	var sort = Sort{
   181  		Rand: 4,
   182  		Time: 3,
   183  		Node: 2,
   184  		Step: 1,
   185  	}
   186  	return NewNode(epoch, 10, node, bits, sort)
   187  }
   188  
   189  func (b Bits) Total() int64 {
   190  	return b.Rand + b.Time + b.Node + b.Step
   191  }
   192  
   193  func (s Sort) Count() int {
   194  	return len(map[int64]struct{}{
   195  		s.Rand: {},
   196  		s.Time: {},
   197  		s.Node: {},
   198  		s.Step: {},
   199  	})
   200  }
   201  
   202  func (n *Node) now() int64 {
   203  	return time.Since(n.epoch).Milliseconds() / n.ms
   204  }
   205  
   206  func (n *Node) GenID() ID {
   207  	n.mutex.Lock()
   208  	defer n.mutex.Unlock()
   209  
   210  	var now = n.now()
   211  
   212  	if now == n.time {
   213  		if n.step = (n.step + 1) & n.stepMax; n.step == 0 {
   214  			for now <= n.time {
   215  				now = n.now()
   216  			}
   217  		}
   218  	} else {
   219  		n.step = 0
   220  	}
   221  
   222  	n.time = now
   223  
   224  	var random int64
   225  	if n.bits.Rand != 0 {
   226  		random = n.rand.Int63() % (-1 ^ (-1 << n.bits.Rand) + 1)
   227  	}
   228  
   229  	var id = random<<n.randShift | now<<n.timeShift | n.node<<n.nodeShift | n.step<<n.stepShift
   230  
   231  	return ID(id)
   232  }
   233  
   234  func (id ID) Int64() int64 {
   235  	return int64(id)
   236  }
   237  
   238  func (id ID) Bytes() []byte {
   239  	return []byte(id.String())
   240  }
   241  
   242  func (id ID) String() string {
   243  	return strconv.FormatInt(int64(id), 10)
   244  }
   245  
   246  func (id ID) MarshalJSON() ([]byte, error) {
   247  	return json.Marshal(id.String())
   248  }
   249  
   250  func (id *ID) UnmarshalJSON(data []byte) (err error) {
   251  	var (
   252  		i   int64
   253  		str string
   254  	)
   255  
   256  	if err = json.Unmarshal(data, &str); err != nil {
   257  		return
   258  	}
   259  
   260  	if i, err = strconv.ParseInt(str, 10, 64); err != nil {
   261  		return
   262  	}
   263  
   264  	*id = ID(i)
   265  
   266  	return
   267  }