electricity_bill_calc_service/tools/serial/algorithm.go

85 lines
2.2 KiB
Go

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 ""
}