设计思路:时序型索引
使用Golang实现了一个时序ID生成器,采用8字节[]byte,可容纳公元0年起每秒最多65536个ID。
前5字节是时间戳timer,由于需要容纳较长年份,因此比传统4字节多1字节。
后3字节是计数器counter,记录每秒内的递增数,3字节最长65536。
ID可表示为8字节[]byte,uint64及36进制string。
附一组解码器,返回timer和counter。
package main
import (
"encoding/binary"
"fmt"
"strconv"
"time"
)
var AidTimer int64
var AidCounter uint16 = 0 // 先限制2位,以后可放宽到3位
func Aid() []byte {
now := 62135596800 + time.Now().Unix()
if AidTimer == now {
AidCounter++
} else {
AidTimer = now
AidCounter = 0
}
tB := make([]byte, 8)
binary.BigEndian.PutUint64(tB, uint64(AidTimer))
cB := make([]byte, 4)
binary.BigEndian.PutUint32(cB, uint32(AidCounter))
return append(tB[3:], cB[1:]...)
}
func Aid10() uint64 {
return binary.BigEndian.Uint64(Aid())
}
func Aid36() string {
return strconv.FormatUint(Aid10(), 36)
}
func AidDecoder(aid []byte) (uint64, uint32) {
timer := binary.BigEndian.Uint64(append(make([]byte, 3), aid[0:5]...))
counter := binary.BigEndian.Uint32(append(make([]byte, 1), aid[5:]...))
return timer, counter
}
func Aid10Decoder(aid10 uint64) (uint64, uint32) {
aid := make([]byte, 8)
binary.BigEndian.PutUint64(aid, aid10)
return AidDecoder(aid)
}
func Aid36Decoder(aid36 string) (uint64, uint32) {
aid10, err := strconv.ParseUint(aid36, 36, 64)
if err != nil {
return 0, 0
}
return Aid10Decoder(aid10)
}
func main() {
fmt.Println(AidDecoder(Aid()))
fmt.Println(Aid10Decoder(Aid10()))
fmt.Println(Aid36Decoder(Aid36()))
}