分布式学习十三:实现全局唯一id命名
温馨提示:
本文最后更新于 2022年03月26日,已超过 1,094 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
全局唯一id
在单体服务中,我们可以通过数据库的自增id去实现唯一id命名,
但是在分布式服务中,分库分表之后,就无法直接使用自增id了,数据库只能保证当前表的id唯一,
这个时候我们就需要通过其他方式去生成全局唯一id,例如UUID
UUID
uuid通俗来讲,就是针对于 每个机器/机器的线程/当前的时间戳/伪随机数 作为生成凭据,能保证每个机器下的每个线程都会生成不同的id
生成的数据大概为一串无规律的数字/一串无规律的字符串 "2145562313212","e70f1357-f260-46ff-a32d-53a086c57ade"
生成的结果由不同的算法而发生改变,但是算法的原理依据都是如上
uuid的好处在于生成速度快,重复概率低(有可能重复,但是这辈子重复的概率接近0,可以不考虑)
缺点是生成的字符串没有明确的意义,甚至没有排序,另外就是数据过长,无法直接使用
zookeeper实现全局唯一id
通过zookeeper的有序节点类型,可以很方便的实现全局唯一id
package main
import (
"errors"
"fmt"
"github.com/go-zookeeper/zk"
"strings"
"time"
)
func main() {
conn, _, err := zk.Connect([]string{"127.0.0.1:10001"}, time.Second)
if err != nil {
panic(err)
}
idPath := "/app1/tableName1/id/"
createPath(conn, idPath)
id,err := getGlobalID(conn, idPath)
if err!=nil {
fmt.Printf("%v \n",err)
return
}
fmt.Printf("Global ID: %s",id)
}
func getGlobalID(conn *zk.Conn, idPath string) (id string,err error) {
id, err = conn.Create(idPath+"a_", []byte{}, zk.FlagSequence, zk.WorldACL(zk.PermAll))
if err != nil {
return id,errors.New(err.Error())
}
fmt.Printf("Global ID:%s\n", id)
return id,nil
}
func createPath(conn *zk.Conn, path string) (err error) {
strArr := strings.Split(path, "/")
var node string
for _, str := range strArr {
if str == "" {
continue
}
node = node + "/" + str
exists, _, err := conn.Exists(node)
if err != nil {
return errors.New(err.Error())
}
if exists {
continue
} else {
_, err = conn.Create(node, []byte{}, 0, zk.WorldACL(zk.PermAll))
if err != nil {
return errors.New(err.Error())
}
}
}
return err
}
将输出:
通过zookeeper生成的id优点是 有序的,可以很清楚的了解到具体的数据值(你还可以把a_改为日期),这样还可以清楚这个id的创建时间等
缺点是zookeeper生成节点很慢(需要同步到其他集群节点),另外如果超过int最大值,则需要重新使用个新的父节点生成
正文到此结束
- 本文标签: 分布式 编程语言
- 本文链接: https://www.php20.cn/article/353
- 版权声明: 本文由仙士可原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权