package nsqd

// the core algorithm here was borrowed from:
// Blake Mizerany's `noeqd` https://github.com/bmizerany/noeqd
// and indirectly:
// Twitter's `snowflake` https://github.com/twitter/snowflake

// only minor cleanup and changes to introduce a type, combine the concept
// of workerID + datacenterId into a single identifier, and modify the
// behavior when sequences rollover for our specific implementation needs

import (
    "encoding/hex"
    "errors"
    "time"
)

const (
    workerIDBits   = uint64(10)
    sequenceBits   = uint64(12)
    workerIDShift  = sequenceBits
    timestampShift = sequenceBits + workerIDBits
    sequenceMask   = int64(-1) ^ (int64(-1) << sequenceBits)

    // ( 2012-10-28 16:23:42 UTC ).UnixNano() >> 20
    twepoch = int64(1288834974288)
)

var ErrTimeBackwards = errors.New("time has gone backwards")
var ErrSequenceExpired = errors.New("sequence expired")
var ErrIDBackwards = errors.New("ID went backward")

type guid int64

type guidFactory struct {
    sequence      int64
    lastTimestamp int64
    lastID        guid
}

func (f *guidFactory) NewGUID(workerID int64) (guid, error) {
    // divide by 1048576, giving pseudo-milliseconds
    ts := time.Now().UnixNano() >> 20

    if ts < f.lastTimestamp {
        return 0, ErrTimeBackwards
    }

    if f.lastTimestamp == ts {
        f.sequence = (f.sequence + 1) & sequenceMask
        if f.sequence == 0 {
            return 0, ErrSequenceExpired
        }
    } else {
        f.sequence = 0
    }

    f.lastTimestamp = ts

    id := guid(((ts - twepoch) << timestampShift) |
        (workerID << workerIDShift) |
        f.sequence)

    if id <= f.lastID {
        return 0, ErrIDBackwards
    }

    f.lastID = id

    return id, nil
}

func (g guid) Hex() MessageID {
    var h MessageID
    var b [8]byte

    b[0] = byte(g >> 56)
    b[1] = byte(g >> 48)
    b[2] = byte(g >> 40)
    b[3] = byte(g >> 32)
    b[4] = byte(g >> 24)
    b[5] = byte(g >> 16)
    b[6] = byte(g >> 8)
    b[7] = byte(g)

    hex.Encode(h[:], b[:])
    return h
}

guid.go的更多相关文章

  1. UniqueIdentifier 数据类型 和 GUID 生成函数

    UniqueIdentifier 数据类型用于存储GUID的值,占用16Byte. SQL Server将UniqueIdentifier存储为16字节的二进制数值,Binary(16),按照特定的格 ...

  2. System.Guid ToString五中格式

    参考:https://msdn.microsoft.com/en-us/library/97af8hh4.aspx 测试代码: using System; using System.Collectio ...

  3. EF里Guid类型数据的自增长、时间戳和复杂类型的用法

    通过前两章Lodging和Destination类的演示,大家肯定基本了解Code First是怎么玩的了,本章继续演示一些很实用的东西.文章的开头提示下:提供的demo为了后面演示效果,前面代码有些 ...

  4. 为Guid数据类型的属性(property)赋值

    先来看看数据库表中的字段设计: 在数据库的数据类型为uniqueidentifier. 而在程序中对应的数据类型为GUID. property有get和set,也就是说能获取值也可以赋值.

  5. Guid的使用

    今天在公司做修改功能时,老大让使用部分更新,但是表中的主键是UNIQUEIDENTIFIER类型,它会在我们添加纪录时,默认生成一个unicode码, 但是我现在必须要将获取到的已经是string类型 ...

  6. GUID生成器

    这个GUID生成器是一个小巧的软件,属于笔者在空余时间开发的. http://pan.baidu.com/s/1sk6VGpn

  7. 使用Guid做主键和int做主键性能比较

    使用Guid做主键和int做主键性能比较 在数据库的设计中我们常常用Guid或int来做主键,根据所学的知识一直感觉int做主键效率要高,但没有做仔细的测试无法 说明道理.碰巧今天在数据库的优化过程中 ...

  8. 生成GUID唯一值的方法汇总(dotnet/javascript/sqlserver)

    一.在 .NET 中生成1.直接用.NET Framework 提供的 Guid() 函数,此种方法使用非常广泛.GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的任何两台计 ...

  9. SQLSERVER如何使用递增排序的GUID做主键

    场景: 产品表数据量较大想用Guid做表的主键,并在此字段上建立聚簇索引. 因为Guid是随机生成的,生成的值大小是不确定的,每次生成的数可能很大,也可能很小.这样会影响插入的效率 1.NEWSEQU ...

  10. COM 组件基础——GUID 和 接口

    一.前言 书接上回,话说在 doc(Word) 复合文件中,已经解决了保存 xls(Excel) 数据的问题了.那么,接下来又要解决另一个问题:当 WORD 程序读取复合文件,遇到了 xls 数据的时 ...

随机推荐

  1. ruby TkPackage can't find package BWidget 之解决办法

    一个特别短的ruby/tk代码: require 'tkextlib\iwidgets' require 'tkextlib\bwidget' x = 0 101.times {|i| x+=i} T ...

  2. FCL源码中数组类型的学习及排序函数Sort函数的分析

    Array 是所有数组的基类ArrayList 解决了所有Array 类的缺点    能动态扩容, 但是类型不安全的,而是会有装箱与拆箱的性能开销List<T> 则是解决了ArrayLis ...

  3. 3 sum closest

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  4. Ajax+jquery+jaso传输数据

    所谓的Ajax.这里我们讲二种方法  方法一:(微软有自带Ajax框架)  在Asp.net里微软有自己的Ajax框架.就是在页面后台.cs文件里引入 using System.Web.Service ...

  5. Bash的一些零星笔记

    1.变量带入操作符 在脚本中,使用变量前做检查是很重要的.通过代入操作符,可以实现这方面的功能.比如当变量未赋值时为变量赋默认值,以及更多内容: ${parameter:-默认为空}:当paramet ...

  6. 第四章:4.2MySQL 权限系统介绍

    4.2.1 权限系统简介 MySQL 的权限系统在实现上比较简单,相关权限信息主要存储在几个被称为granttables 的系统表中,即: mysql.User,mysql.db,mysql.Host ...

  7. Spring Boot开发MongoDB应用实践

    本文继续上一篇定时任务中提到的邮件服务,简单讲解Spring Boot中如何使用MongoDB进行应用开发. 上文中提到的这个简易邮件系统大致设计思路如下: 1.发送邮件支持同步和异步发送两种 2.邮 ...

  8. CSS布局之--各种居中

    居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明 ...

  9. js实现定时器,时间倒计时为0后停止

    <script type="text/javascript"> var orign_time = 1496706400; var leftTime = Date.par ...

  10. 落入绝地求生的Python神仙,实现绝地求生无后座!

    叙述 绝地求生已经出来那么久了,大家应该都晓得如今的游戏情形很是差 .特别在高端局,神仙满天飞 搞得很多人类玩家很是没有游戏体验! 由于绝地求生的火爆,繁衍出许多外挂流传于各个地方.飞机上.网吧内,各 ...