版本号:版本号即上文所说的五个版本,在五个版本的UUID中,都总是在该位置标识版本,占据 4-bit,分别以下列数字表示:

文章插图
因此版本号这一位的取值只会是1,2,3,4,5
变体值:表明所依赖的标准(X表示可以是任意值):

文章插图
时钟序列:在基于时间的UUID中,时钟序列占据了07~06位的14-bit 。不同于时间值,时钟序列实际上是表示一种逻辑序列,用于标识事件发生的顺序 。在此,如果前一时钟序列已知,则可以通过自增来实现时钟序列值的改变;否则,通过(伪)随机数来设置 。主要用于避免因时间值向未来设置或节点值改变可能导致的UUID重复问题 。
节点值:在基于时间的UUID中,节点值占据了05~00的48-bit,由机器的MAC地址构成 。如果机器有多个MAC地址,则随机选其中一个;如果机器没有MAC地址,则采用(伪)随机数 。
了解了基于时间的UUID结构及生成规则后,再看看其他版本的UUID生成规则:
- 版本2 - 分布式安全的UUID:
- 版本3/5 - 基于名字空间的UUID (MD5/SHA1):
- 将命名空间 (如DNS、URL、OID等) 及名字转换为字节序列;
- 通过MD5/SHA1散列算法将上述字节序列转换为16字节哈希值 (MD5散列不再推荐,SHA1散列的20位只使用其15~00位);
- 将哈希值的 3~0 字节置于UUID的15~12位;
- 将哈希值的 5~4 字节置于UUID的11~10位;
- 将哈希值的 7~6 字节置于UUID的09~08位,并用相应版本号覆盖第9位的高4位 (同版本1位置);
- 将哈希值的 8 字节置于UUID的07位,并用相应变体值覆盖其高2位 (同版本1位置);
- 将哈希值的 9 字节置于UUID的06位 (原时钟序列位置);
- 将哈希值的 15~10 字节置于UUID的05~00位 (原节点值位置) 。
- 版本4 - 基于随机数的UUID:
- 生成16byte随机值填充UUID 。重复机率与随机数产生器的质量有关 。若要避免重复率提高,必须要使用基于密码学上的假随机数产生器来生成值才行;
- 将变体值及版本号填到相应位置 。
5.多版本伪码
// 版本 1 - 基于时间的UUID:gen_uuid { struct uuid uu; // 获取时间戳 get_time(&clock_mid, &uu.time_low); uu.time_mid = (uint16_t) clock_mid; // 时间中间位 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; // 时间高位 & 版本号 // 获取时钟序列 。在libuuid中,尝试取时钟序列+1,取不到则随机;在Python中直接使用随机 get_clock(&uu.clock_seq);// 时钟序列+1 或 随机数 uu.clock_seq |= 0x8000;// 时钟序列位 & 变体值 // 节点值 char node_id[6]; get_node_id(node_id);// 根据mac地址等获取节点id uu.node = node_id; return uu;}// 版本4 - 基于随机数的UUID:gen_uuid { struct uuid uu; uuid_t buf; random_get_bytes(buf, sizeof(buf));// 获取随机出来的uuid,如libuuid根据进程id、当日时间戳等进行srand随机 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;// 变体值覆盖 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;// 版本号覆盖 return uu;}// 版本5 - 基于名字空间的UUID(SHA1版):gen_uuid(name) { struct uuid uu; uuid_t buf; sha_get_bytes(name, buf, sizeof(buf));// 获取name的sha1散列出来的uuid uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;// 变体值覆盖 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x5000;// 版本号覆盖 return uu;}(左滑查看完整代码)数据库自增ID
数据库自增ID可能是大家最熟悉的一种唯一ID生成方式,其具有使用简单,满足基本需求,天然有序的优点,但也有缺陷:
- 并发性不好
- 数据库写压力大
- 数据库故障后不可使用
- 存在数量泄露风险
1. 数据库水平拆分,设置不同的初始值和相同的步长
推荐阅读
- 算法:如何实现大正整数相加?
- 用python实现汉诺塔算法!(含代码示例)
- 自媒体1w推荐量却只有100多阅读量?莫慌!平台算法了解一下
- 太阳系中拥有卫星最多的行星是天王星 阳系中唯一同时拥有大陆地壳和大洋地壳的行星是
- Mysql 为什么要选择 B+Tree
- 分享mysql配置文件my.cnf一键生成器
- 分布式原理:一致性哈希算法简介
- DH算法原理
- 算法之常见排序算法-冒泡排序、归并排序、快速排序
- 普洱茶养生成为引领健康生活方式的风向标
