109 lines
4.1 KiB
Go
109 lines
4.1 KiB
Go
|
|
/*
|
|||
|
|
用于生成唯一的、递增的Id。生成的规则如下:
|
|||
|
|
1、生成的Id包含一个固定前缀值
|
|||
|
|
2、为了生成尽可能多的不重复数字,所以使用int64来表示一个数字,其中:
|
|||
|
|
0 000000000000000 0000000000000000000000000000 00000000000000000000
|
|||
|
|
第一部分:1位,固定为0
|
|||
|
|
第二部分:共IdentifierBit位,表示固定唯一标识(机器号或者服务器Id等)。范围为[0, math.Pow(2, IdentifierBit))
|
|||
|
|
第三部分:共ConstructCountBit位,表示对象被构造的次数。范围为[0, math.Pow(2, ConstructCountBit)),以2020-1-1 00:00:00为基准
|
|||
|
|
第四部分:共SeedBit位,表示自增种子。范围为[0, math.Pow(2, SeedBit))
|
|||
|
|
3、总体而言,此规则支持总共创建math.Pow(2, ConstructCountBit)次对象,并且每次对象构造期间生成math.Pow(2, SeedBit)个不同的数字
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
修改记录:
|
|||
|
|
2020-03-04 14:30:00 调整了时间和唯一标识在Id中的位置,以便生成递增的Id
|
|||
|
|
2020-04-20 21:10:00 同步了C#版本的逻辑
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
package idUtil
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"math"
|
|||
|
|
"sync"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type IdentifierConstructCountSeedGenerator struct {
|
|||
|
|
identifier int64 // 唯一标识
|
|||
|
|
identifierBit int32 // 唯一标识(机器号或者服务器Id等)所占的位数
|
|||
|
|
identifierBitOffset int32 // 唯一标识的偏移位数
|
|||
|
|
|
|||
|
|
constructCount int64 // 对象构造的次数
|
|||
|
|
constructCountBit int32 // 对象构造的次数所占的位数
|
|||
|
|
constructCountBitOffset int32 // 时间戳对象构造的次数的偏移位数的偏移位数
|
|||
|
|
|
|||
|
|
seed int64 // 当前种子值
|
|||
|
|
seedBit int32 // 自增种子所占的位数
|
|||
|
|
seedBitOffset int32 // 自增种子的偏移位数
|
|||
|
|
maxSeed int64 // 最大的种子值
|
|||
|
|
|
|||
|
|
mutex sync.Mutex // 锁对象
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (this *IdentifierConstructCountSeedGenerator) getNewSeed() (int64, error) {
|
|||
|
|
this.mutex.Lock()
|
|||
|
|
defer this.mutex.Unlock()
|
|||
|
|
|
|||
|
|
if this.seed >= this.maxSeed {
|
|||
|
|
return 0, fmt.Errorf("Seed's value is out of scope")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.seed += 1
|
|||
|
|
|
|||
|
|
return this.seed, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成新的Id
|
|||
|
|
// 返回值:
|
|||
|
|
// 新的Id
|
|||
|
|
// 错误对象
|
|||
|
|
func (this *IdentifierConstructCountSeedGenerator) GenerateNewId() (int64, error) {
|
|||
|
|
seed, err := this.getNewSeed()
|
|||
|
|
if err != nil {
|
|||
|
|
return 0, err
|
|||
|
|
}
|
|||
|
|
id := (this.identifier << this.identifierBitOffset) | (this.constructCount << this.constructCountBitOffset) | (seed << this.seedBitOffset)
|
|||
|
|
|
|||
|
|
return id, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建新的Id生成器对象(为了保证Id的唯一,需要保证生成的对象全局唯一)
|
|||
|
|
// identifierBit + constructCountBit + seedBit <= 63
|
|||
|
|
// identifier:id唯一标识
|
|||
|
|
// identifierBit:id唯一标识(机器号或者服务器Id等)的位数
|
|||
|
|
// constructCount:对象构造次数
|
|||
|
|
// constructCountBit:对象构造次数的位数
|
|||
|
|
// seedBit:自增种子的位数
|
|||
|
|
// 返回值:
|
|||
|
|
// 新的Id生成器对象
|
|||
|
|
// 错误对象
|
|||
|
|
func NewIdentifierConstructCountSeedGenerator(identifier int64, identifierBit int32, constructCount int64, constructCountBit, seedBit int32) (*IdentifierConstructCountSeedGenerator, error) {
|
|||
|
|
// 之所以使用63位而不是64,是为了保证值为正数
|
|||
|
|
if identifierBit+constructCountBit+seedBit > 63 {
|
|||
|
|
return nil, fmt.Errorf("总位数%d超过63位,请调整所有值的合理范围。", identifierBit+constructCountBit+seedBit)
|
|||
|
|
}
|
|||
|
|
if identifier < 0 || identifier > int64(math.Pow(2, float64(identifierBit)))-1 {
|
|||
|
|
return nil, fmt.Errorf("唯一标识值溢出,有效范围为【0,%d】", int64(math.Pow(2, float64(identifierBit)))-1)
|
|||
|
|
}
|
|||
|
|
if constructCount < 0 || constructCount > int64(math.Pow(2, float64(constructCountBit)))-1 {
|
|||
|
|
return nil, fmt.Errorf("对象构造次数的值溢出,有效范围为【0,%d】", int64(math.Pow(2, float64(constructCountBit)))-1)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
obj := &IdentifierConstructCountSeedGenerator{
|
|||
|
|
identifier: identifier,
|
|||
|
|
identifierBit: identifierBit,
|
|||
|
|
constructCount: constructCount,
|
|||
|
|
constructCountBit: constructCountBit,
|
|||
|
|
seed: 0,
|
|||
|
|
seedBit: seedBit,
|
|||
|
|
maxSeed: int64(math.Pow(2, float64(seedBit)) - 1),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
obj.seedBitOffset = 0
|
|||
|
|
obj.constructCountBitOffset = obj.seedBitOffset + obj.seedBit
|
|||
|
|
obj.identifierBitOffset = obj.constructCountBitOffset + obj.constructCountBit
|
|||
|
|
|
|||
|
|
return obj, nil
|
|||
|
|
}
|