90 lines
2.6 KiB
Go
Raw Permalink Normal View History

2020-12-28 05:11:31 +08:00
/*
* 薄雾算法
*
* 1 2 48 56 64
* +------+-----------------------------------------------------+----------+----------+
* retain | increas | salt | sequence |
* +------+-----------------------------------------------------+----------+----------+
* 0 | 0000000000 0000000000 0000000000 0000000000 0000000 | 00000000 | 00000000 |
* +------+-----------------------------------------------------+------------+--------+
*
* 0. 最高位 1 保持为 0使得值永远为正数
* 1. 自增数 47 自增数在高位能保证结果值呈递增态势遂低位可以为所欲为
* 2. 随机因子一 8 上限数值 255使结果值不可预测
* 3. 随机因子二 8 上限数值 255使结果值不可预测
*
* 编号上限为百万亿级上限值计算为 140737488355327 int64(1 << 47 - 1)假设每天取值 10 亿能使用 385+
*/
package main
import (
"crypto/rand"
"fmt"
"math/big"
"strconv"
"sync"
"time"
)
const startYear = 2019
const saltBit = uint(8) // 随机因子二进制位数
const saltShift = uint(8) // 随机因子移位数
const increasShift = saltBit + saltShift // 自增数移位数
func NewIncreaserFromTime(t time.Time) int64 {
year := t.Year() - startYear
day := t.YearDay()
secs := 60*60*t.Hour() + 60*t.Minute() + t.Second()
s := fmt.Sprintf("%d%d%05d", year, day, secs)
v, _ := strconv.ParseInt(s, 10, 64)
return v
}
type Mist struct {
sync.Mutex // 互斥锁
increas int64 // 自增数
saltA int64 // 随机因子一
saltB int64 // 随机因子二
}
/* 初始化 Mist 结构体*/
func NewMist(c int64) *Mist {
mist := Mist{increas: c}
return &mist
}
/* 生成唯一编号 */
func (c *Mist) Generate() int64 {
c.Lock()
defer c.Unlock()
c.increas++
// 获取随机因子数值 使用真随机函数提高性能
randA, _ := c.newRand()
c.saltA = randA.Int64()
randB, _ := c.newRand()
c.saltB = randB.Int64()
// 通过位运算实现自动占位
mist := int64((c.increas << increasShift) | (c.saltA << saltShift) | c.saltB)
return mist
}
func (c Mist) newRand() (*big.Int, error) {
return rand.Int(rand.Reader, big.NewInt(255))
}
func main() {
// 使用方法
// mist := NewMist(NewIncreaserFromTime(time.Now()))
mist := NewMist(31175572)
m := make(map[int64]int)
for i := 0; i < 10; i++ {
v := mist.Generate()
if _, ok := m[v]; ok {
fmt.Println(v, i)
}
m[v] = i
fmt.Println(v)
}
}