forked from free-lancers/electricity_bill_calc_service
		
	feat(serial):增加改进雪花算法。
This commit is contained in:
		
							
								
								
									
										76
									
								
								tools/serial/algorithm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								tools/serial/algorithm.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| package serial | ||||
|  | ||||
| import ( | ||||
| 	"electricity_bill_calc/config" | ||||
| 	"electricity_bill_calc/global" | ||||
| 	"electricity_bill_calc/logger" | ||||
| 	"electricity_bill_calc/tools/time" | ||||
| 	"fmt" | ||||
| 	stdTime "time" | ||||
|  | ||||
| 	"github.com/rueian/rueidis" | ||||
| 	"github.com/samber/lo" | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| var log = logger.Named("Algorithm", "Unique Serial") | ||||
|  | ||||
| // 在防止服务器时间回拨的情况下,生成一个用于生成唯一编号的精简时间戳,该时间戳的起始时间为`2022-02-22 22:22:22.000000 +0800`,时间戳精确到秒。 | ||||
| func generateTimestamp() int64 { | ||||
| 	for { | ||||
| 		timestamp := time.Timestamp() | ||||
| 		cmds := make(rueidis.Commands, 0, 2) | ||||
| 		cmds = append(cmds, global.Rd.B().Set().Key("LAST_TIMESTAMP").Value(fmt.Sprintf("%d", timestamp)).Nx().ExSeconds(1).Build()) | ||||
| 		cmds = append(cmds, global.Rd.B().Get().Key("LAST_TIMESTAMP").Build()) | ||||
| 		results := global.Rd.DoMulti(global.Ctx, cmds...) | ||||
| 		store_res, err := lo.Last(results) | ||||
| 		if err != nil { | ||||
| 			log.Error("从Redis缓存中获取上一次的时间戳失败。", zap.Error(err)) | ||||
| 			stdTime.Sleep(1 * stdTime.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 		if stored_timestamp, err := store_res.AsInt64(); err == nil && timestamp >= stored_timestamp { | ||||
| 			return timestamp | ||||
| 		} else { | ||||
| 			log.Error("转换从Redis缓存中获取的时间戳失败。", zap.Error(err)) | ||||
| 			stdTime.Sleep(1 * stdTime.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 生成一个基于精简改进的雪花算法的数字类型唯一编号。 | ||||
| func GenerateUniqueSerial() int64 { | ||||
| 	for { | ||||
| 		timestamp := generateTimestamp() | ||||
| 		cmds := make(rueidis.Commands, 0, 2) | ||||
| 		cmds = append(cmds, global.Rd.B().Set().Key("SERIAL").Value(fmt.Sprintf("%d", 0)).Nx().ExSeconds(1).Build()) | ||||
| 		cmds = append(cmds, global.Rd.B().Incr().Key("SERIAL").Build()) | ||||
| 		results := global.Rd.DoMulti(global.Ctx, cmds...) | ||||
| 		store_res, err := lo.Last(results) | ||||
| 		if err != nil { | ||||
| 			log.Error("从Redis缓存中获取上一次的序列号失败。", zap.Error(err)) | ||||
| 			stdTime.Sleep(1 * stdTime.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 		if stored_serial, err := store_res.AsInt64(); err == nil { | ||||
| 			return (timestamp << 20) | ((config.ServiceSettings.HostSerial & 0xffff) << 16) | (stored_serial & 0xffff_ffff) | ||||
| 		} else { | ||||
| 			log.Error("转换从Redis缓存中获取的序列号失败。", zap.Error(err)) | ||||
| 			stdTime.Sleep(1 * stdTime.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 生成一个基于精简改进的雪花算法的字符串类型唯一编号。 | ||||
| func GenerateUniqueSerialString() string { | ||||
| 	uniqueId := GenerateUniqueSerial() | ||||
| 	return fmt.Sprintf("%d", uniqueId) | ||||
| } | ||||
|  | ||||
| // 生成一个带有前缀的基于精简改进的雪花算法的字符串类型唯一编号。 | ||||
| func GeneratePrefixedUniqueSerialString(prefix string) string { | ||||
| 	uniqueId := GenerateUniqueSerial() | ||||
| 	return fmt.Sprintf("%s%d", prefix, uniqueId) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user