lg106
V2EX  ›  PHP

生成唯一字母 ID 求解

  •  
  •   lg106 · Jan 22, 2020 · 11631 views
    This topic created in 2312 days ago, the information mentioned may be changed or developed.

    有一个需求是不用数字作为用户 ID,要用英文字母

    我现在有三种解决方案

    第一种:用户注册时候,生成一个随机英文字符串,去查用户表,如果重复再重新生成,直到唯一。

    第二种:先生成一张字母 ID 表,每次用户从里面取,取了就标记为已用。

    第三种:用函数把用户数字 ID 转为字母 ID,但是转出来的 ID,两个相近的用户,字母 ID 太相似了。

    有什么更好的解决方案吗?

    53 replies    2020-01-24 22:45:24 +08:00
    Varobjs
        1
    Varobjs  
       Jan 22, 2020 via Android
    就是随机生成不唯一的用户名呗
    lg106
        2
    lg106  
    OP
       Jan 22, 2020
    @Varobjs 也可以这么说,用户 ID 要显示在外面,我们不想让别人看到我们的数字 ID,所以想用英文来代替,包括我们的文章 ID 也是要弄成英文 ID
    imlinhanchao
        3
    imlinhanchao  
       Jan 22, 2020
    @lg106 uuid 可否?
    whypool
        4
    whypool  
       Jan 22, 2020
    新增数据可以用 UUID,把横杠去掉就行,就是有点长
    用户名+时间戳+MD5 也能生成唯一 ID
    crypto 库也能生成唯一 ID
    jfcherng
        5
    jfcherng  
       Jan 22, 2020 via Android
    hashids
    jinhan13789991
        6
    jinhan13789991  
       Jan 22, 2020 via Android
    第一个人是 AAAAAAAA,第二个人是 AAAAAAAB,以此类推~ 变相的 26 进制自增
    eojessie
        7
    eojessie  
       Jan 22, 2020
    @jinhan13789991 这个容易被枚举了。。。。
    lg106
        8
    lg106  
    OP
       Jan 22, 2020
    @imlinhanchao 可能太长了
    otakustay
        9
    otakustay  
       Jan 22, 2020
    就用自增键然后 hash 一下呢
    lg106
        10
    lg106  
    OP
       Jan 22, 2020
    @jinhan13789991 我第三种就是这种,可以用函数转化,但容易被找规律
    lg106
        11
    lg106  
    OP
       Jan 22, 2020
    @whypool 我试试第三种,UUID 有点长
    lg106
        12
    lg106  
    OP
       Jan 22, 2020
    @jfcherng 我试试去
    Varobjs
        13
    Varobjs  
       Jan 22, 2020 via Android
    @lg106 那就数字 id md5 下就可以了,多方便
    lg106
        14
    lg106  
    OP
       Jan 22, 2020
    @Varobjs 我忘了说了,长度只能是 8 到 10 位,太长了不行,类似这种 rczlihkgyt
    GM
        15
    GM  
       Jan 22, 2020   ❤️ 1
    HashID 了解一下,数据表可以继续用自增 id 字段,对外做个转换变成 HashID 就好了。
    009694
        16
    009694  
       Jan 22, 2020 via iPhone
    前两种方案有什么缺点吗?
    5oiR5piv5YK76YC8
        17
    5oiR5piv5YK76YC8  
       Jan 22, 2020   ❤️ 2
    hashids 靠谱
    cgpiao
        18
    cgpiao  
       Jan 22, 2020 via iPhone
    设备 id + 自定义格式时间 + 自增 转换为 36 进制
    lg106
        19
    lg106  
    OP
       Jan 22, 2020
    试了下 hashids,这个完美解决,感谢大佬们
    eason1874
        20
    eason1874  
       Jan 22, 2020
    怕 ID 暴露可以用 36 进制,36 个字符打乱顺序就不好猜了,但如果获得连续 ID 还是可以破解出来。
    vanishcode
        21
    vanishcode  
       Jan 22, 2020
    https://github.com/souyunku/SnowFlake
    不知道是不是楼主想要的。。
    xaplux
        22
    xaplux  
       Jan 22, 2020
    @vanishcode 很明显不是,楼主想要的是全字母的,17 楼说的 hashids 靠谱
    tabris17
        23
    tabris17  
       Jan 22, 2020
    snowflake 算法生成 64 位整数

    然后转换成 base53 字符串(仅包含字母和下划线)
    hubqin
        24
    hubqin  
       Jan 22, 2020
    取巧,JavaScript:Math.random().toString(36).slice(2)
    wengcd
        25
    wengcd  
       Jan 22, 2020
    https://hashids.org

    配置密钥,真实🆔根据密钥生成 hash 值;有密钥可反推出真实🆔,没有则无法反推
    alaikis
        26
    alaikis  
       Jan 22, 2020
    数字 36 进制
    MrYELiex
        27
    MrYELiex  
       Jan 22, 2020
    snowflake
    Raymon111111
        28
    Raymon111111  
       Jan 22, 2020
    snowflake 这种方案然后把 0 到 9 映射到 a - j 上就行了.

    一个简单的实现是, 当前时间(unixtime, 秒和毫秒都可以) + 机器码(比如集群是 100 个机器, 那就号码就是 00 - 99) + 三位轮询的数(每个机器启动时候就拿到一个打乱的大小是 1000 的数组, 里面的数是 000 - 999, 生成的时候从里面取数然后移除, 空了再生成一次)

    这么干冲突的概率相当小(几乎不会有)
    looplj
        29
    looplj  
       Jan 22, 2020
    uuid->hash->baese64 取前 10 位
    sleepm
        30
    sleepm  
       Jan 22, 2020
    有个自增主键 id,然后,先插入新纪录,然后获取 id,再根据 id 生成全字母的 ID
    luopengfei14
        31
    luopengfei14  
       Jan 22, 2020 via iPhone
    36、62 进制都可以
    fx
        32
    fx  
       Jan 22, 2020
    hashids
    jeremaihloo
        33
    jeremaihloo  
       Jan 22, 2020
    nanoid

    github.com 上搜一下,不同语言都有实现,一定程度上满足需求吧
    qsbaq
        34
    qsbaq  
       Jan 22, 2020
    把 ID 弄个 md5 肯定唯一了
    songco
        35
    songco  
       Jan 22, 2020
    没有可读性要求可以直接 id 映射一下就行, 比如数字转换成 16 进制; 比如 0-9 映射成 10 个字幕

    有可读性要求的话, 准备字典, 然后随机生成两到组拼起来, 预先生成也行; 生成后查重复也行; 直接按顺序映射也可以, 生成的结果大概类似 docker 的默认名字, 比如 adoring_lovelace 之类的
    Liang
        36
    Liang  
       Jan 22, 2020
    @qsbaq md5 在一定概率下会重复的
    wzwwzw
        37
    wzwwzw  
       Jan 22, 2020
    uuid 去掉 - 呗。
    kkkkkrua
        38
    kkkkkrua  
       Jan 22, 2020 via iPhone
    将数字转成 58 进制
    hauzi
        39
    hauzi  
       Jan 22, 2020 via iPhone
    第一种
    fireapp
        40
    fireapp  
       Jan 22, 2020 via iPhone
    mongo object id 还不错可以试试
    freemoon
        41
    freemoon  
       Jan 22, 2020
    利用自增思想,A->B 等效于 1->2
    fdingiit
        42
    fdingiit  
       Jan 22, 2020
    有请求,再创建不是一个好的生产环境策略。

    我们的生产环境上,id 是有个预资源池,初始可能是 n 位,随用随取。如果用完了,就 stop the world 并再生成一个位数为 n+1 的 id 新池子。

    这个思路的来源是编译器中内存分配以及垃圾回收的几个简单算法。
    gamexg
        43
    gamexg  
       Jan 22, 2020
    hashid 挺好,
    我做过类似的另一个需求,
    不过原始 id 是二进制数据,直接固定 iv 的 aes 流加密来做的。
    rogwan
        44
    rogwan  
       Jan 22, 2020
    hashids + 盐。
    LancerEvo
        45
    LancerEvo  
       Jan 22, 2020
    记得在某个公司的代码里见过一个微服务 用的第二种实现
    zyqhi
        46
    zyqhi  
       Jan 22, 2020 via iPhone
    26 进制
    ech0x
        47
    ech0x  
       Jan 22, 2020
    生成一个 UUID 不就行了,UUID3 或者 UUID5
    wd
        48
    wd  
       Jan 22, 2020 via iPhone
    我觉得第一种就挺好的 uuid 里面取几位用 不会那么大概率需要生成第二次
    zpvip
        49
    zpvip  
       Jan 22, 2020 via Android
    我不知道为什么 Ruby on Rails 在国内这么不受待见。这个需求一行代码就搞定了

    gem 'friendly_id'
    lookas2001
        50
    lookas2001  
       Jan 23, 2020 via Android
    8 位 id 取 5 次都有重复的可能性基本上就为 0 了
    所以,第一种
    dandandanerdan
        51
    dandandanerdan  
       Jan 23, 2020
    uuid 是最安全的
    polymerdg
        52
    polymerdg  
       Jan 23, 2020
    我用的是 MD5(用戶名+時間戳+隨機 6 位)
    huzb
        53
    huzb  
       Jan 24, 2020
    用函数把用户 ID 转成字母 ID 是最好的,可以确保唯一且在前端就完成校验。相近 ID 这个可以用混淆和扩散的方式把变化打乱。我有总结过一篇文章:huzb.me/2018/03/23/简单的密码学生成唯一邀请码 /
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4104 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 169ms · UTC 10:12 · PVG 18:12 · LAX 03:12 · JFK 06:12
    ♥ Do have faith in what you're doing.