package serial import ( "electricity_bill_calc/config" "electricity_bill_calc/logger" "electricity_bill_calc/types" "fmt" "time" ) var ( log = logger.Named("Algorithm", "Unique Serial") SerialRequestChan = make(chan int64, 500) StringSerialRequestChan = make(chan int64, 500) SerialResponseChan = make(chan int64, 500) StringSerialResponseChan = make(chan string, 500) ) func init() { go func() { var ( lastTimestamp int64 = 0 lastSerial int64 = 0 ) log.Info("唯一序列号生成服务已经启动。") for { select { case <-SerialRequestChan: log.Info("收到生成数字型唯一序列号的请求。") timestamp := generateTimestamp(lastTimestamp) if timestamp != lastTimestamp { lastSerial = 0 } lastSerial = lastSerial + 1 uniqueId := generateSerial(timestamp, lastSerial) SerialResponseChan <- uniqueId lastTimestamp = timestamp case <-StringSerialRequestChan: log.Info("收到生成字符串型唯一序列号的请求。") timestamp := generateTimestamp(lastTimestamp) if timestamp != lastTimestamp { lastSerial = 0 } lastSerial = lastSerial + 1 uniqueId := generateStringSerial(timestamp, lastSerial) StringSerialResponseChan <- uniqueId lastTimestamp = timestamp } } }() } // 生成一个能够对抗服务器时间回拨的时间戳 func generateTimestamp(base int64) int64 { for { timestamp := types.Timestamp() if timestamp >= base { return timestamp } time.Sleep(1 * time.Second) } } // 生成一个唯一的数字型序列号 func generateSerial(timestamp, serial int64) int64 { return (timestamp << 20) | ((config.ServiceSettings.HostSerial & 0xffff) << 16) | (serial & 0xffff_ffff) } // 生成一个唯一的字符串型序列号 func generateStringSerial(timestamp, serial int64) string { return fmt.Sprintf("%017d", generateSerial(timestamp, serial)) } // 生成一个带前缀字符串的唯一字符串型序列号 func Prefix(prefix string, serial interface{}) string { switch serial := serial.(type) { case int64: return fmt.Sprintf("%s%017d", prefix, serial) case string: return fmt.Sprintf("%s%s", prefix, serial) } return "" }