前端唯一标识那些事儿

简介: 在做聊天模块的时候,最初的消息唯一标识是msgId,在业务量小的情况下是可以满足需求的,毫秒级的唯一冲突是很难出现的。但是当用户量上升之后,时间戳的这种方案显然不行。因此需要引入一种新的前端生成唯一标识的方案。

image.png



除了时间戳之外,我在公司的其他前端项目中,发现一些其他的前端唯一性标识实现,因此在这里做一个记录。

  • 时间戳 唯一性差(目前应用于聊天消息唯一标识)
  • random string 唯一性较强(目前应用于OSS存储文件唯一识别名)
  • uuid 唯一性极强(待引入的唯一性更强的方案)
  • RFC4122是什么
  • node-uuid
  • node-uuid是什么
  • uuid的v1,v3,v4,v5分别是什么意思?
  • 已有项目uuid应用分析
  • node-uuid项目实践
  • 总结与思考


时间戳


应用于聊天模块的msgId,就是采用了时间戳的形式。


this.message.msgId = `${+new Date()}`; // "1568689340401"

虽然说唯一性较差,但是截至目前还没有出现因为唯一性差导致重大问题。


random string



function randomString(length) {
  const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_=-';
  let result = '';
  for (let i = length; i > 0; --i) {
    result += chars[Math.floor(Math.random() * chars.length)];
  }
  return result;
}


假如length输入的是64,那么这个随机数算法会在0~9,a~z,A~Z,-=_中生成一个64的64次方的分之一的随机字符串,64的64次方式3.940200619639448e+115,亿级也就1.0e+10,这个数字已经庞大到令人发指,唯一性其实已经很强了。


唯一性会随着length长度的下降而下降,在文件名过长的情况下调整文件名长度时需要特别注意。


uuid


node-uuid是一个基于RFC4122加密算法的nodejs实现,在现代化的前端项目中,是可以直接引用的。


UUID的全写是Universally Unique IDentifier,可以理解为全球唯一识别码。(引入uuid以后,根本不用担心自己手上的项目前端凭证唯一性不足的问题,因为UUID是全球都唯一的。)


RFC4122是什么


来看一段RFC4122的官方摘要就基本明白了。

AbstractThis specification defines a Uniform Resource Name namespace forUUIDs (Universally Unique IDentifier), also known as GUIDs (GloballyUnique IDentifier). A UUID is 128 bits long, and can guaranteeuniqueness across space and time. UUIDs were originally used in theApollo Network Computing System and later in the Open SoftwareFoundation's (OSF) Distributed Computing Environment (DCE), and thenin Microsoft Windows platforms.This specification is derived from the DCE specification with thekind permission of the OSF (now known as The Open Group).Information from earlier versions of the DCE specification have beenincorporated into this document.


可以提炼出以下知识点:

  • 这个规范定义了UUIDs(Universally Unique IDentifier)的统一资源名命名空间,也可以叫做GUIDs(Global Unique IDentifier)。
  • 一个UUID的长度是128位,在空间和时间两个维度都是可以保证唯一性的。
  • UUID的首次应用,是在阿波罗网络计算系统上,之后又应用在了开源软件基金会(OSF)和分布式计算环境(DCE),后来也应用在了微软的Windows平台上。
  • 这个规范是在OSF的许可下从DCE规范衍生出来的。(OSF指的是Open Group)
  • DCE规范早期版本中的内容合并在了这个文档中。


从上面关于RFC4122的描述可以看出,RFC4122其实是一个UUID规范,最初诞生于阿波罗计算机,一直沿用至今。基于这个规范,有多种语言的版本。


从github上,我找到了几种语言的基于RFC4122实现的UUID的repo。


node-uuid


node-uuid是什么


  • 符合commonjs规范和RFC4122的nodejs实现的UUID
  • 支持版本1,3,4,5多个版本的UUID
  • 跨平台,浏览器端和node端皆可使用
  • 可加密-必要时可以使用随机数API进行加密增强安全性
  • 零依赖,纯粹的自给自足的package


