提交 ffb9978f 编写于 作者: Z zhouzj

AddGo

上级 7ade620f
......@@ -22,7 +22,7 @@ namespace Yitter.IdGenerator
public virtual short Method { get; set; } = 1;
/// <summary>
/// 开始时间(UTC格式)
/// 基础时间(UTC格式)
/// 不能超过当前系统时间
/// </summary>
public virtual DateTime BaseTime { get; set; } = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc);
......
# idgenerator
something is going on.
## Go环境
1.go 1.16
2. 默认采用GOROOT方式编译,你可修改为Go-Modules
## Go代码示例
```
var yid = idgen.YitIdHelper{}
fmt.Println(yid.NextId())
// 方法二:自定义参数
var options = contract.NewIdGeneratorOptions(1)
//options.WorkerIdBitLength = 6
//options.SeqBitLength = 6
//options.TopOverCostCount = 2000
//options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6
yid.SetIdGenerator(options)
```
package main
import (
"../yitidgen/contract"
"../yitidgen/idgen"
"fmt"
"time"
)
func main() {
// 方法一:直接采用默认方法生成一个Id
var yid = idgen.YitIdHelper{}
fmt.Println(yid.NextId())
// 方法二:自定义参数
var options = contract.NewIdGeneratorOptions(1)
//options.WorkerIdBitLength = 6
//options.SeqBitLength = 6
//options.TopOverCostCount = 2000
//options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6
yid.SetIdGenerator(options)
var times = 50000
for ; ; {
var begin = time.Now().UnixNano() / 1e6
for i := 0; i < times; i++ {
yid.NextId()
}
var end = time.Now().UnixNano() / 1e6
fmt.Println(end - begin)
time.Sleep(time.Duration(1000) * time.Millisecond)
}
}
package contract
type IIdGenerator interface {
NewLong() uint64
}
package contract
type ISnowWorker interface {
NextId() uint64
}
package contract
import "fmt"
type IdGeneratorException struct {
message string
error error
}
func (e IdGeneratorException) IdGeneratorException(message ...interface{}) {
fmt.Println(message)
}
package contract
type IdGeneratorOptions struct {
Method uint16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1
BaseTime int64 // 基础时间,不能超过当前系统时间
WorkerId uint16 // 机器码,与 WorkerIdBitLength 有关系
WorkerIdBitLength byte // 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22)
SeqBitLength byte // 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22)
MaxSeqNumber uint32 // 最大序列数(含),(由SeqBitLength计算的最大值)
MinSeqNumber uint32 // 最小序列数(含),默认5,不小于1,不大于MaxSeqNumber
TopOverCostCount uint // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关)
}
func NewIdGeneratorOptions(workerId uint16) *IdGeneratorOptions {
return &IdGeneratorOptions{
Method: 1,
WorkerId: workerId,
BaseTime: 1582136402000,
WorkerIdBitLength: 6,
SeqBitLength: 6,
MaxSeqNumber: 0,
MinSeqNumber: 5,
TopOverCostCount: 2000,
}
}
package contract
type OverCostActionArg struct {
ActionType int
TimeTick int64
WorkerId int64
OverCostCountInOneTerm int
GenCountInOneTerm int
TermIndex int
}
func (ocaa OverCostActionArg) OverCostActionArg(workerId int64, timeTick int64, actionType int, overCostCountInOneTerm int, genCountWhenOverCost int, index int) {
ocaa.ActionType = actionType
ocaa.TimeTick = timeTick
ocaa.WorkerId = workerId
ocaa.OverCostCountInOneTerm = overCostCountInOneTerm
ocaa.GenCountInOneTerm = genCountWhenOverCost
ocaa.TermIndex = index
}
package core
import (
"../contract"
"math"
"sync"
"time"
)
type SnowWorkerM1 struct {
BaseTime int64 //基础时间
WorkerId uint16 //机器码
WorkerIdBitLength byte //机器码位长
SeqBitLength byte //自增序列数位长
MaxSeqNumber uint32 //最大序列数(含)
MinSeqNumber uint32 //最小序列数(含)
TopOverCostCount uint //最大漂移次数
_TimestampShift byte
_CurrentSeqNumber uint32
_LastTimeTick int64
_TurnBackTimeTick int64
_TurnBackIndex byte
_IsOverCost bool
_OverCostCountInOneTerm uint
_GenCountInOneTerm uint
_TermIndex uint
sync.Mutex
}
func NewSnowWorkerM1(options *contract.IdGeneratorOptions) contract.ISnowWorker {
var WorkerIdBitLength byte
var SeqBitLength byte
var MaxSeqNumber uint32
var WorkerId = options.WorkerId
if options.WorkerIdBitLength == 0 {
WorkerIdBitLength = 6
} else {
WorkerIdBitLength = options.WorkerIdBitLength
}
if options.SeqBitLength == 0 {
SeqBitLength = 6
} else {
SeqBitLength = options.SeqBitLength
}
if options.MaxSeqNumber > 0 {
MaxSeqNumber = options.MaxSeqNumber
} else {
MaxSeqNumber = uint32(math.Pow(2, float64(options.SeqBitLength))) - 1
}
var MinSeqNumber = options.MinSeqNumber
var TopOverCostCount = options.TopOverCostCount
var BaseTime int64
if options.BaseTime != 0 {
BaseTime = options.BaseTime
} else {
BaseTime = 1582136402000
}
timestampShift := (byte)(options.WorkerIdBitLength + options.SeqBitLength)
currentSeqNumber := options.MinSeqNumber
return &SnowWorkerM1{
BaseTime: BaseTime,
WorkerId: WorkerId,
WorkerIdBitLength: WorkerIdBitLength,
SeqBitLength: SeqBitLength,
MaxSeqNumber: MaxSeqNumber,
MinSeqNumber: MinSeqNumber,
TopOverCostCount: TopOverCostCount,
_TimestampShift: timestampShift,
_CurrentSeqNumber: currentSeqNumber}
}
func (m1 *SnowWorkerM1) DoGenIdAction(arg *contract.OverCostActionArg) {
}
func (m1 *SnowWorkerM1) BeginOverCostAction(useTimeTick int64) {
}
func (m1 *SnowWorkerM1) EndOverCostAction(useTimeTick int64) {
if m1._TermIndex > 10000 {
m1._TermIndex = 0
}
}
func (m1 *SnowWorkerM1) BeginTurnBackAction(useTimeTick int64) {
}
func (m1 *SnowWorkerM1) EndTurnBackAction(useTimeTick int64) {
}
func (m1 *SnowWorkerM1) NextOverCostId() uint64 {
currentTimeTick := m1.GetCurrentTimeTick()
if currentTimeTick > m1._LastTimeTick {
m1.EndOverCostAction(currentTimeTick)
m1._LastTimeTick = currentTimeTick
m1._CurrentSeqNumber = m1.MinSeqNumber
m1._IsOverCost = false
m1._OverCostCountInOneTerm = 0
m1._GenCountInOneTerm = 0
return m1.CalcId(m1._LastTimeTick)
}
if m1._OverCostCountInOneTerm >= m1.TopOverCostCount {
m1.EndOverCostAction(currentTimeTick)
m1._LastTimeTick = m1.GetNextTimeTick()
m1._CurrentSeqNumber = m1.MinSeqNumber
m1._IsOverCost = false
m1._OverCostCountInOneTerm = 0
m1._GenCountInOneTerm = 0
return m1.CalcId(m1._LastTimeTick)
}
if m1._CurrentSeqNumber > m1.MaxSeqNumber {
m1._LastTimeTick++
m1._CurrentSeqNumber = m1.MinSeqNumber
m1._IsOverCost = true
m1._OverCostCountInOneTerm++
m1._GenCountInOneTerm++
return m1.CalcId(m1._LastTimeTick)
}
m1._GenCountInOneTerm++
return m1.CalcId(m1._LastTimeTick)
}
func (m1 *SnowWorkerM1) NextNormalId() uint64 {
currentTimeTick := m1.GetCurrentTimeTick()
if currentTimeTick < m1._LastTimeTick {
if m1._TurnBackTimeTick < 1 {
m1._TurnBackTimeTick = m1._LastTimeTick - 1
m1._TurnBackIndex++
// 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序
// 最多4次回拨(防止回拨重叠)
if m1._TurnBackIndex > 4 {
m1._TurnBackIndex = 1
}
m1.BeginTurnBackAction(m1._TurnBackTimeTick)
}
time.Sleep(time.Duration(10) * time.Millisecond)
return m1.CalcTurnBackId(m1._TurnBackTimeTick)
}
// 时间追平时,_TurnBackTimeTick清零
if m1._TurnBackTimeTick > 0 {
m1.EndTurnBackAction(m1._TurnBackTimeTick)
m1._TurnBackTimeTick = 0
}
if currentTimeTick > m1._LastTimeTick {
m1._LastTimeTick = currentTimeTick
m1._CurrentSeqNumber = m1.MinSeqNumber
return m1.CalcId(m1._LastTimeTick)
}
if m1._CurrentSeqNumber > m1.MaxSeqNumber {
m1.BeginOverCostAction(currentTimeTick)
m1._TermIndex++
m1._LastTimeTick++
m1._CurrentSeqNumber = m1.MinSeqNumber
m1._IsOverCost = true
m1._OverCostCountInOneTerm = 1
m1._GenCountInOneTerm = 1
return m1.CalcId(m1._LastTimeTick)
}
return m1.CalcId(m1._LastTimeTick)
}
func (m1 *SnowWorkerM1) CalcId(useTimeTick int64) uint64 {
result := uint64(useTimeTick<<m1._TimestampShift) + uint64(m1.WorkerId<<m1.SeqBitLength) + uint64(m1._CurrentSeqNumber)
m1._CurrentSeqNumber++
return result
}
func (m1 *SnowWorkerM1) CalcTurnBackId(useTimeTick int64) uint64 {
result := uint64(useTimeTick<<m1._TimestampShift) + uint64(m1.WorkerId<<m1.SeqBitLength) + uint64(m1._TurnBackIndex)
m1._TurnBackTimeTick--
return result
}
func (m1 *SnowWorkerM1) GetCurrentTimeTick() int64 {
var millis = time.Now().UnixNano() / 1e6
return millis - m1.BaseTime
}
func (m1 *SnowWorkerM1) GetNextTimeTick() int64 {
tempTimeTicker := m1.GetCurrentTimeTick()
for tempTimeTicker <= m1._LastTimeTick {
tempTimeTicker = m1.GetCurrentTimeTick()
}
return tempTimeTicker
}
func (m1 *SnowWorkerM1) NextId() uint64 {
m1.Lock()
defer m1.Unlock()
if m1._IsOverCost {
return m1.NextOverCostId()
} else {
return m1.NextNormalId()
}
}
package core
import (
"../contract"
"fmt"
"strconv"
"sync/atomic"
)
type SnowWorkerM2 struct {
*SnowWorkerM1
}
func NewSnowWorkerM2(options *contract.IdGeneratorOptions) contract.ISnowWorker {
return &SnowWorkerM2{
NewSnowWorkerM1(options).(*SnowWorkerM1),
}
}
func (m2 SnowWorkerM2) NextId() uint64 {
currentTimeTick := m2.GetCurrentTimeTick()
if m2._LastTimeTick == currentTimeTick {
atomic.AddUint32(&m2._CurrentSeqNumber, 1)
if m2._CurrentSeqNumber > m2.MaxSeqNumber {
atomic.StoreUint32(&m2._CurrentSeqNumber, uint32(m2.MinSeqNumber))
currentTimeTick = m2.GetNextTimeTick()
}
} else {
atomic.StoreUint32(&m2._CurrentSeqNumber, uint32(m2.MinSeqNumber))
}
if currentTimeTick < m2._LastTimeTick {
fmt.Println("Time error for {0} milliseconds", strconv.FormatInt(m2._LastTimeTick-currentTimeTick, 10))
}
m2._LastTimeTick = currentTimeTick
result := uint64((currentTimeTick << m2._TimestampShift)) + uint64(m2.WorkerId<<m2.SeqBitLength) + uint64(m2._CurrentSeqNumber)
return result
}
package idgen
import (
"../contract"
"../core"
"math"
"time"
)
type DefaultIdGenerator struct {
Options *contract.IdGeneratorOptions
SnowWorker contract.ISnowWorker
IdGeneratorException contract.IdGeneratorException
}
func NewDefaultIdGenerator(Options *contract.IdGeneratorOptions) *DefaultIdGenerator {
if Options == nil {
panic("dig.Options error.")
}
var minTime = time.Now().AddDate(-50, 0, 0).UnixNano() / 1e6
if minTime == 0 || Options.BaseTime < minTime || Options.BaseTime > time.Now().UnixNano()/1e6 {
panic("BaseTime error.")
}
if Options.SeqBitLength+Options.WorkerIdBitLength > 22 {
panic("error:WorkerIdBitLength + SeqBitLength <= 22")
}
maxWorkerIdNumber := uint16(math.Pow(float64(2), float64(Options.WorkerIdBitLength))) - 1
if Options.WorkerId > maxWorkerIdNumber {
panic("WorkerId error. (range:[1, "+ string(maxWorkerIdNumber)+ "]")
}
if Options.SeqBitLength < 2 || Options.SeqBitLength > 21 {
panic("SeqBitLength error. (range:[2, 21])")
}
maxSeqNumber := uint32(math.Pow(2, float64(Options.SeqBitLength))) - 1
if Options.MaxSeqNumber > maxSeqNumber {
panic("MaxSeqNumber error. (range:[1, "+ string(maxSeqNumber)+ "]")
}
if Options.MinSeqNumber > maxSeqNumber {
panic("MinSeqNumber error. (range:[1, "+ string(maxSeqNumber)+ "]")
}
var snowWorker contract.ISnowWorker
switch Options.Method {
case 1:
snowWorker = core.NewSnowWorkerM1(Options)
case 2:
snowWorker = core.NewSnowWorkerM2(Options)
default:
snowWorker = core.NewSnowWorkerM1(Options)
}
if Options.Method == 1 {
time.Sleep(time.Duration(500) * time.Microsecond)
}
return &DefaultIdGenerator{
Options: Options,
SnowWorker: snowWorker,
}
}
func (dig DefaultIdGenerator) NewLong() uint64 {
return dig.SnowWorker.NextId()
}
package idgen
import (
"../contract"
"sync"
)
var ins *YitIdHelper
var once sync.Once
type YitIdHelper struct {
idGenInstance interface {
NewLong() uint64
}
}
func GetIns() *YitIdHelper {
once.Do(func() {
ins = &YitIdHelper{}
})
return ins
}
func (yih *YitIdHelper) GetIdGenInstance() interface{} {
return yih.idGenInstance
}
func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) {
yih.idGenInstance = NewDefaultIdGenerator(options)
}
func (yih *YitIdHelper) NextId() uint64 {
once.Do(func() {
if yih.idGenInstance == nil {
options := contract.NewIdGeneratorOptions(1)
yih.idGenInstance = NewDefaultIdGenerator(options)
}
})
return yih.idGenInstance.NewLong()
}
......@@ -17,7 +17,7 @@ public class IdGeneratorOptions {
public short Method = 1;
/**
* 开始时间
* 基础时间
* 不能超过当前系统时间
*/
public long BaseTime = 1582136402000L;
......
......@@ -34,8 +34,8 @@ public class StartUp {
options.BaseTime = 1582206693000L;
options.WorkerId = 1;
IIdGenerator IdGen = new DefaultIdGenerator(options);
GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId);
IIdGenerator idGen = new DefaultIdGenerator(options);
GenTest genTest = new GenTest(idGen, genIdCount, options.WorkerId);
// 首先测试一下 IdHelper 方法,获取单个Id
YitIdHelper.setIdGenerator(options);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册