昨晚用 Golang 写了个 ID 生成服务,分享给大家 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
owenliang
V2EX    Go 编程语言

昨晚用 Golang 写了个 ID 生成服务,分享给大家

  •  
  •   owenliang
    owenliang 2017-11-19 11:11:33 +08:00 5190 次点击
    这是一个创建于 2933 天前的主题,其中的信息可能已经有所发展或是发生改变。

    go-id-alloc

    Golang+Mysql 实现的分布式 ID 生成服务

    特性

    • 高性能:分配 ID 只访问内存
    • 分布式:横向扩展,理论无上限
    • 高可靠:Mysql 持久化,故障恢复快
    • 唯一性:生成 64 位整形,整体递增,永不重复
    • 易用性:可自定义 ID 起始位置,对外 HTTP 服务
    • 可运维性:提供健康检查接口,通过负载均衡自动摘除故障节点

    地址: https://github.com/owenliang/go-id-alloc

    第 1 条附言    2017-11-21 13:28:35 +08:00
    整理成博客,供大家理解: https://yuerblog.cc/2017/11/21/golang-id-alloc/
    36 条回复    2018-01-02 19:29:48 +08:00
    GjriFeu
        1
    GjriFeu  
       2017-11-19 11:31:44 +08:00
    唯一性:生成 64 位整形,整体递增,永不重复 太长
    owenliang
        2
    owenliang  
    OP
       2017-11-19 11:33:50 +08:00 via Android
    @GjriFeu
    twm
        3
    twm  
       2017-11-19 11:58:48 +08:00 via iPhone
    实际情况中来讲不递增 id 会好一些
    owenliang
        4
    owenliang  
    OP
       2017-11-19 12:11:05 +08:00 via Android
    @twm 按业务规则生成会好一些
    winglight2016
        5
    winglight2016  
       2017-11-19 12:47:03 +08:00
    @owenliang id 最好不要带业务规则,这是 DB schema 的设计原则之一
    owenliang
        6
    owenliang  
    OP
       2017-11-19 12:49:27 +08:00 via Android
    @winglight2016 谁的原则
    rockuw
        7
    rockuw  
       2017-11-19 13:09:53 +08:00 via iPhone
    > 高性能:分配 ID 只访问内存

    多个服务器怎么保证递增?
    owenliang
        8
    owenliang  
    OP
       2017-11-19 13:25:06 +08:00 via Android
    @rockuw 看代码喽
    rockuw
        9
    rockuw  
       2017-11-19 13:44:19 +08:00 via iPhone
    分布式,只访问内存,还能保证严格递增,图灵奖级别的成就啊。
    owenliang
        10
    owenliang  
    OP
       2017-11-19 13:47:28 +08:00 via Android
    @rockuw 不是严格。。我的措辞是整体递增,哈哈
    hilow
        11
    hilow  
       2017-11-19 14:26:46 +08:00 via Android
    用 redis 的 increment 生成 id 比这个 mysql 方便吧?
    pynix
        12
    pynix  
       2017-11-19 14:31:37 +08:00 via iPhone
    直接用 uuid,自增 id 最麻烦的就是可猜测。。。。
    notreami
        13
    notreami  
       2017-11-19 15:21:26 +08:00
    SnowFlake
    notreami
        14
    notreami  
       2017-11-19 15:23:58 +08:00
    理论无上限,永不重复
    就这两条,我能喷死你。。。
    troywinter
        15
    troywinter  
       2017-11-19 15:34:03 +08:00
    楼上正解,现阶段 twitter snowflake 算法算是最为可用的方案。。。
    owenliang
        16
    owenliang  
    OP
       2017-11-19 15:58:42 +08:00
    @notreami 我就很好奇你能喷出啥。。
    owenliang
        17
    owenliang  
    OP
       2017-11-19 15:58:58 +08:00
    @troywinter snowflake 还需要分享给大家么?
    geelaw
        18
    geelaw  
       2017-11-19 16:32:07 +08:00
    @owenliang 编码长度是有限的,只要执行足够多次就会出现重复或者程序不正常。

    用带有硬件信息的 GUID 算法就好了啊,这样不同电脑生成的就会不同了。
    owenliang
        19
    owenliang  
    OP
       2017-11-19 16:41:30 +08:00 via Android   1
    鉴于不同意见较多,不再一一回复大家,关于分布式 ID 方案优劣势参考: https://tech.meituan.com/MT_Leaf.html。
    genesislive
        20
    genesislive  
       2017-11-19 17:43:05 +08:00
    @owenliang 链接多了个“。”
    myself659410
        21
    a href="/member/myself659410" class="dark">myself659410  
       2017-11-19 21:05:47 +08:00
    肯定楼主的动手出代码
    都用 golang 还再加上 mysql 就为了分布式 uuid 实现起来觉得有点重了 依赖了 mysql,考虑到就帮,那 mysql 高可用也需要保证了吧
    Chingim
        22
    Chingim  
       2017-11-19 21:38:21 +08:00 via Android
    只能有 2^64 个 id 吧,永不重复有点过了
    owenliang
        23
    owenliang  
    OP
       2017-11-19 21:48:00 +08:00 via Android
    @Chingim 很有道理
    owenliang
        24
    owenliang  
    OP
       2017-11-19 21:52:36 +08:00 via Android
    @myself659410 对 云或者公司都有能力提供高可用 mysql
    ihuotui
        25
    ihuotui  
       2017-11-20 00:31:12 +08:00 via iPhone
    有序 id 还是有用的
    swulling
        26
    swulling  
       2017-11-20 00:49:11 +08:00 via iPhone
    snowflake 加原子钟,直接硬件解决时间问题

    便宜的原子钟才几百块
    wowowo1
        27
    wowowo1  
       2017-11-20 02:49:50 +08:00
    看了下代码,仿佛核心是先分区( segments ),仿佛也可称为分片,然后根据每个分片根据自己的分区信息自己内部进行 ID 递增。


    ```
    func (alloc *Alloc)NextId() (int64, error) {
    alloc.mutex.Lock()
    defer alloc.mutex.Unlock()

    if len(alloc.segments) > 0 {
    id := alloc.segments[0].left + alloc.segments[0].offset
    alloc.segments[0].offset++
    if id + 1 >= alloc.segments[0].right {
    alloc.segments = append(alloc.segments[:0], alloc.segments[1:]...)
    }
    return id, nil
    } else {
    return 0, errors.New("no more id")
    }
    }
    ```

    套用日本中二片里面自吹的话,最简单是 ID 生成器,最难也是 ID 生成器。

    如果我理解没错的话,
    你这套代码只能保证某个分区内递增,不能保证所有分区一起递增。
    每次请求不能落盘,不能记录已分配的 ID,或许可以采用异步解决,但是遇到灾难性故障基本会出现重复的情况。
    64 位整形仍然不能保证不重复。

    目前来看,UUID 中 snowflake 才是终极方案,自增 ID 仍然数 TIDB 那套比较靠谱,虽然他不能保证连续,但是至少自增。
    wowowo1
        28
    wowowo1  
       2017-11-20 02:52:23 +08:00
    而且,mutex.lock 和 unlock 中间代码行数比较多,单个分片可能有性能问题。go 语言是否可以用 atomic.incr 那一套逻辑解决。

    我只是稍微看了点代码,如有理解错误请提。
    owenliang
        29
    owenliang  
    OP
       2017-11-20 14:22:45 +08:00
    @wowowo1 你理解错了,再看看代码吧。
    ztao8607
        30
    ztao8607  
       2017-11-20 16:30:05 +08:00
    @owenliang 问个问题,都记录在内存中,有容灾处理么?分布式节点中,多个节点 down 后,如何解决脑裂问题呢?
    zkeeper
        31
    zkeeper  
       2017-12-03 07:24:54 +08:00 via iPhone
    @owenliang 人家仔细看了代码,而且贴出来了自己的分析,即使你觉得错,多写两句告诉别人具体哪里你觉得有问题才是讨论的态度吧?什么都不说直接让人再看代码?别人估计不会再看了
    owenliang
        32
    owenliang  
    OP
       2017-12-03 11:47:26 +08:00 via Android
    @zkeeper 看不看与我何干?感兴趣自己看,还有管闲事的,真是笑尿了
    zkeeper
        33
    zkeeper  
       2017-12-03 21:06:51 +08:00 via iPhone
    @owenliang 就你这个态度,真没必要把你的什么项目贴出来,指望别人不由分说就一脸膜拜交口称赞?你自嗨去吧
    zkeeper
        34
    zkeeper  
       2017-12-03 21:07:35 +08:00 via iPhone
    @zkeeper 拉黑
    wowowo1
        35
    wowowo1  
       2017-12-14 18:02:49 +08:00
    @zkeeper 蛤蛤蛤,没必要的。

    至于态度,也还好吧。

    但是第二天 astaxie 发了每日链接,有他这个 ID 生成器的设计的文章,感觉还好。

    他自己也贴在一楼了。

    毕竟有产出,有益于社会。

    不用苛求太多。

    我要是好不容易写个东西然后被楼上这么喷,我估计我也会毛的。
    iceheart
        36
    iceheart  
       2018-01-02 19:29:48 +08:00 via Android
    1024
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1041 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 17:44 PVG 01:44 LAX 09:44 JFK 12:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86