github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/random/int64.go (about)

     1  /*
     2  * 薄雾算法 github.com/asyncins/mist
     3  *
     4  * 1      2                                                     48         56       64
     5  * +------+-----------------------------------------------------+----------+----------+
     6  * retain | incr                                                | salt     | sequence |
     7  * +------+-----------------------------------------------------+----------+----------+
     8  * 0      | 0000000000 0000000000 0000000000 0000000000 0000000 | 00000000 | 00000000 |
     9  * +------+-----------------------------------------------------+------------+--------+
    10  *
    11  * 0. 最高位,占 1 位,保持为 0,使得值永远为正数;
    12  * 1. 自增数,占 47 位,自增数在高位能保证结果值呈递增态势,遂低位可以为所欲为;
    13  * 2. 随机因子一,占 8 位,上限数值 255,使结果值不可预测;
    14  * 3. 随机因子二,占 8 位,上限数值 255,使结果值不可预测;
    15  *
    16  * 编号上限为百万亿级,上限值计算为 140737488355327 即 int64(1 << 47 - 1),假设每天取值 10 亿,能使用 385+ 年
    17   */
    18  package random
    19  
    20  import (
    21  	"crypto/rand"
    22  	"math/big"
    23  	"sync"
    24  )
    25  
    26  const saltBit = uint(8)               // 随机因子二进制位数
    27  const saltShift = uint(8)             // 随机因子移位数
    28  const incrShift = saltBit + saltShift // 自增数移位数
    29  var defaultMist *Mist
    30  
    31  type Mist struct {
    32  	sync.Mutex        // 互斥锁
    33  	incr       uint64 // 自增数
    34  	saltA      uint64 // 随机因子一
    35  	saltB      uint64 // 随机因子二
    36  }
    37  
    38  func init() {
    39  	defaultMist = NewMist()
    40  }
    41  
    42  func Int64() uint64 {
    43  	return defaultMist.Generate()
    44  }
    45  
    46  func NewMist(incr ...uint64) *Mist {
    47  	var i uint64 = 1
    48  	if len(incr) > 0 && incr[0] > 0 {
    49  		i = incr[0]
    50  	}
    51  	return &Mist{incr: i}
    52  }
    53  
    54  func (c *Mist) Generate() uint64 {
    55  	c.Lock()
    56  	c.incr++
    57  	// 获取随机因子数值 | 使用真随机函数提高性能
    58  	randA, _ := rand.Int(rand.Reader, big.NewInt(255))
    59  	c.saltA = randA.Uint64()
    60  	randB, _ := rand.Int(rand.Reader, big.NewInt(255))
    61  	c.saltB = randB.Uint64()
    62  	// 实现自动占位
    63  	mist := (c.incr << incrShift) | (c.saltA << saltShift) | c.saltB
    64  	c.Unlock()
    65  	return mist
    66  }