雪花算法 Snowflake & Sonyflake

简介:

唯一ID算法Snowflake相信大家都不墨生,他是Twitter公司提出来的算法。非常广泛的应用在各种业务系统里。也因为Snowflake的灵活性和缺点,对他的改造层出不穷,比百度的UidGenerator、美团的Leaf、索尼的Sonyflake等等。这篇帖子主要是讲一下原生的Snowflake算法、缺点及改造方案,并分析索尼的Sonyflake源码对原生Snowflake的改造,

原生Snowflake

原生Snowflake算法使用一个64 bit的整形数据,根据当前的时间来生成ID。
原生Snowflake结构如下:

  • 因为最高位是标识位,为1表示为负数,所以最高位不使用。
  • 41bit 保存时间戳,精确到毫秒。也就是说最大可使用的年限是69年。
  • 10bit 的机器位,能部属在1024台机器节点来生成ID。
  • 12bit 的序列号,一毫秒最大生成唯一ID的数量为4096个。

原生的Snowflake算法是完全依赖于时间的,如果有时钟回拨的情况发生,会生成重复的ID,市场上的解决方案也是非常多的:

  • 最简单的方案,就是关闭生成唯一ID机器的时间同步。
  • 使用阿里云的的时间服务器进行同步,2017年1月1日的闰秒调整,阿里云服务器NTP系统24小时“消化”闰秒,完美解决了问题。
  • 如果发现有时钟回拨,时间很短比如5毫秒,就等待,然后再生成。或者就直接报错,交给业务层去处理。
  • 可以找2bit位作为时钟回拨位,发现有时钟回拨就将回拨位加1,达到最大位后再从0开始进行循环。

个人比较推荐的是最后一个方案

找2bit位作为时钟回拨位,发现有时钟回拨就将回拨位加1,达到最大位后再从0开始进行循环。

比如下图这样,从机器位上,均出来2位做回拨位:

Sonyflake

Snowflake算法是相当灵活的,我们可以根据自己的业务需要,对63 bit的的各个部分进行增减。索尼公司的Sonyflake对原生的Snowflake进行改进,重新分配了各部分的bit位:

  • 39bit 来保存时间戳,与原生的Snowflake不同的地方是,Sonyflake是以10毫秒为单位来保存时间的。这样的话,可以使用的年限为 174年Snowflake长太多了。
const sonyflakeTimeUnit = 1e7 // nsec, i.e. 10 msec
func toSonyflakeTime(t time.Time) int64 {
    return t.UTC().UnixNano() / sonyflakeTimeUnit
}
func currentElapsedTime(startTime int64) int64 {
    return toSonyflakeTime(time.Now()) - startTime
}
  • 8bit 做为序列号,每10毫最大生成256个,1秒最多生成25600个,比原生的Snowflake少好多,如果感觉不够用,目前的解决方案是跑多个实例为生成同一业务的ID来弥补。
  • 16bit 做为机器号,默认的是当前机器的私有IP的最后两位
sf.machineID, err = lower16BitPrivateIP()
func lower16BitPrivateIP() (uint16, error) {
    ip, err := privateIPv4()
    if err != nil {
        return 0, err
    }
    return uint16(ip[2])<<8 + uint16(ip[3]), nil
}

对于时间回拨的问题Sonyflake简单暴力,就是直接等待 :

func (sf *Sonyflake) NextID() (uint64, error) {
    const maskSequence = uint16(1<<BitLenSequence - 1)
    sf.mutex.Lock()
    defer sf.mutex.Unlock()
    current := currentElapsedTime(sf.startTime)
    if sf.elapsedTime < current {
        sf.elapsedTime = current
        sf.sequence = 0
    } else { // sf.elapsedTime >= current
        sf.sequence = (sf.sequence + 1) & maskSequence
        if sf.sequence == 0 {
            sf.elapsedTime++
            overtime := sf.elapsedTime - current
            time.Sleep(sleepTime((overtime)))
        }
    }    
    return sf.toID()
}
目录
相关文章
|
1月前
|
算法 Java
雪花算法生成id
雪花算法生成id
|
2月前
|
存储 算法 数据库
C++ “雪花算法“原理
C++ “雪花算法“原理
|
7月前
|
算法 安全 NoSQL
雪花算法的实现原理
一位工作4年的小伙伴,去某东面试时被问到这样一道题,说请你简述一下雪花算法的实现原理。屏幕前的小伙伴,如果你遇到这个问题,你会怎么回答?
128 0
|
8月前
|
XML 算法 Java
基于雪花算法解决Mybatis-Plus id主键生成的问题
基于雪花算法解决Mybatis-Plus id主键生成的问题
|
26天前
|
缓存 算法 关系型数据库
深度思考:雪花算法snowflake分布式id生成原理详解
雪花算法snowflake是一种优秀的分布式ID生成方案,其优点突出:它能生成全局唯一且递增的ID,确保了数据的一致性和准确性;同时,该算法灵活性强,可自定义各部分bit位,满足不同业务场景的需求;此外,雪花算法生成ID的速度快,效率高,能有效应对高并发场景,是分布式系统中不可或缺的组件。
深度思考:雪花算法snowflake分布式id生成原理详解
|
1月前
|
算法 数据库 索引
什么是雪花算法?啥原理?
什么是雪花算法?啥原理?
34 0
什么是雪花算法?啥原理?
|
1月前
|
算法 Java 数据中心
分布式ID生成系统之雪花算法详解
在当今的云计算和微服务架构盛行的时代,分布式系统已成为软件开发的重要组成部分。随着系统规模的扩大和业务的复杂化,对数据一致性和唯一性的要求也越来越高,尤其是在全局唯一标识符(ID)的生成上。因此,分布式ID生成系统应运而生,成为保证数据唯一性和提高系统可扩展性的关键技术之一。雪花算法(Snowflake)是Twitter开源的一种算法,用于生成64位的全局唯一ID,非常适用于分布式系统中生成唯一标识符。下面我们将深入探讨雪花算法的原理、结构和实现方式。
98 2
 分布式ID生成系统之雪花算法详解
|
2月前
|
算法
雪花算法id生成util
雪花算法id生成util
17 0
|
3月前
|
存储 算法 NoSQL
细说雪花算法
细说雪花算法
|
4月前
|
算法
雪花算法id生成器
雪花算法id生成器
63 0