zoukankan      html  css  js  c++  java
  • snowflake 雪花算法 分布式实现全局id生成

    snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。

    这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间等。

    其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号,最后还有一个符号位,永远是0。

    比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示:

    整个结构是64位,所以我们在Java中可以使用long来进行存储。 该算法实现基本就是二进制操作,单机每秒内理论上最多可以生成1024*(2^12),也就是409.6万个ID(1024 X 4096 = 4194304)

    0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 

        1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
        41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
        10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId。10-bit机器可以分别表示1024台机器。如果我们对IDC划分有需求,还可以将10-bit分5-bit给IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,可以根据自身需求定义。
       12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号。12个自增序列号可以表示2^12个ID,理论上snowflake方案的QPS约为409.6w/s,这种分配方式可以保证在任何一个IDC的任何一台机器在任意毫秒内生成的ID都是不同的。
       加起来刚好64位,为一个Long型。

    优点:

      整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。

    • 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
    • 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
    • 可以根据自身业务特性分配bit位,非常灵活

    缺点:

    • 强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

    Go实现

      sonyflake

     

    下载 

    go get github.com/sony/sonyflake
    

    Demo

    package main
    
    import (
    	"fmt"
    	"github.com/sony/sonyflake"
    )
    
    var (
    	LSonyFlake *sonyflake.Sonyflake
    	machineId  uint16 // 真正的分布式环境下必须zookeeper或etcd中获取
    )
    
    func getMachineID() (uint16, error) {
    	return machineId, nil
    }
    func Init(mid uint16) (err error) {
    	machineId = mid
    	st := sonyflake.Settings{}
    	st.MachineID = getMachineID
    	LSonyFlake = sonyflake.NewSonyflake(st)
    	return
    }
    func GetID()(id uint64,err error)  {
    	if LSonyFlake == nil{
    		err = fmt.Errorf("No Init
    ")
    		return
    	}
    	return LSonyFlake.NextID()
    }
    
    func main()  {
    	Init(0)
    	id,err:=GetID()
    	if err != nil {
    		fmt.Println(err)
    	}
    	fmt.Println(id)
    }
    

      

     

     

     

     

    Songzhibin
  • 相关阅读:
    Delphi XE4 FireMonkey 开发 IOS APP 发布到 AppStore 最后一步.
    Native iOS Control Delphi XE4
    Delphi XE4 iAD Framework 支持.
    using IOS API with Delphi XE4
    GoF23种设计模式之行为型模式之命令模式
    Android青翼蝠王之ContentProvider
    Android白眉鹰王之BroadcastReceiver
    Android倚天剑之Notification之亮剑IOS
    Android紫衫龙王之Activity
    GoF23种设计模式之行为型模式之访问者模式
  • 原文地址:https://www.cnblogs.com/binHome/p/12072433.html
Copyright © 2011-2022 走看看