全球数字化浪潮滚滚而来,各行各业无时无刻不在与数字
打交道,万事万物或被牵扯和囊括其中。数字(Digit or number
)作为一种简单快速的识别代码,深受开发者和广大用户的喜爱,在以下诸如此类的众多场景中被广泛使用:
(1)各个国家居民身份的唯一标识(ID Card
)
(2)全世界生产的所有电脑,每台电脑都有着唯一的序列号(硬件MAC地址
)
(3)各大手机厂商为用户分配的识别号,如(苹果手机AppID、华为手机HUAWEI_id
)
(4)全球通信运营商为用户分配的移动号码(8614879421684
)
(5)互联网为政府机构、大学校园教育、企业单位、个人用户都分配了唯一的IP地址,从广域网(WAN
)到局域网(LAN
),从IPv4
到IPv6
,公网环境下寄托在域名服务器DNS
中的域名地址
(6)银行等业务部门为客户办理的业务单号、账单流水、卡号等
(7) 世界上所有英文期刊发表的论文的唯一标识,如(DOI
)。
假如存在这样一个问题→从全球数十亿人口中寻找满足特定条件的某一个人,那么我们该如何去做这件事情呢?
思路一:世界本无序,但人们可以定义规则生成秩序,对几十亿人口按照阿拉伯数字编号并排序,寻找某个人就相当于获取该人物的编号,但是数字的存储位数显著增加会给计算机存储带来巨大挑战
,因为人处于社会当中,伴随复杂多样的关系,导致属性关联、各异,海量信息无法仅仅依赖于数字;
思路二:为所有人口分配互不重复且唯一的识别码,这个识别码可以是数字、字母、符号以及它们的组合体
,但需要统一管理。
思路三:结合思路一和思路二,考虑归纳分组、分门别类的思想,采取分而治之,从国家到地区、城市、县、乡、村,正如域名分配一样,从顶级、中级到低级一样,采用分层分级的思路实现,便于提高处理效率,缩短计算时间。
前两种思路无形中都与数据库密切相关,数据库的规模可大可小,查询检索速度可快可慢,主要取决于查询条件和数据量的大小
;第三种思路正如金字塔、树等结构,自上而下,分门别类,扩展延伸,分层分级,较为灵活,当然比较符合现代科学技术的发展、计算机的存储方式、数据库设计模式
等理念。当然大家如果有好的想法,欢迎在评论区各抒己见,畅所欲言呀!✨✨✨
UUID的全称为(Universally Unique Identifier
)通用唯一标识符,它出现的目的是让分布式系统中出现的一切元素都具有唯一的辨识,而不需要根据中央控制端来指定辨识资格,即出生便具有独特性、唯一性和有效性。下图为Github上的uuid,已然收获了13k+的star
数量,足见其深受广大开发者和工程师的喜爱。
如果想要进一步了解UUID
是如何生成的,可以参考UUID标准和维基百科上的UUID介绍。UUID具有多个版本且各个版本具有不同的算法和应用范围,分别为基于时间的UUID、DCE安全的UUID、基于名字的UUID(MD5)、随机UUID和基于名字的UUID(SHA1)
。总的来说,各个版本的发展都是为了保证唯一性、尽可能避免冲突同时提高生成效率,基本是与时间、MAC地址、域名、URL相关或随机生成。
Version 1 UUIDs are generated from a time and a node id (usually the MAC address);
version 2 UUIDs are generated from an identifier (usually a group or user id), time, and a node id;
versions 3 and 5 produce deterministic UUIDs generated by hashing a namespace identifier and name;
and version 4 UUIDs are generated using a random or pseudo-random number.
下面就到了激动人心的环节,读完卷书,不如行万里路,让我们来亲自动手实践一下,以C#、Java、Python、C++、C和JavaScript
这六种语言代码体验一下通用唯一标识符的生成和调用方法吧。
具体需要参考Microsoft-C#官方API文档中的Guid,使用Guid来生成UUID
也是一种不错的方法哦。
using System;
namespace UUIDCSharp
{
class TestUUID
{
static void Main(string[] args)
{
for(int i=0;i<10;i++)
{
string uuid = Convert.ToString(Guid.NewGuid());
Console.WriteLine("第"+i.ToString()+"个 UUID is: " + uuid);
}
}
}
}
具体参考Oracle-Java官方API文档中的UUID,介绍了四种版本的UUID
;再者还可参考h2数据库网站上的UUID描述,利用其提供的样例源码来估计和理解两个UUID
重复的概率。
TestUUID.java
文件内容代码如下:
package com;
import java.util.UUID;
public class TestUUID {
public static String getTwoUUIDRepeatProbability(int i)
{
String res = null;
double x = Math.pow(2, 122);
double n = Math.pow(2, i);
double p = 1 - Math.exp(-(n * n) / 2 / x);
res = ("2^" + i + "=" + (1L << i) + " probability: 0" + String.valueOf(1 + p).substring(1));
return res;
}
public static void main(String[] args)
{
/*
* 直接利用java.util.UUID类直接获取UUID字符串
*/
for(int i=0;i<10;i++)
System.out.println("第"+i+"个 UUID:"+UUID.randomUUID().toString());
// for(int i=35;i<62;i++)
// System.out.println(getTwoUUIDRepeatProbability(i));
}
}
运行结果截图如下:
具体参考Python-uuid官网API文档,通过导入uuid
模块就可以使用它的四个方法了。注意这四个方法依次是uuid1(),uuid3(),uuid4(),uuid5(),然而并没有uuid2()。在某个文件目录下用Notepad新建test-uuid.py
文件,并输入如下代码后打开控制台执行命令:python test-uuid.py
。
test-uuid.py
文件内容代码如下:
# -*- coding:utf-8 -*-
import uuid
print(uuid.uuid1())
print(uuid.uuid3(uuid.NAMESPACE_DNS, 'jing_zhong'))
print(uuid.uuid4())
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'jing_zhong'))
命令行和Python自带的IDLE
运行结果如下所示:
下面利用PyCharm新建项目和TestUUID.py
文件,编译运行测试,TestUUID.py
文件内容代码如下:
# -*- coding:utf-8 -*-
import uuid
def getUUID1():
return str(uuid.uuid1())
def getUUID3(name):
return str(uuid.uuid3(uuid.NAMESPACE_DNS, name))
def getUUID4():
return str(uuid.uuid4())
def getUUID5(name):
return str(uuid.uuid5(uuid.NAMESPACE_DNS, name))
if __name__ == '__main__':
n = 10
for i in range(0,n):
print("第" + str(i+1) + "个uuid1:" + getUUID1())
print("第" + str(i+1) + "个uuid3:" + getUUID3("jing_zhong"))
print("第" + str(i+1) + "个uuid4:" + getUUID4())
print("第" + str(i+1) + "个uuid5:" + getUUID5("jing_zhong"))
这里依赖C++的Boost库来生成UUID
,到官网下载编译后的Boost
库或根据官方文档自己编译源码均可,之后用VS 2015
新建C++项目将头文件和库文件目录引入即可,然后新建TestUUID.cpp
文件,输入如下代码后编译生成即可。
TestUUID.cpp
文件内容代码如下:
#include
#include
#include
#include
using namespace std;
using namespace boost;
string getUUID()
{
boost::uuids::uuid a_uuid = boost::uuids::random_generator()();
string uuid_string = boost::uuids::to_string(a_uuid);
return uuid_string;
}
int main()
{
std::cout << "-----------------------C++ 使用boost库生成UUID------------------------" << std::endl;
for (int i = 0; i < 10; i++)
std::cout << "第"<< (i+1) <<"个UUID:" << getUUID() << std::endl;
return 0;
}
至于用C
语言代码生成UUID
,大家可能使用更多的是在linux系统上的libuuid库,当然也推荐大家学习Github-stduuid库,尝试在Windows
系统下用VS
编译即可使用。有兴趣的伙伴可以多阅读StackOverflow上的generating-a-random-uuid-in-c话题讨论,或许会有启发。
TestUUID-linux-libuuid.c
文件内容代码如下(linux下安装libuuid库后调用):
#include <stdlib.h>
#include <stdio.h>
#include <uuid.h>
int main(void) {
uuid_t binuuid;
uuid_generate_random(binuuid);
char *uuid = malloc(37);
#ifdef capitaluuid
uuid_unparse_upper(binuuid, uuid);
#elif lowercaseuuid
uuid_unparse_lower(binuuid, uuid);
#else
uuid_unparse(binuuid, uuid);
#endif
puts(uuid); // Equivalent of printf("%s\n", uuid); - just my personal preference
return 0;
}
//#include
//#include
//
gcc uuid.c -luuid -o uuid
//
//int main()
//{
// int i, n;
// uuid_t uu[4];
// char buf[1024];
// struct timeval tv;
// //1、
// uuid_generate(uu[0]);
// //2、
// uuid_generate_random(uu[1]);
// //3、
// uuid_generate_time(uu[2]);
// //4、
// n = uuid_generate_time_safe(uu[3]);
// printf("n = %d\n", n);
// for (i = 0; i<4; ++i) {
// uuid_unparse(uu[i], buf);
// printf("uu[%d]\t\t%s\n", i, buf);
// }
//
// uuid_time(uu[2], &tv);
// printf("tv s:%lx u:%lx\n", tv.tv_sec, tv.tv_usec);
//
//
// return 0;
//}
此外,自己动手编写一个利用随机数生成UUID
的函数代码,放到TestUUID.c中,利用VS 2015
新建项目后编译运行。
TestUUID.c
文件内容代码如下:
#include
#include
char* gen_uuid() //3fb17ebc-bc38-4939-bc8b-74f2443281d4
{
char v[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static char buf[37] = { 0 };
for (int i = 0; i < 37; ++i)
{
if (i == 8 || i == 13 || i == 18 || i == 23)
buf[i] = '-'; //put dashes in place 8 dash 4 dash 4 dash 4 dash 12
else if(i != 36)
buf[i] = v[rand() % 16]; //gen random for all spaces because lazy
else
buf[36] = '\0'; //needs end byte
}
return buf;
}
void printChars(char *s)
{
for (int i = 0; i <= 36; ++i)
{
if(i !=36)
printf("%c", *(s++));
else
printf("\n");
}
}
int main()
{
puts("----------------C语言代码生成UUID-----------------");
for (int i = 0; i < 10; i++)
{
char *s = gen_uuid();
printf("第%d个UUID:", i + 1);
printChars(s);
}
system("pause");
return 0;
}
在前端JavaScript
代码面前,生成UUID
早已成为老生常谈的话题,有兴趣的朋友可以参考StackOverflow
上的两个讨论话题:how-to-create-a-guid-uuid-in-javascript和collisions-when-generating-uuids-in-javascript,个人觉得该话题早已引起了广泛而又激烈的讨论,大家的思路和想法都十分活跃和积极,下面的代码是自己认为较为精华的部分:
{
function createGuid1() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0;
var v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function createuuid2() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
console.log('-------------------使用第一种方法生成UUID---------------------');
for(let i=0;i<10;i++)
console.log('第'+(i+1)+'个UUID:',createGuid1())
console.log('-------------------使用第二种方法生成UUID---------------------');
for(let i=0;i<10;i++)
console.log('第'+(i+1)+'个UUID:',createuuid2())
}
浏览器中按F12进入开发者控制台Console
窗口中,将以上代码粘贴其中后按回车键,即可看到运行结果:
除了在浏览器内运行js外,可能大多数开发者更喜欢在命令行终端窗口中测试运行。这里假设大家在电脑上已经安装好了Node.js
环境,且已经配置好了npm
包管理器,那么可以全局或者在某文件目录下局部安装uuid依赖库进行测试学习,下面我以本地E:\jing_zhong\TestNodeUUID
文件目录下测试运行js代码进行说明。
第一步,Win+R打开cmd命令行窗口,依次输入如下两行命令在查看安装的node版本号和npm版本号,确保前提环境安装成功。
node -v
npm -v
第二步,用Notepad
或其他IDE新建package.json
文件和TestUUID.js
文件,并将下述内容粘贴到其中;
package.json
文件(utf-8编码)内容如下:
{
"name": "test-node-uuid",
"version": "1.0.0",
"description": "test javascript uuid",
"main": "TestUUID.js",
"scripts": {
"testuuid": "node TestUUID"
},
"type": "cjs",
"keywords": [
"uuid",
"js"
],
"author": "jing_zhong",
"license": "MIT",
"dependencies": {
"uuid": "^9.0.0"
}
}
TestUUID.js
文件内容代码如下:
function createGuid1() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0;
var v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function createuuid2() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
console.log('-------------------使用第一种方法生成UUID---------------------');
for(let i=0;i<10;i++)
console.log('第'+(i+1)+'个UUID:',createGuid1())
console.log('-------------------使用第二种方法生成UUID---------------------');
for(let i=0;i<10;i++)
console.log('第'+(i+1)+'个UUID:',createuuid2())
console.log('-------------------使用第三种方法生成UUID(uuid库)---------------------');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var uuidv1 = (0, _interopRequireDefault(require("./node_modules/uuid/dist/v1.js")).default);
var uuidv3 = (0, _interopRequireDefault(require("./node_modules/uuid/dist/v3.js")).default);
var uuidv4 = (0, _interopRequireDefault(require("./node_modules/uuid/dist/v4.js")).default);
var uuidv5 = (0, _interopRequireDefault(require("./node_modules/uuid/dist/v5.js")).default);
for(let i=0;i<10;i++)
console.log('第'+(i+1)+'个UUID:',uuidv1(),' ', uuidv4())
//console.log(uuidv3('6ba7b810-9dad-11d1-80b4-00c04fd430c8','6ba7b810-9dad-11d1-80b4-00c04fd430c8'));
//console.log(uuidv4());
//console.log(uuidv5('6ba7b810-9dad-11d1-80b4-00c04fd430c8','6ba7b810-9dad-11d1-80b4-00c04fd430c8'));
第三步,在命令行窗口中输入命令进入TestNodeUUID
目录,安装uuid库后执行TestUUID.js代码,得到运行结果。
cd E:\jing_zhong\TestNodeUUID
E:
npm install
node TestUUID.js
世界上没有两片完全相同的叶子。作为身份的唯一标识码,UUID在许多行业和实际的应用场景中都有独特的唯一性要求,众多软件应用和硬件厂商早已考虑到这一点。人间各地烟火不同,繁花各异(樱花、梅花、海棠花、菊花、茉莉花、桃花
),此时此刻,不由得回忆起《爱莲说》中的予独爱莲之出淤泥而不染,濯清涟而不妖,中通外直,不蔓不枝,香远益清,亭亭净植,可远观而不可亵玩焉
!!!
愿自己始终能够保持一颗纯净而沉着的心灵,不被外事外物束缚、干扰,脚踏实地,诚心诚意,实事求是,追求真理,不遗余力,在自己热爱的技术领域深耕探索,以绵薄之力分享些许技术心得,体会学海遨游的乐趣,感叹知识海洋的无线广阔,慢慢成长,积极学习。
人生充满未知和挑战,勇敢者从未停止脚步。寒门学子,漂泊在外,漆黑的夜晚时常独自思考自己的人生应该如何度过,回想自己还有哪些不足和遗憾 ?尽管久久无法找到答案,但灵机一动发现,除了从书中寻找答案,还可以用心感受社会的变迁、气候的变化、工作的不易和生活的艰辛,可怜天下父母心,母亲身上那种时不我待、只争朝夕的坚强品格,乐观向上的豁达心态令我敬佩不已;父亲身上那种刚强勇毅、不屈不挠、坚韧执著的恒心和毅力更能成为我前进道路上的明灯。愿自己活到老,学到老,还有三分没学到,回首往事之时尽是历历在目的美好回忆。
❤️❤️❤️亲爱的孟营,世界之大,有幸相识,时光匆匆,感恩曾经,纵有不舍,心有所往,愿你早遇佳人,幸福一生
最后,谨以此文与诸君共勉之,孤独寂寞的日子里还是会偷偷地思念家人、默默期待着未来的那个她
人的一生应当这样度过,当他回首往事的时候,不因虚度年华而悔恨,更不因碌碌无为而羞愧。多少人曾爱慕你年轻时的容颜,可知谁愿承受岁月无情的变迁。