1、背景
在分布式系统中,数据需要由消息唯一标识,以标识数据在系统中的唯一性。该标识通常用作数据库的主键,innodb引擎将使用主键id来保留集群索引(物理排序按该字段排序)。
而数据库的自增id不能实现分布式模式下的自增,只能实现左单表的自增,这就需要统一的id生成器来实现id的生成。基本要求:全局唯一、单调递增(聚集索引)、信息安全(没有id可以避免被抓取)。
2、程序
方案一:数据库自增ID(AUTO_INCREMENT),维护一个序列表,需要插入新数据时从序列中取出next_id,然后等待下一次使用。
方案二:用redis或zookeeper保存id生成器的数据本质上和方案一一样,依赖第三方的服务,复杂度高。
方案三:类似Twitter的雪花算法,为每台机器提供唯一标识符,id机器标识符自动添加到时间戳中,这样ID生成算法完全不依赖第三方,没有网络调用,效率高。
3. Snowflake algorithm
第一,不需要。在二进制中,1的最高位是负数,但是我们生成的id一般是整数,所以这个最高位总是0。
41位,用来记录时间戳(毫秒),41位可以。。2411个数字,也就是说41位可以。。2411毫秒的值,换算成单位年就是(2 411)/(1000606024365)=69年。
10位数字,用于记录工作机器的id。可以部署在210=1024个节点中,包括5位的datacenterId和5位的worker id,5位可以表示的最大正整数是2 ^ 51=31。
也就是32个数字,比如0,1,2,3,31,可以用来表示不同的datecenterId或workerId。
12位,序列号,用于记录同一毫秒内生成的不同id。12位可以表示的最大正整数是2121=4095,即0、1、2、3、可以用4095。
表示同一台机器在同一时间段(毫秒)内生成的4096个ID序列号
4.单点批量ID生成服务
分布式id的难点在于很难保证绝对定时。为了保证绝对定时,我们只能使用单点服务,使用本地时钟来保证“绝对定时”。在第一种方案中,可以优化方案的缺点,每次取出的next_id 10,
这样每次取出10个id,分发后再取出10个id,这样单点数据库的压力减少了1/10,单点故障问题可以通过备用数据库和keepalive来实现。
如果服务挂机重启得到next_id 10的数据,可能会有漏洞,但问题不大。
4. Goran realizes snowflake. github. com/bwmarrin/Snowflake is a fairly lightweight snowflake to realize.
package mainimport ('fmt''github.com/bwmarrin/snowflake''os')func main() {n, err :=snowflake.NewNode(1)if err !=nil {println(err)os.Exit(1)}id :=n.Generate()//Print out the ID in a few different ways.fmt.Printf('Int64 ID: %d\n', id)fmt.Printf('String ID: %s\n', id)fmt.Printf('Base2 ID: %s\n', id.Base2())fmt.Printf('Base64 ID: %s\n', id.Base64())//Print out the ID's timestampfmt.Printf('ID Time : %d\n', id.Time())//Print out the ID's node numberfmt.Printf('ID Node : %d\n', id.Node())//Print out the ID's sequence numberfmt.Printf('ID Step : %d\n', id.Step())//Generate and print, all in one.fmt.Printf('ID: %d\n', n.Generate().Int64())}
标题:实施制定一系列具有全局性意义的(大众id系列有几款车)
链接:https://www.52hkw.com/news/rj/62899.html
版权:文章转载自网络,如有侵权,请联系删除!