uuid的v1,v3,v4,v5分别是什么意思?


v1 timestamp(时间戳)


uuid.v1(options, buffer, offset)


options包括node,clockseq,msecs和nsecs;buffer是UUID将要写入的地方;buffer起始位置。


一般来说直接vvid.v1()即可。


v3 namespace(命名空间)


uuid.v3(name, namespace, buffer, offset)


name是uuid的名字;namespace是字符串或16位数组UUID的命名空间;buffer起始位置。


一般来说直接指定name和namespace即可。


const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
uuid.v3('Hello, World!', MY_NAMESPACE); // ⇨ 'e8b5a51d-11c8-3310-a6ab-367563f20686'

v4 random number(随机数)


uuid.v4(options, buffer, offset)

options包括random和rng;buffer是UUID将要写入的地方;buffer起始位置。

一般来说直接vvid.v4()即可。


v5 namespace(命名空间)


uuid.v5(name, namespace, buffer, offset)

name是uuid的名字;namespace是字符串或16位数组UUID的命名空间;buffer起始位置。


一般来说直接指定name和namespace即可。

const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
uuid.v5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'

从上面可以看出,UUID有时间戳,随机数和命名空间三种版本。

v1是时间戳;v4是随机数;v3和v5是命名空间。

根据具体业务场景选择恰当的UUID版本。


已有项目uuid应用分析


import UUID from "uuid";
export const uuid = () => UUID.v4().split("-").join("")
/**
UUID.v4(); // "51a3b08b-41ce-49ca-bda3-717b22bd9b3e"
UUID.v4().split("-"); // ["51a3b08b", "41ce", "49ca", "bda3", "717b22bd9b3e"]
UUID.v4().split("-").join(""); // "51a3b08b41ce49cabda3717b22bd9b3e"
**/


生成长度为32的uuid,将-移除。其实移除不移除都是ok的。


node-uuid项目实践


使用node-uuid替换现有的msgId,增强消息唯一标识的唯一性。

我最初的想法是通过node-uuid的v4版本生成一个随机数uuid,对消息做唯一标识即可。但是由于考虑到服务端的业务实现,这个方案不可行。


原因是因为服务端需要使用时间戳类型的msgId加时间戳类型的版本号,最后消息需要根据时间戳进行排序。因此不能暴力替换,需要找一个其他的不会造成break change的方案。


node-uuid或者说UUID的v1版本就是时间戳的形式,但是能否引入到项目中还有待商榷。


import UUID from "uuid";
export const uuid = () => UUID.v1();// "a20c6eb0-d922-11e9-9be9-5ff126df765f"


总结与思考


  • 时间戳唯一性虽然差但是可能刚好满足特定的业务场景,不见得是差的技术方案
  • 自定义的random string唯一识别实现,其实也能满足唯一性的要求
  • uuid有多个版本,包括时间戳(v1),随机数(v4),命名空间(v3,v5)
  • 永远没有最佳的技术方案,只要最适合业务场景的技术方案



相关文章
|
前端开发 程序员
#yyds干货盘点# 前端歌谣的刷题之路-第十五题-段落标识
#yyds干货盘点# 前端歌谣的刷题之路-第十五题-段落标识
77 0
#yyds干货盘点# 前端歌谣的刷题之路-第十五题-段落标识
|
30天前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
127 2
|
30天前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
37 0
|
30天前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
30天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
30天前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
|
30天前
|
前端开发 算法 测试技术
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
本文对比测试了通义千文、文心一言、智谱和讯飞等多个国产大模型在处理基础计数问题上的表现,特别是通过链式推理(COT)提示的效果。结果显示,GPTo1-mini、文心一言3.5和讯飞4.0Ultra在首轮测试中表现优秀,而其他模型在COT提示后也能显著提升正确率,唯有讯飞4.0-Lite表现不佳。测试强调了COT在提升模型逻辑推理能力中的重要性,并指出免费版本中智谱GLM较为可靠。
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
|
2月前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
3月前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
40 0
|
5月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
94 2