V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tctc4869
V2EX  ›  程序员

有什么基于短数字的唯一 id 生成器的实现?

  •  
  •   tctc4869 · 193 天前 · 2658 次点击
    这是一个创建于 193 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我目前看到的雪花算法生成的 id 基本都是长整型,有没有短数字唯一 id 生成,直接生成 int,比如 b 站 av 号之类的。既然是短数字的唯一 id 生成,那就不会应用到类似“订单 id 生成”等诸如 1 秒内生成几百几千个 id 的场景中,

    希望能在服务端内部生成,不用必须依赖数据库来生成 id,能控制长度(比如长度固定,或者数字长度不低于几位不高于几位之类的)

    有没有序无所谓,当然如果能选择无序模式或有序模式的话,那最好不过了。

    那么有哪些实现的呢,或者哪些工具类有这些功能了

    22 条回复    2021-07-08 11:21:48 +08:00
    tabris17
        1
    tabris17  
       193 天前
    有啊,数据库自增字段,或者其他全局计数器
    retanoj
        2
    retanoj  
       193 天前
    时间戳够用么?
    wellsc
        3
    wellsc  
       193 天前
    @tabris17 自增性能不太行
    rioshikelong121
        4
    rioshikelong121  
       193 天前
    你搜 shortid 就出来了
    sunjiayao
        5
    sunjiayao  
       193 天前
    @wellsc mysql 自增主键性能还是不错的
    liaohongxing
        6
    liaohongxing  
       193 天前
    最类似下面这个,但还是偏长
    https://gitee.com/yitter/idgenerator
    tctc4869
        7
    tctc4869  
    OP
       193 天前
    @liaohongxing 谢谢,js 的话,数字很长就得把数字转成字符串
    qwe520liao
        8
    qwe520liao  
       193 天前
    给一条数据赋值 ID 一般代表这条数据具有生命周期,也就是实体,随机性的 ID 生成优点是速度快,但是一般都比较长,短且紧凑的 ID 一般需要有一个单独的地方进行维护管理,因为随机会有重复的风险,毕竟这个状态我们需要持久化。

    说一下我们之前做过的一个 ID 生成服务:不同实体的 ID,都是一个隔离开的空间范围,这个递增的空间范围需要由一个独立的服务来进行维护和管理。传入实体类型,也就是一个 Key 绑定一个 ID 的当前值,并告诉这个服务我需要多大范围的 ID,可以设计一个接口:

    (start, end) nextIdRange(key, size)

    其中 key (实体标识)和 size (获取多少个)为参数,用于获取一段 ID 范围,返回值 start 为起始值,end 为结束值。
    客户端获得以后就可以在这个范围内进行本地递增。需要注意的是,这个接口需要保证原子性,也就是并发的时候不会返回相同的数据,每一次调用都将会导致内部维护的当前 ID 值发生变化。

    客户端如果生成 ID 频繁,可以考虑优化为当剩余的 ID 快要耗尽时,另外起一个线程去预取下一批次的 ID 段(假设是跨网络的服务调用,ID 生成服务为一个独立的进程),保证 ID 生成不会受到获取 ID 这个操作的延迟影响,设置为多少合适则取决于实际的情况。
    liaohongxing
        9
    liaohongxing  
       193 天前
    @tctc4869 你注意看文档,我说的很长是指和 B 站 BV 相比 ,他这个 避免了 js 的最大值 ,仔细看下 。
    zhaokun
        10
    zhaokun  
       193 天前
    @tctc4869 前端当成字符串处理有啥问题呢?
    oddcc
        11
    oddcc  
       193 天前
    还是要依赖 id 生成的服务的
    简单的设计可以考虑提前生成 id,放到库里
    服务端用的时候一批一批的取,只要取出来就认为是用掉了
    整体设计比较简单,好理解,也没有过多的依赖
    jslang
        12
    jslang  
       193 天前
    自己生成呗,毫秒时间戳+2~3 随机数
    或者 21-0707-剩余(毫秒 /秒)+几位随机数
    kop1989
        13
    kop1989  
       193 天前
    最简单的就是时间相关+随机。具体时间精度取多少,随机又取多长,要看你的目标压力而定。
    macttt
        14
    macttt  
       193 天前
    增加一个服务实例分配号段吧,每个服务存一个 id 池譬如 1~1000,用完了之后到发号服务里再拿一段号段,以此类推。用发号服务来保证 id 不重复。如果需要标识实例编号的话,得在短 id 头部预留几位保存实例编号。
    zachlhb
        15
    zachlhb  
       193 天前 via iPhone
    short uuid 就可以
    sakishum
        16
    sakishum  
       193 天前
    Snowflake 雪花?
    libook
        17
    libook  
       193 天前
    如果不担心被遍历的话,可以数据库自增。

    如果担心被遍历的话就用时间戳+随机数字再 HASH,只不过越短碰撞可能性越大。

    当然也可以数据库自增再加随机量的增量,然后再做个风控监测,如果某客户端短时间内访问了大量的无效 ID 就封掉。

    缩短 ID 的最重要的一步是做进制转换。
    自增是十进制,HASH 是十六进制,如果你大小写不敏感就一律转换成 36 进制,即 0-9a-z,如果大小写敏感就用 62 进制,0-9a-zA-Z,这个如果用 JS 的话可以直接 toString(进制数)。
    sighforever
        18
    sighforever  
       193 天前
    又短又唯一,不用数据库记录一下不可能啊,最少需要保存一个已用的数据范围
    mxT52CRuqR6o5
        19
    mxT52CRuqR6o5  
       193 天前
    把自增 id 用对称加密算法加密,就能获得随机(只要密钥不泄露对外就等于随机)不会碰撞的 id
    lix7
        20
    lix7  
       193 天前
    从服务上线起的毫秒时间戳 + IP 前后 16 位异或 + 两位随机数
    应该是足够用了,如果再有碰撞的话,就依赖于重试去处理了
    find456789
        21
    find456789  
       193 天前   ❤️ 2
    我知道有个 基于字母+数字 的 叫 hashid, 很多语言都支持
    sunmoon1983
        22
    sunmoon1983  
       193 天前
    不知道京东的订单号是怎么得出来的,很短,纯数字
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3376 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 05:09 · PVG 13:09 · LAX 21:09 · JFK 00:09
    ♥ Do have faith in what you're doing.