lg106
V2EX  ›  PHP

生成唯一字母 ID 求解

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

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

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

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

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

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

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

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

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

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