yitter / IdGenerator

💎多语言实现,高性能生成唯一数字ID。 💎优化的雪花算法(SnowFlake)——雪花漂移算法,在缩短ID长度的同时,具备极高瞬时并发处理能力(50W/0.1s)。 💎原生支持 C#/Java/Go/Rust/C/JavaScript/TypeScript/Python/Pascal 多语言,提供其它适用于其它语言的多线程安全调用动态库(FFI)。💎支持容器环境自动扩容(自动注册 WorkerId ),单机或分布式唯一IdGenerator。💎顶尖优化,超强效能。
MIT License
2.51k stars 363 forks source link

看了下go的代码用的加法返回geneid可能有bug #92

Open molixiaoge opened 7 months ago

molixiaoge commented 7 months ago

看到的源码是这样写的,使用加法返回拼接的位数

// CalcID .
func (m1 *SnowWorkerM1) CalcId(useTimeTick int64) int64 {
    result := int64(useTimeTick<<m1._TimestampShift) + int64(m1.WorkerId<<m1.SeqBitLength) + int64(m1._CurrentSeqNumber)
    m1._CurrentSeqNumber++
    return result
}

做了简单的测试代码,发现加和或的值不一样

func main() {
    var a int64 = 178438932798732984
    var b int64 = 318793718938921712

    fmt.Printf("a value %064b\n", a)
    fmt.Printf("b value %064b\n", b)
    aor := a | b
    aadd := a + b

    fmt.Printf("a|b value %064b\n", aor)
    fmt.Printf("a+b value %064b\n", aadd)
    fmt.Printf("|   %d\n ", aor)
    fmt.Printf("add %d\n ", aadd)

    if aor != aadd {
        fmt.Println("not equal")

    }

}

另外发现,go做左移的时候会有溢出的问题

    var workid int64 = 1234211
    fmt.Printf("%064b\n", workid)
    //0000000000000000000000000000000000000000000100101101010100100011

    id := workid << 53
    //左移53位应该是如下值 但是go运算似乎是直接用 workid*2^53次方导致溢出了
    //1010010001100000000000000000000000000000000000000000000000000000
    fmt.Println(id)
    //-6602277053725147136
    fmt.Printf("%064b", id)
    //-101101110100000000000000000000000000000000000000000000000000000
yitter commented 7 months ago

一般来说,加法和或的运算结果,确实可能不一样。 但是,在本算法满足条件:_TimestampShift = (WorkerIdBitLength + SeqBitLength) 时,加与或结果是一致的。 至于左移导致溢出的问题,这是理论上存在的,所以算法有“时长限制”,在时限范围内,不会溢出。 默认配置时限7.1万年,具体的,参考readme。

molixiaoge commented 7 months ago

好的,使用加法的目的是什么,比或更快么?