| @@ -25,9 +25,8 @@ make install | |||||
| //snowdrift.ini | //snowdrift.ini | ||||
| snowdrift.Method=1 //1 漂移算法 2 传统算法 | snowdrift.Method=1 //1 漂移算法 2 传统算法 | ||||
| snowdrift.BaseTime=1582136402000 | snowdrift.BaseTime=1582136402000 | ||||
| snowdrift.WorkerId=1 //默认workerid | |||||
| snowdrift.WorkerIdNum=1 //支持的WorkerId数量,默认1,不超过(-1L << snowdrift.WorkerIdBitLength) ^ -1L | |||||
| snowdrift.WorkerIdBitLength=6 | |||||
| snowdrift.WorkerId=1 //默认workerid,支持参数传递改变实际使用的值,范围1~(-1L << snowdrift.WorkerIdBitLength) ^ -1L | |||||
| snowdrift.WorkerIdBitLength=6 //WorkerId位数,默认6。 | |||||
| snowdrift.SeqBitLength=6 //自增序号位数 | snowdrift.SeqBitLength=6 //自增序号位数 | ||||
| snowdrift.MaxSeqNumber=0 | snowdrift.MaxSeqNumber=0 | ||||
| snowdrift.MinSeqNumber=0 | snowdrift.MinSeqNumber=0 | ||||
| @@ -1,3 +1,40 @@ | |||||
| # ❄ idgenerator-V | # ❄ idgenerator-V | ||||
| ## 介绍 | |||||
| 项目更多介绍参照:https://github.com/yitter/idgenerator | |||||
| ## 运行环境 | |||||
| ```sh | |||||
| $ v --enable-globals run test.v | |||||
| ``` | |||||
| ## 调用示例(V) | |||||
| 第1步,**全局** 初始化(应用程序启动时执行一次): | |||||
| ```v ignore | |||||
| // 定义全局变量 | |||||
| __global ( idgen gen.YitIdHelper ) //定义全局变量 | |||||
| // 使用默认参数配置 | |||||
| idgen = gen.YitIdHelper{ | |||||
| id_gen: gen.make_generator(&contract.IdGeneratorOptions{}) | |||||
| } | |||||
| // 更改配置参数 | |||||
| idgen.set_id_generator(&contract.IdGeneratorOptions{ | |||||
| method: 1 | |||||
| base_time: 1582136402000 | |||||
| workerid_bitlength: 6 | |||||
| seq_bitlength: 10 | |||||
| }) | |||||
| //以上配置全局一次 | |||||
| ``` | |||||
| 第2步,生成ID: | |||||
| ```v ignore | |||||
| // 初始化以后,即可在任何需要生成ID的地方,调用以下方法: | |||||
| newId := idgen.next_id() | |||||
| ``` | |||||
| @@ -2,4 +2,4 @@ module contract | |||||
| pub interface IIdGenerator { | pub interface IIdGenerator { | ||||
| new_long() u64 | new_long() u64 | ||||
| } | |||||
| } | |||||
| @@ -1,5 +1,5 @@ | |||||
| module contract | module contract | ||||
| pub interface ISnowWorker { | |||||
| pub interface ISnowWorker { | |||||
| next_id() u64 | next_id() u64 | ||||
| } | |||||
| } | |||||
| @@ -2,12 +2,12 @@ module contract | |||||
| pub struct IdGeneratorOptions { | pub struct IdGeneratorOptions { | ||||
| pub mut: | pub mut: | ||||
| method u16 =1// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | |||||
| base_time i64// 基础时间,不能超过当前系统时间 | |||||
| worker_id u16 =1// 机器码,与 workerid_bitlength 有关系 | |||||
| workerid_bitlength byte=6// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | |||||
| seq_bitlength byte=6// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | |||||
| max_seqnumber u32// 最大序列数(含),(由seq_bitlength计算的最大值) | |||||
| min_seqnumber u32// 最小序列数(含),默认5,不小于1,不大于max_seqnumber | |||||
| top_over_cost_count u32 =2000// 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) | |||||
| } | |||||
| method u16 = 1 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | |||||
| base_time i64 = 1582136402000 // 基础时间,不能超过当前系统时间 | |||||
| worker_id u16 = 1 // 机器码,与 workerid_bitlength 有关系 | |||||
| workerid_bitlength byte = 6 // 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | |||||
| seq_bitlength byte = 6 // 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | |||||
| max_seqnumber u32 = 0 // 最大序列数(含),(由seq_bitlength计算的最大值) | |||||
| min_seqnumber u32 = 0 // 最小序列数(含),默认5,不小于1,不大于max_seqnumber | |||||
| top_over_cost_count u32 = 2000 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) | |||||
| } | |||||
| @@ -2,52 +2,50 @@ module core | |||||
| import contract | import contract | ||||
| import time | import time | ||||
| import sync | |||||
| pub struct SnowWorkerM1{ | |||||
| pub struct SnowWorkerM1 { | |||||
| mut: | mut: | ||||
| method u16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | |||||
| base_time i64 // 基础时间,不能超过当前系统时间 | |||||
| worker_id u16 // 机器码,与 workerid_bitlength 有关系 | |||||
| workerid_bitlength byte// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | |||||
| seq_bitlength byte// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | |||||
| max_seqnumber u32 // 最大序列数(含),(由seq_bitlength计算的最大值) | |||||
| min_seqnumber u32 // 最小序列数(含),默认5,不小于1,不大于max_seqnumber | |||||
| top_over_cost_count u32 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) | |||||
| timestamp_shift byte | |||||
| current_seqnumber u32 | |||||
| last_time_tick i64 | |||||
| turn_back_timetick i64 | |||||
| turnback_index byte | |||||
| is_over_cost bool | |||||
| method u16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | |||||
| base_time i64 // 基础时间,不能超过当前系统时间 | |||||
| worker_id u16 // 机器码,与 workerid_bitlength 有关系 | |||||
| workerid_bitlength byte // 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | |||||
| seq_bitlength byte // 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | |||||
| max_seqnumber u32 // 最大序列数(含),(由seq_bitlength计算的最大值) | |||||
| min_seqnumber u32 // 最小序列数(含),默认5,不小于1,不大于max_seqnumber | |||||
| top_over_cost_count u32 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) | |||||
| timestamp_shift byte | |||||
| current_seqnumber u32 | |||||
| last_time_tick i64 | |||||
| turn_back_timetick i64 | |||||
| turnback_index byte | |||||
| is_over_cost bool | |||||
| overcostcount_inoneterm u32 | overcostcount_inoneterm u32 | ||||
| gencount_inoneterm u32 | |||||
| term_index u32 | |||||
| mu sync.Mutex | |||||
| gencount_inoneterm u32 | |||||
| term_index u32 | |||||
| } | } | ||||
| pub fn make_sf_m1(options &contract.IdGeneratorOptions) &contract.ISnowWorker{ | |||||
| pub fn make_sf_m1(options &contract.IdGeneratorOptions) &contract.ISnowWorker { | |||||
| worker_id := options.worker_id | worker_id := options.worker_id | ||||
| mut workerid_bitlength:=byte(6) | |||||
| mut workerid_bitlength := byte(6) | |||||
| if options.workerid_bitlength != 0 { | if options.workerid_bitlength != 0 { | ||||
| workerid_bitlength = options.workerid_bitlength | workerid_bitlength = options.workerid_bitlength | ||||
| } | } | ||||
| mut seq_bitlength:=byte(6) | |||||
| mut seq_bitlength := byte(6) | |||||
| if options.seq_bitlength != 0 { | if options.seq_bitlength != 0 { | ||||
| seq_bitlength = options.seq_bitlength | seq_bitlength = options.seq_bitlength | ||||
| } | } | ||||
| mut max_seqnumber:=u32(0) | |||||
| mut max_seqnumber := u32(0) | |||||
| if options.max_seqnumber > 0 { | if options.max_seqnumber > 0 { | ||||
| max_seqnumber = options.max_seqnumber | max_seqnumber = options.max_seqnumber | ||||
| } else { | } else { | ||||
| max_seqnumber = (1<<options.seq_bitlength) - 1 | |||||
| max_seqnumber = (1 << options.seq_bitlength) - 1 | |||||
| } | } | ||||
| min_seqnumber := options.min_seqnumber | min_seqnumber := options.min_seqnumber | ||||
| top_over_cost_count := options.top_over_cost_count | top_over_cost_count := options.top_over_cost_count | ||||
| mut base_time:=i64(0) | |||||
| mut base_time := i64(0) | |||||
| if options.base_time != 0 { | if options.base_time != 0 { | ||||
| base_time = options.base_time | base_time = options.base_time | ||||
| } else { | } else { | ||||
| @@ -56,15 +54,16 @@ pub fn make_sf_m1(options &contract.IdGeneratorOptions) &contract.ISnowWorker{ | |||||
| timestamp_shift := byte(options.workerid_bitlength + options.seq_bitlength) | timestamp_shift := byte(options.workerid_bitlength + options.seq_bitlength) | ||||
| current_seqnumber := options.min_seqnumber | current_seqnumber := options.min_seqnumber | ||||
| return &SnowWorkerM1{ | return &SnowWorkerM1{ | ||||
| base_time: base_time, | |||||
| worker_id: worker_id, | |||||
| workerid_bitlength: workerid_bitlength, | |||||
| seq_bitlength: seq_bitlength, | |||||
| max_seqnumber: max_seqnumber, | |||||
| min_seqnumber: min_seqnumber, | |||||
| top_over_cost_count: top_over_cost_count, | |||||
| timestamp_shift: timestamp_shift, | |||||
| current_seqnumber: current_seqnumber} | |||||
| base_time: base_time | |||||
| worker_id: worker_id | |||||
| workerid_bitlength: workerid_bitlength | |||||
| seq_bitlength: seq_bitlength | |||||
| max_seqnumber: max_seqnumber | |||||
| min_seqnumber: min_seqnumber | |||||
| top_over_cost_count: top_over_cost_count | |||||
| timestamp_shift: timestamp_shift | |||||
| current_seqnumber: current_seqnumber | |||||
| } | |||||
| } | } | ||||
| // fn (m1 SnowWorkerM1) do_gen_id_action(arg &contract.over_cost_action_arg) { | // fn (m1 SnowWorkerM1) do_gen_id_action(arg &contract.over_cost_action_arg) { | ||||
| @@ -162,13 +161,13 @@ fn (mut m1 SnowWorkerM1) next_normal_id() u64 { | |||||
| } | } | ||||
| fn (mut m1 SnowWorkerM1) calc_id() u64 { | fn (mut m1 SnowWorkerM1) calc_id() u64 { | ||||
| result := u64(m1.last_time_tick<<m1.timestamp_shift) | u64(m1.worker_id<<m1.seq_bitlength) | u64(m1.current_seqnumber) | |||||
| result := u64(m1.last_time_tick << m1.timestamp_shift) | u64(m1.worker_id << m1.seq_bitlength) | u64(m1.current_seqnumber) | |||||
| m1.current_seqnumber++ | m1.current_seqnumber++ | ||||
| return result | return result | ||||
| } | } | ||||
| fn (mut m1 SnowWorkerM1) calc_turn_back_id() u64 { | fn (mut m1 SnowWorkerM1) calc_turn_back_id() u64 { | ||||
| result := u64(m1.turn_back_timetick<<m1.timestamp_shift) | u64(m1.worker_id<<m1.seq_bitlength) | u64(m1.turnback_index) | |||||
| result := u64(m1.turn_back_timetick << m1.timestamp_shift) | u64(m1.worker_id << m1.seq_bitlength) | u64(m1.turnback_index) | |||||
| m1.turn_back_timetick-- | m1.turn_back_timetick-- | ||||
| return result | return result | ||||
| } | } | ||||
| @@ -186,13 +185,13 @@ fn (m1 &SnowWorkerM1) get_next_time_tick() i64 { | |||||
| } | } | ||||
| pub fn (mut m1 SnowWorkerM1) next_id() u64 { | pub fn (mut m1 SnowWorkerM1) next_id() u64 { | ||||
| m1.mu.@lock() | |||||
| mut id:=u64(0) | |||||
| if m1.is_over_cost { | |||||
| id= m1.next_over_cost_id() | |||||
| } else { | |||||
| id= m1.next_normal_id() | |||||
| mut id := u64(0) | |||||
| lock { | |||||
| if m1.is_over_cost { | |||||
| id = m1.next_over_cost_id() | |||||
| } else { | |||||
| id = m1.next_normal_id() | |||||
| } | |||||
| } | } | ||||
| m1.mu.unlock() | |||||
| return id | return id | ||||
| } | |||||
| } | |||||
| @@ -2,37 +2,37 @@ module core | |||||
| import contract | import contract | ||||
| struct SnowWorkerM2{ | |||||
| struct SnowWorkerM2 { | |||||
| SnowWorkerM1 | SnowWorkerM1 | ||||
| } | } | ||||
| pub fn make_sf_m2(options &contract.IdGeneratorOptions) &contract.ISnowWorker{ | |||||
| m1:=make_sf_m1(options) | |||||
| if m1 is SnowWorkerM1{ | |||||
| return &SnowWorkerM2{ | |||||
| m1 | |||||
| } | |||||
| pub fn make_sf_m2(options &contract.IdGeneratorOptions) &contract.ISnowWorker { | |||||
| m1 := make_sf_m1(options) | |||||
| if m1 is SnowWorkerM1 { | |||||
| return &SnowWorkerM2{m1} | |||||
| } | } | ||||
| return &SnowWorkerM2{} | return &SnowWorkerM2{} | ||||
| } | } | ||||
| pub fn (mut m2 SnowWorkerM2) next_id()u64{ | |||||
| m2.mu.@lock() | |||||
| mut current_time_tick:=m2.get_current_time_tick() | |||||
| if m2.last_time_tick==current_time_tick{ | |||||
| m2.current_seqnumber=(m2.current_seqnumber+1) & m2.max_seqnumber | |||||
| if m2.current_seqnumber==0{ | |||||
| m2.current_seqnumber=m2.min_seqnumber | |||||
| current_time_tick=m2.get_next_time_tick() | |||||
| pub fn (mut m2 SnowWorkerM2) next_id() u64 { | |||||
| mut id := u64(0) | |||||
| lock { | |||||
| mut current_time_tick := m2.get_current_time_tick() | |||||
| if m2.last_time_tick == current_time_tick { | |||||
| m2.current_seqnumber = (m2.current_seqnumber + 1) & m2.max_seqnumber | |||||
| if m2.current_seqnumber == 0 { | |||||
| m2.current_seqnumber = m2.min_seqnumber | |||||
| current_time_tick = m2.get_next_time_tick() | |||||
| } | |||||
| } else { | |||||
| m2.current_seqnumber = m2.min_seqnumber | |||||
| } | } | ||||
| }else{ | |||||
| m2.current_seqnumber=m2.min_seqnumber | |||||
| } | |||||
| if current_time_tick < m2.last_time_tick { | |||||
| println("Time error for "+(m2.last_time_tick-current_time_tick).str()+" milliseconds") | |||||
| if current_time_tick < m2.last_time_tick { | |||||
| println('Time error for ' + (m2.last_time_tick - current_time_tick).str() + | |||||
| ' milliseconds') | |||||
| } | |||||
| m2.last_time_tick = current_time_tick | |||||
| id = u64(current_time_tick << m2.timestamp_shift) | u64(m2.worker_id << m2.seq_bitlength) | u64(m2.current_seqnumber) | |||||
| } | } | ||||
| m2.last_time_tick=current_time_tick | |||||
| id:= u64(current_time_tick<<m2.timestamp_shift) | u64(m2.worker_id<<m2.seq_bitlength) | u64(m2.current_seqnumber) | |||||
| m2.mu.unlock() | |||||
| return id | return id | ||||
| } | |||||
| } | |||||
| @@ -6,62 +6,60 @@ import time | |||||
| pub struct DefaultIdGenerator { | pub struct DefaultIdGenerator { | ||||
| mut: | mut: | ||||
| options &contract.IdGeneratorOptions | |||||
| snow_worker &contract.ISnowWorker | |||||
| options &contract.IdGeneratorOptions | |||||
| snow_worker &contract.ISnowWorker | |||||
| } | } | ||||
| pub fn make_generator(options &contract.IdGeneratorOptions) &DefaultIdGenerator { | pub fn make_generator(options &contract.IdGeneratorOptions) &DefaultIdGenerator { | ||||
| min_time := i64(631123200000) | min_time := i64(631123200000) | ||||
| if options.base_time < min_time || options.base_time > time.now().unix_time_milli() { | |||||
| panic("base_time error.") | |||||
| if options.base_time < min_time || options.base_time > time.now().unix_time_milli() { | |||||
| panic('base_time error.') | |||||
| } | } | ||||
| if options.seq_bitlength+options.workerid_bitlength > 22 { | |||||
| panic("error:workerid_bitlength + seq_bitlength <= 22") | |||||
| if options.seq_bitlength + options.workerid_bitlength > 22 { | |||||
| panic('error:workerid_bitlength + seq_bitlength <= 22') | |||||
| } | } | ||||
| max_workerid_number := 1<<options.workerid_bitlength - 1 | |||||
| max_workerid_number := 1 << options.workerid_bitlength - 1 | |||||
| if options.worker_id > max_workerid_number { | if options.worker_id > max_workerid_number { | ||||
| panic("WorkerId error. (range:[1, " + max_workerid_number.str() + "]") | |||||
| panic('WorkerId error. (range:[1, ' + max_workerid_number.str() + ']') | |||||
| } | } | ||||
| if options.seq_bitlength < 2 || options.seq_bitlength > 21 { | if options.seq_bitlength < 2 || options.seq_bitlength > 21 { | ||||
| panic("seq_bitlength error. (range:[2, 21])") | |||||
| panic('seq_bitlength error. (range:[2, 21])') | |||||
| } | } | ||||
| max_seqnumber := 1<<options.seq_bitlength - 1 | |||||
| max_seqnumber := 1 << options.seq_bitlength - 1 | |||||
| if options.max_seqnumber > max_seqnumber { | if options.max_seqnumber > max_seqnumber { | ||||
| panic("MaxSeqNumber error. (range:[1, " + max_seqnumber.str() + "]") | |||||
| panic('MaxSeqNumber error. (range:[1, ' + max_seqnumber.str() + ']') | |||||
| } | } | ||||
| if options.min_seqnumber > max_seqnumber { | if options.min_seqnumber > max_seqnumber { | ||||
| panic("MinSeqNumber error. (range:[1, " + max_seqnumber.str() + "]") | |||||
| panic('MinSeqNumber error. (range:[1, ' + max_seqnumber.str() + ']') | |||||
| } | } | ||||
| match options.method { | match options.method { | ||||
| 1 { | 1 { | ||||
| return &DefaultIdGenerator{ | return &DefaultIdGenerator{ | ||||
| options: options, | |||||
| snow_worker: core.make_sf_m1(options), | |||||
| options: options | |||||
| snow_worker: core.make_sf_m1(options) | |||||
| } | } | ||||
| } | } | ||||
| 2 { | 2 { | ||||
| return &DefaultIdGenerator{ | return &DefaultIdGenerator{ | ||||
| options: options, | |||||
| snow_worker: core.make_sf_m2(options), | |||||
| options: options | |||||
| snow_worker: core.make_sf_m2(options) | |||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| return &DefaultIdGenerator{ | return &DefaultIdGenerator{ | ||||
| options: options, | |||||
| snow_worker: core.make_sf_m1(options), | |||||
| options: options | |||||
| snow_worker: core.make_sf_m1(options) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| pub fn (mut dig DefaultIdGenerator) new_long() u64 { | pub fn (mut dig DefaultIdGenerator) new_long() u64 { | ||||
| return dig.snow_worker.next_id() | return dig.snow_worker.next_id() | ||||
| } | |||||
| } | |||||
| @@ -2,11 +2,17 @@ module gen | |||||
| import contract | import contract | ||||
| pub struct YitIdHelper { | |||||
| pub struct YitIdHelper { | |||||
| mut: | mut: | ||||
| id_gen contract.IIdGenerator | id_gen contract.IIdGenerator | ||||
| } | } | ||||
| pub fn (mut yih YitIdHelper) set_id_generator(options &contract.IdGeneratorOptions) { | |||||
| lock { | |||||
| yih.id_gen = make_generator(options) | |||||
| } | |||||
| } | |||||
| pub fn (yih &YitIdHelper) next_id() u64 { | pub fn (yih &YitIdHelper) next_id() u64 { | ||||
| return yih.id_gen.new_long() | return yih.id_gen.new_long() | ||||
| } | |||||
| } | |||||
| @@ -1,31 +1,34 @@ | |||||
| module main | module main | ||||
| import time | import time | ||||
| import contract | import contract | ||||
| import gen | import gen | ||||
| fn main(){ | |||||
| // 方法一:直接采用默认方法生成一个Id | |||||
| yid := gen.YitIdHelper{ | |||||
| id_gen: gen.make_generator(&contract.IdGeneratorOptions{ | |||||
| method: 1 | |||||
| base_time: 1582136402000 | |||||
| workerid_bitlength:6 | |||||
| seq_bitlength:6 | |||||
| }) | |||||
| __global ( idgen gen.YitIdHelper ) | |||||
| fn main() { | |||||
| idgen = gen.YitIdHelper{ | |||||
| id_gen: gen.make_generator(&contract.IdGeneratorOptions{}) | |||||
| } | } | ||||
| println(yid.next_id()) | |||||
| // 方法一:直接采用默认方法生成一个Id | |||||
| println(idgen.next_id()) | |||||
| // 方法二:自定义参数 | |||||
| idgen.set_id_generator(&contract.IdGeneratorOptions{ | |||||
| method: 1 | |||||
| base_time: 1582136402000 | |||||
| workerid_bitlength: 6 | |||||
| seq_bitlength: 10 | |||||
| }) | |||||
| times := 50000 | times := 50000 | ||||
| for { | for { | ||||
| begin := time.now().unix_time_milli() | begin := time.now().unix_time_milli() | ||||
| for i := 0; i < times; i++ { | for i := 0; i < times; i++ { | ||||
| yid.next_id() | |||||
| idgen.next_id() | |||||
| } | } | ||||
| end := time.now().unix_time_milli() | end := time.now().unix_time_milli() | ||||
| println("漂移,总共:"+times.str()+","+(end-begin).str()+" ms") | |||||
| println('漂移,总共:' + times.str() + ',' + (end - begin).str() + ' ms') | |||||
| time.sleep(1 * time.second) | time.sleep(1 * time.second) | ||||
| } | } | ||||
| } | |||||
| } | |||||