uuid
{% note success no-icon %}
UUID 简介(PHP为例)
介绍
- 名称:Universally Unique Identifier(通用唯一标识符)
- 简介
- UUID 是一串全球唯一的(16进制)数字串。
- UUID 由开源软件基金会 (Open Software Foundation, OSF) 定义,是分布式计算环境 (Distributed Computing Environment, DCE) 的一个组成部分。
- UUID 的标准格式为“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx”,五个部分分别为8个字符、4个字符、4个字符、4个字符、12个字符,中间用“-”号间隔。常见的 GUID(Globally Unique Identifier)是微软对 UUID 标准的一种实现。
- 目的
- 让每个使用者都能生成不跟其他人重复的唯一码
- 组成
- 【xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx】UUID是16进制128bit长的数字,通常以36字节的字符串表示。
- 其中 M 与 N 都有特殊含义M 表示 UUID 版本,目前只有五个版本,即只会出现 1,2,3,4,5。数字 N 的一至三个最高有效位表示 UUID 变体,目前只会出现 8,9,a,b 四种情况。
应用场景
- 很多应用场景需要一个id,但是又不要求这个id有具体的意义,仅仅用来标识一个对象。
- 常见的例子有:
- 数据库表的id字段
- Linux 系统配置档
- 阿里云、腾讯云的API 界面中的请求Id(requestId)
- ...etc
版本
UUID版本 (Version 1)
- 基于时间的 UUID
- 基于时间的 UUID 通过计算当前时间戳、随机数和机器 MAC 地址得到。由于在算法中使用了 MAC 地址,这个版本的 UUID 可以保证在全球范围的唯一性。但与此同时,使用 MAC 地址会带来安全性问题,这就是这个版本 UUID 受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址。
UUID版本 (Version 2)
- DCE 安全的 UUID
- 分布式计算环境(Distributed Computing Environment) 安全的 UUID 和基于时间的 UUID 算法相同,但会把时间戳的前 4 位置换为 POSIX 的 UID 或 GID。这个版本的UUID在实际中较少用到。
UUID版本 (Version 3)
- 基于名字的 UUID(MD5)
- 基于名字的 UUID 通过计算名字和命名空间的 MD5 散列值得到。这个版本的 UUID 保证了:
- 相同命名空间中不同名字生成的 UUID 的唯一性;
- 不同命名空间中的 UUID 的唯一性;
- 相同命名空间中相同名字的 UUID 重复生成是相同的。
UUID版本 (Version 4)
- 随机 UUID
- 根据随机数,或者伪随机数生成 UUID。
- 这种UUID产生重复的概率是可以计算出来的。
UUID版本 (Version 5)
- 基于名字的 UUID(SHA1)
- 和版本 3 的 UUID 算法类似,只是散列值计算使用 SHA1(Secure Hash Algorithm 1)算法。
UUID 版本对比
V1 | V2 | V4 | V3 | V5 | |
---|---|---|---|---|---|
长度组成 | 48bit 主机的 Mac 地址 60bit 时间戳 (13-14bit 作为时间序列) |
48bit 主机的 Mac 地址 40bit 域名/ID 28bit 时间戳(6bit 作为时间序列) |
6bit 标记版本 122bit 随机数 |
将值与指定的命名空间拼接后,做 hash 运算,再做一些额外的固定变换得到最终的 UUID V5 区别于 V3 是使用了更不容易碰撞的 hash 算法,前者 sha1,后者 md5。 注意值不变的情况下生成的 UUID 相同 |
同前 |
重复率 | 每个节点每秒钟可生成 1630 亿个,也就是说每毫秒 163 个。 | 允许一个节点存在 1 万亿个 域名/ID 对象,每个对象每 7 秒产生一个 UUID。 | 每秒生成 10 亿个,大约需要 85 年才有重复的可能,所以在正常应用情形下这种碰撞概率可以忽略。 | --- | --- |
选择 | 有暴露MAC地址的危险,需要反向解析主机 Mac 地址。 | 一般不会用到 | 首选 最简单实用的版本 |
需要根据特定的值生成,而且在值不变的情况下生成的 UUID 不变。 | 同前 |
UUID 的选择
- 从UUID的不同版本可以看出:
- Version 1/2适合应用于分布式计算环境下,具有高度的唯一性;
- Version 3/5适合于一定范围内名字唯一,且需要或可能会重复生成UUID的环境下;
- Version 4,虽然重复率可计算,但是它是最简单最方便的。
UUID 的生成(PHP)
- 使用类库或者插件(常用方法)
- PECL::Package::uuid (插件)
- ramsey/uuid (类库)
- WebComandAPI
- 使用数据库生成(一般为Version 1)
- mysqli_query($dbname, "select uuid() as uuid")
- 使用PHP方法com_create_guid()产生GUID
- 可以使用trim(com_create_guid(), '{}')来生成UUID(一般为V4版本)
- 使用PHP自己编写生成(一般可以实现Version 1与Version 4)
简单范例 V1/V4
/**
* create v1uuid
* @author doubleam
* @param string $prefix ps
* @param int $median 随机位个数
* @return string
*/
function create_v1uuid($prefix = "uuid-v1: ", $median = 3) {
$randArr = ['8', '9', 'a', 'b'];
$ip = get_ip() ?? 'ip1.ip2.ip3.ip4';
$ipUniqid = uniqid(base_convert(implode('', explode('.', $ip)), 10, 16));
$randNum = md5(uniqid(mt_rand()));
$mt = microtime(); //unix时间戳
list($msc, $ts) = explode(" ", $mt);
$mscStr = uniqid(ltrim($msc, "0."));
$tsStr = dechex($ts);
$uuid = $tsStr . '-'; //时间戳精确到秒
$uuid .= substr($mscStr, 0, 4) . '-';
$uuid .= '1' . substr($mscStr, 4, 3) . '-';
$uuid .= $randArr[mt_rand(0, 3)] . substr($ipUniqid, 0, 3) . '-';
$uuid .= substr($ipUniqid, 4, 9);
$uuid .= substr($randNum, 0, $median);
return $prefix . $uuid;
}
$uuid = "select uuid() as uuid";
echo create_v1uuid();
echo "<br/>uuid-v1: " . mysqli_fetch_assoc(mysqli_query($hxb_db, $uuid))['uuid'];
mysqli_close($hxb_db);
/**
* 获取ip地址
* @return String ip地址
*/
function get_ip() {
if (!empty(filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP'))) {
return filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP');
} elseif (!empty(filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR'))) {
return filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR');
} else {
return filter_input(INPUT_SERVER, 'REMOTE_ADDR');
}
}
/**
* create v4uuid
* @author doubleam
* @param string $prefix ps
* @return string
*/
function create_v4uuid($prefix = "uuid-v4: ") {
$randArr = ['8', '9', 'a', 'b'];
$str = md5(uniqid(mt_rand(), true));
$uuid = substr($str, 0, 8) . '-';
$uuid .= substr($str, 8, 4) . '-';
$uuid .= '4' . substr($str, 12, 3) . '-';
$uuid .= $randArr[mt_rand(0, 3)] . substr($str, 15, 3) . '-';
$uuid .= substr($str, 19, 12);
return $prefix . $uuid;
}
echo create_v4uuid();
echo "<br/>uuid-v4: " . trim(com_create_guid(), '{}');