使用UUID
UUID是通用唯一识别码(Universally Unique Identifier)的缩写,其目的是让分布式系统中的所有元素,都能有唯一的辨识信息。UUID是由一组32位数的16进制数字构成,所以UUID理论上总数为16^32=2^128。
UUID有五个版本:
- 版本1:基于时间戳和mac地址
- 版本2:基于时间戳,mac地址和
POSIX UID/GID - 版本3:基于MD5哈希算法
- 版本4:基于随机数
- 版本5:基于SHA-1哈希算法
格式为:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个x是一个十六进制数字。例如:8ad85109-fa53-44f4-8719-e49821c718fc。
优缺点
优点是代码简单,性能比较好,缺点是:uuid没有排序,无法保证按序递增;其次uuid比较长,存储数据库占用空间比较大,不利于检索和排序。
go的依赖包
package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
u1 := uuid.Must(uuid.NewV4()).String()
fmt.Printf("UUIDv4: ", u1)
// NewV4用来返回一个随机生成的UUID,以及生成过程中遇到的错误
// Must将返回结果为(UUID, error)类型的值进行包裹,如果error非nil,程序会panic。在生产环境下,不建议使用。
// String会将UUID类型转化成string类型
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Println("failed to parse uuid: ", err)
return
}
fmt.Println("successfully parsed:", u2)
// FromString会解析字符串成uuid
}
// func Must(u UUID, err error) {
// if err != nil {
// panic(err)
// }
// return u
// }
}
使用数据库id
在分布式系统中,可以用DB proxy请求不同的分库,每个分库设置不同的初始值,步长和分库数量相等。例如:有三个数据库,db1、db2和db3。db1起始值为1,db2起始值为2,db3起始值为3。步长为数据库个数3,那么到时候db1生成的id是1,4,7,db2生成的id是2,4,8,db3生成的为3,6,9等。
优缺点
优点是:实现简单;id有序,对排序有利。缺点是:比较依赖数据库,如果数据库挂掉,服务将变得不可用。
使用twitter的snowflake算法
snowflake生成的id一共分四部分:
- 第一部分:占用1bit,值始终为0,没有实际作用
- 第二部分:时间戳,占用41bit,精确到毫秒。
- 第三部分:工作机器id,占用10bit。最多容纳1024个节点。
- 第四部分:占用12bit,这个值在同一毫秒,同一节点上从0开始增加。
因此,snowflake算法在同一毫秒内最多产生的id数量:1024*4096=4194304
优缺点
优点是:生成id不依赖db,完全在内存生成,高性能、高可用;其次id递增,后续插入索引数性能比较好。缺点是:依赖于系统时钟的一致性,如果某台机器的系统时钟有问题,可能造成id冲突。
依赖包
package main
import (
"fmt"
"github.com/bwmarrin/snowflake"
)
func main() {
node, err := snowflake.NewNode(1)
if err != nil {
fmt.Println(err)
return
}
id := node.Generate().String()
fmt.Println("id is:", id)
// NewNode创建并返回一个新的snowflake节点,正如前面文章谈到,它是有范围的。在0~1023。
// func NewNode(node int64) (*Node, error) {
// mu.Lock()
// ...
// if n.node < 0 || n.node > n.nodeMax {
// return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
// }
// }
// Generate会生成并返回一个唯一的snowflake ID,为了保证其唯一性,你需要保证你的系统的时间要精确
// 生成的ID上有多个类型转化的接口,例如:String(),Int64()等
}
// id is: 1164423864051044352
本文探讨了在Go分布式集群中生成全局唯一ID的三种方法:使用UUID、数据库ID和Twitter的Snowflake算法。UUID提供了一种简单但长度较长的唯一标识,而数据库ID则能保证有序性但依赖数据库。Snowflake算法在不依赖数据库的情况下,能生成高性能、递增的ID,但需要关注系统时钟一致性。
966

被折叠的 条评论
为什么被折叠?



