github.com/zooyer/miskit@v1.0.71/zuid/zuid.go (about) 1 package zuid 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "math/rand" 7 "strconv" 8 "sync" 9 "time" 10 ) 11 12 type Bits struct { 13 Rand int64 // 随机位数 14 Time int64 // 时间位数 15 Node int64 // 节点位数 16 Step int64 // 序列位数 17 } 18 19 type Sort struct { 20 Rand int64 // 随机位权重 21 Time int64 // 时间位权重 22 Node int64 // 节点位权重 23 Step int64 // 序列位权重 24 } 25 26 type Node struct { 27 mutex sync.Mutex 28 rand *rand.Rand 29 30 bits Bits 31 sort Sort 32 node int64 33 step int64 34 time int64 35 ms int64 36 epoch time.Time 37 38 randMax int64 39 timeMax int64 40 nodeMax int64 41 stepMax int64 42 randMask int64 43 timeMask int64 44 nodeMask int64 45 stepMask int64 46 randShift int64 47 timeShift int64 48 nodeShift int64 49 stepShift int64 50 } 51 52 type ID int64 53 54 func NewBits(rand, time, node, step int64) Bits { 55 var bits = Bits{ 56 Rand: rand, 57 Time: time, 58 Node: node, 59 Step: step, 60 } 61 62 if total := bits.Total(); total < 5 || total > 63 { 63 panic(fmt.Errorf("total bits must between 5 and 63")) 64 } 65 66 return bits 67 } 68 69 func NewSort(rand, time, node, step int64) Sort { 70 var sort = Sort{ 71 Rand: rand, 72 Time: time, 73 Node: node, 74 Step: step, 75 } 76 77 if sort.Count() < 3 { 78 panic(fmt.Errorf("sort counts must greater than or equal to 3")) 79 } 80 81 return sort 82 } 83 84 func bitShift(bits Bits, sorts Sort, sort int64) (bit int64) { 85 if sorts.Rand < sort { 86 bit += bits.Rand 87 } 88 if sorts.Time < sort { 89 bit += bits.Time 90 } 91 if sorts.Node < sort { 92 bit += bits.Node 93 } 94 if sorts.Step < sort { 95 bit += bits.Step 96 } 97 return 98 } 99 100 func NewNode(epoch, ms, node int64, bits Bits, sort Sort) *Node { 101 // 校验失败则panic 102 bits = NewBits(bits.Rand, bits.Time, bits.Node, bits.Step) 103 sort = NewSort(sort.Rand, sort.Time, sort.Node, sort.Step) 104 105 var n Node 106 var now = time.Now() 107 108 n.rand = rand.New(rand.NewSource(now.UnixNano())) 109 110 n.bits = bits 111 n.sort = sort 112 n.node = node 113 n.epoch = now.Add(time.Unix(epoch/1000, epoch%1000*1000000).Sub(now)) 114 n.ms = ms 115 116 n.randMax = -1 ^ (-1 << bits.Rand) 117 n.timeMax = -1 ^ (-1 << bits.Time) 118 n.nodeMax = -1 ^ (-1 << bits.Node) 119 n.stepMax = -1 ^ (-1 << bits.Step) 120 121 n.randShift = bitShift(bits, sort, sort.Rand) 122 n.timeShift = bitShift(bits, sort, sort.Time) 123 n.nodeShift = bitShift(bits, sort, sort.Node) 124 n.stepShift = bitShift(bits, sort, sort.Step) 125 126 n.randMask = n.randMax << n.randShift 127 n.nodeMask = n.nodeMax << n.nodeShift 128 n.timeMask = n.timeMax << n.timeShift 129 n.stepMask = n.stepMax << n.stepShift 130 131 if node < 0 || node > n.nodeMax { 132 panic(fmt.Errorf("node number must be between 0 and %v", n.nodeMax)) 133 } 134 135 return &n 136 } 137 138 // 短ID雪花算法 139 func Shotflake(epoch, node int64) *Node { 140 var bits = Bits{ 141 Rand: 0, 142 Time: 30, 143 Node: 2, 144 Step: 2, 145 } 146 var sort = Sort{ 147 Rand: 4, 148 Time: 3, 149 Node: 2, 150 Step: 1, 151 } 152 return NewNode(epoch, 1000, node, bits, sort) 153 } 154 155 // 标准雪花算法 - Twitter 156 func Snowflake(epoch, node int64) *Node { 157 var bits = Bits{ 158 Rand: 0, 159 Time: 41, 160 Node: 10, 161 Step: 12, 162 } 163 var sort = Sort{ 164 Rand: 4, 165 Time: 3, 166 Node: 2, 167 Step: 1, 168 } 169 return NewNode(epoch, 1, node, bits, sort) 170 } 171 172 // 索尼雪花算法 173 func Sonyflake(epoch, node int64) *Node { 174 var bits = Bits{ 175 Rand: 0, 176 Time: 39, 177 Node: 8, 178 Step: 16, 179 } 180 var sort = Sort{ 181 Rand: 4, 182 Time: 3, 183 Node: 2, 184 Step: 1, 185 } 186 return NewNode(epoch, 10, node, bits, sort) 187 } 188 189 func (b Bits) Total() int64 { 190 return b.Rand + b.Time + b.Node + b.Step 191 } 192 193 func (s Sort) Count() int { 194 return len(map[int64]struct{}{ 195 s.Rand: {}, 196 s.Time: {}, 197 s.Node: {}, 198 s.Step: {}, 199 }) 200 } 201 202 func (n *Node) now() int64 { 203 return time.Since(n.epoch).Milliseconds() / n.ms 204 } 205 206 func (n *Node) GenID() ID { 207 n.mutex.Lock() 208 defer n.mutex.Unlock() 209 210 var now = n.now() 211 212 if now == n.time { 213 if n.step = (n.step + 1) & n.stepMax; n.step == 0 { 214 for now <= n.time { 215 now = n.now() 216 } 217 } 218 } else { 219 n.step = 0 220 } 221 222 n.time = now 223 224 var random int64 225 if n.bits.Rand != 0 { 226 random = n.rand.Int63() % (-1 ^ (-1 << n.bits.Rand) + 1) 227 } 228 229 var id = random<<n.randShift | now<<n.timeShift | n.node<<n.nodeShift | n.step<<n.stepShift 230 231 return ID(id) 232 } 233 234 func (id ID) Int64() int64 { 235 return int64(id) 236 } 237 238 func (id ID) Bytes() []byte { 239 return []byte(id.String()) 240 } 241 242 func (id ID) String() string { 243 return strconv.FormatInt(int64(id), 10) 244 } 245 246 func (id ID) MarshalJSON() ([]byte, error) { 247 return json.Marshal(id.String()) 248 } 249 250 func (id *ID) UnmarshalJSON(data []byte) (err error) { 251 var ( 252 i int64 253 str string 254 ) 255 256 if err = json.Unmarshal(data, &str); err != nil { 257 return 258 } 259 260 if i, err = strconv.ParseInt(str, 10, 64); err != nil { 261 return 262 } 263 264 *id = ID(i) 265 266 return 267 }