分布式id生成器

分布式id生成

一、 MySQL自增ID

二、Twitter的snowflake算法

2.1 snowflake的id生成

在这里插入图片描述

首先确定我们的数值是64位,int64类型,被划分为五部分:

  • 第一个bit位不用,代表符号位
  • 用41位来表示收到请求时的时间戳,单位为毫秒
  • 5位数表示数据中心的ID
  • 再5位数表示机器的实例ID
  • 最后是12位的循环自增ID,到达 1111 1111 1111 后会归0
    这样的机制可以支持我们在同一台机器上,同一毫秒内产生2^12 = 4096条消息,一秒则可以生成409.6w条消息,从值域上来讲完全够用。
    数据中心加上实例ID共10位,可以支持我们每个数据中心部署32台机器,32*32 = 1024 总共1024台实例。
    表示timestamp的41位,可以支持使用69年,这里的timestamp可以当做基于某个时间的增量,而不是从1970年开始计
2.2 worker_id分配

timestampdatacenter_idworker_idmermaid sequenceDiagram_id这四个字段中,timestampmermaid sequenceDiagram_id是由程序在运行期生成的。但是 datacenter_idworker_id需要我们在部署阶段就能够获取得到,并且一旦程序启动之后就无法修改(否则会导致生成的id会有冲突)
一般针对于不同的数据中心的机器,会提供对应的获取数据中心id的API,而worker_id是我们逻辑给机器分配的一个id。

  • 使用能够提供这种自增id功能的工具来支持
    比如MySQL,但是使用MySQL的同时相当于也产生了依赖,依赖越多,服务的可运维性就越差。
  • 直接定义好worker_id,写入到worker的配置中,上线时由部署脚本完成worker_id字段的替换
2.3 开源实例
2.3.1 snowflake

github.com/bwmarrin/snowflake
在这里插入图片描述

这是一个轻量化的snowflake的Go实现,使用上比较简单:

package main 

import ( 
    "fmt" 
    "os" 
    "github.com/bwmarrin/snowflake" 
)

func main() { 
    n, err := snowflake.NewNode(1) 
    if err != nil { 
        println(err) 
        os.Exit(1) 
    }
    for i := 0; i < 3; i++ { 
        id := n.Generate() 
        fmt.Println("id", id) 
        fmt.Println( "node: ", id.Node(), "step: ", id.Step(), "time: ", id.Time(), "\n", ) 
    } 
}

这个库也预留了一些可定制的字段:

Epoch int64 = 1288834974657
// Number of bits to use for Node
// Remember, you have a total 22 bits to share between Node/Step
NodeBits uint8 = 10
// Number of bits to use for Step
// Remember, you have a total 22 bits to share between Node/Step
StepBits uint8 = 12

Epoch 就是本节开头讲的起始时间, NodeBits 指的是机器编号的位长, StepBits 指的是自增序列的位长

2.3.2 sonyflake

sonyflake基本思路和snowflake差不多,不过位分配上稍有不同
在这里插入图片描述

这里的时间只用了39个bit,但时间的单位变成了10ms,所以理论上比41位表示的时间还要久(2^39*10/1000/86400/365≈174年)
Sequence ID 和之前的定义一致, Machine ID其实就是节点ID(nodeID),sonyflake与众不同的地方在于其启动阶段的配置参数:

func NewSonyflake(st Settings) *Sonyflake

Settings数据结构如下:

type Settings struct {
StartTime time.Time
MachineID func() (uint16, error)
CheckMachineID func(uint16) bool
}
  • StartTime选项和snowflake的Epoch差不多,如果不设置的话默认从2014-09-01 00:00:00 +0000 UTC开始
  • MachineID可以由用户自定义的函数,如果用户不定义的话,会默认将本机IP的低16位作为MachineID
  • CheckMachineID是由用户提供的检查MachineID是否冲突的函数。如果有redis集群,可以很轻松地用set来检查冲突
127.0.0.1:6379> SADD machine_id 10086
(integer) 1 
127.0.0.1:6379> SADD machine_id 10086
(integer) 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值