生成可读的随机唯一 ID

Generate a readable random unique ID

我需要生成唯一的交易 ID。系统允许数字、字母、连字符和下划线,但不允许句号。

我目前使用的功能是,

generate_id() {
    $id = uniqid('P_', true);
    $id = str_replace('.', '-', $id);
    return $id;
}

示例输出:

P_551171d3dd8a93-57457934

但是,我最近发现 (a) uniqid() 不一定是唯一的,并且 (b) 我的客户偶尔需要重新输入这些 ID、比较它们、搜索它们等。当前ID 的可读性不强,也很难引起注意。 (我原以为这些纯粹是支付内部使用的API。我最近才发现客户真的在看东西。)

所以我想改成这个,

function generate_id() {
    $s = '';
    for ($i = 0; $i < 5; $i++) {
        if ($s) {
            $s .= '-';
        }
        $s .= bin2hex(openssl_random_pseudo_bytes(2));
    }
    return $s;
}

示例输出:

ced7-1cef-5331-193c-907d

openssl_random_pseudo_bytes() 推荐的 生成随机唯一标识符的方法,但我担心这样做四次并连接(我这样做只是因为那是用连字符将其拆分以便于阅读的最简单方法)可能会损害它。我应该生成一个长字符串然后对其进行操作以添加连字符吗?

或者,事实上,我应该完全做点别的事情吗?我真的不介意交易 ID 是什么样子,只要它是唯一的并且相对容易观察或重新输入即可。

连续多次调用openssl_random_pseudo_bytes应该没有问题。无论您读取一长串随机字节还是读取许多短随机字节串都没有关系,它们仍然是随机的。我仍然会将该代码更改为此,因为它更简单:

join('-', str_split(bin2hex(openssl_random_pseudo_bytes(40)), 4))

这个 几乎 看起来像 UUID already, so you may actually want to use one of those instead. While random bytes should do, UUIDs are explicitly designed to be globally unique with a high enough probability that you don't need to worry about it in practice at all. Use http://pecl.php.net/package/uuid 或您的替代首选实现。

使用 UUID。它可以由 uniqid() 和自定义算法或使用库形成。如果你使用 UUID 发生碰撞,< insert random massive gift here >.

https://github.com/ramsey/uuid