前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >轻量、安全的唯一 ID 生成器 NanoID

轻量、安全的唯一 ID 生成器 NanoID

原创
作者头像
轻量级云原生架构实验室
发布2022-12-20 22:42:46
2.5K0
发布2022-12-20 22:42:46
举报
文章被收录于专栏:轻量级微服务轻量级微服务

Nano ID

一个小巧、安全、URL友好、唯一的 JavaScript 字符串 ID 生成器。

  • 小巧:130 bytes (已压缩和 gzipped), 没有依赖,Size Limit 控制大小;
  • 快速:它比 UUID 快 60%;
  • 安全:它使用加密的强随机 API,可在集群中使用;
  • 紧凑:它使用比 UUID(A-Za-z0-9_-)更大的字母表,因此,ID 大小从 36 个符号减少到 21 个符号;
  • 易用:Nano ID 已被移植到 20种编程语言
代码语言:javascript
复制
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

支持现代浏览器、IE 使用 Babel、Node.js 和 React Native。

undefined

undefined

undefined

与 UUID 的比较

Nano ID 与 UUID v4 (基于随机) 相当。它们在 ID 中有相似数量的随机位(Nano ID 为126,UUID 为122),因此它们的冲突概率相似::

要想有十亿分之一的重复机会,必须产生 103万亿 个版本4的 ID 。

Nano ID 和 UUID v4之间有三个主要区别:

  1. Nano ID 使用更大的字母表,所以类似数量的随机位被包装在 21 个符号中,而不是36个。
  2. Nano ID 代码比 uuid/v4 包少 4 倍:130 字节而不是 483 字节.
  3. 由于内存分配的技巧,Nano ID 比 UUID 快 60%

基准值

代码语言:rust
复制
$ node ./test/benchmark.js
crypto.randomUUID         25,603,857 ops/sec
@napi-rs/uuid              9,973,819 ops/sec
uid/secure                 8,234,798 ops/sec
@lukeed/uuid               7,464,706 ops/sec
nanoid                     5,616,592 ops/sec
customAlphabet             3,115,207 ops/sec
uuid v4                    1,535,753 ops/sec
secure-random-string         388,226 ops/sec
uid-safe.sync                363,489 ops/sec
cuid                         187,343 ops/sec
shortid                       45,758 ops/sec

Async:
nanoid/async                  96,094 ops/sec
async customAlphabet          97,184 ops/sec
async secure-random-string    92,794 ops/sec
uid-safe                      90,684 ops/sec

Non-secure:
uid                       67,376,692 ops/sec
nanoid/non-secure          2,849,639 ops/sec
rndm                       2,674,806 ops/sec

测试配置: ThinkPad X1 Carbon Gen 9, Fedora 34, Node.js 16.10.

安装

代码语言:shell
复制
npm install --save nanoid

Nano ID 提供 ES 模块:

代码语言:javascript
复制
import { nanoid } from 'nanoid'

API

Nano ID 有 3 个 API:正常(阻塞)、异步、和不安全。默认情况下,Nano ID 使用 URL 友好的符号(A-Za-z0-9_-)并返回一个有21个字符(类似 UUID v4 的冲突概率)的 ID 。

阻塞

使用 Nano ID 最安全、最简单的方法。在极少数情况下,噪声收集时可能会阻止 CPU 执行其他工作用于硬件随机发生器。

代码语言:javascript
复制
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

如果你想要减小 ID size(但是会增加冲突概率),可以将 size 作为参数传递。

代码语言:javascript
复制
nanoid(10) //=> "IRFa-VaY2b"

异步

代码语言:javascript
复制
import { nanoid } from 'nanoid/async'

async function createUser () {
  user.id = await nanoid()
}

undefined

不安全

代码语言:javascript
复制
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

自定义字母或大小

customAlphabet 允许您使用自己的字母表创建 nanoid 和 ID size。

代码语言:javascript
复制
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"

自定义随机字节生成器

customRandom 允许您创建一个 nanoid 并替换字母表和默认的随机字节生成器。

在此示例中,使用基于种子的生成器:

代码语言:javascript
复制
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return (new Uint8Array(size)).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

random 回调必须接受数组大小并返回随机数的数组。如果要使用与 customRandom 相同的URL友好符号, 你可以使用 urlAlphabet 获取默认字母表。

代码语言:javascript
复制
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

异步和非安全 API 不适用于 customRandom

用法

React

目前还没有将 nanoid 用于 React key prop 的正确方法

因为它在不同的渲染中应该是一致的。

代码语言:html
复制
function Todos({todos}) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={nanoid()}> /* 不要这样做 */
          {todo.text}
        </li>
      ))}
    </ul>
  )
}

您应该尝试在列表项中找到稳定的 id。

代码语言:html
复制
const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
)

如果您没有稳定的 ID,您最好使用索引作为 而不是 nanoid()

代码语言:html
复制
const todoItems = todos.map((text, index) =>
  <li key={index}> /* 仍然不推荐,但优于 nanoid()。
                      仅当项目没有稳定ID时才执行此操作。 */
    {text}
  </li>
)

React Native

React Native 没有内置的随机生成器。下面的 polyfill 适用于普通 React Native 和从 39.x 开始的 Expo。

  1. 检查 react-native-get-random-values 文档并安装它。
  2. 在 Nano ID 之前导入它。
代码语言:javascript
复制
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

undefined

PouchDB and CouchDB

在 PouchDB 和 CouchDB 中,ID 不能以下划线 _ 开头。需要一个前缀来防止这个问题,因为 Nano ID 可能在默认情况下使用 _ 作为 ID 的开头。在默认情况下,在 ID 的开头使用 _

用下面的选项覆盖默认的 ID。

代码语言:javascript
复制
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

可以通过调用 npx nanoid 在终端获得唯一的 ID。

代码语言:shell
复制
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

如果你想改变字母或 ID size,应该使用 nanoid-cli

undefined

其他编程语言

Nano ID 已被移植到许多语言。 你可以使用下面这些移植,获取在客户端和服务器端相同的ID生成器。

其他方式生成 ID

代码语言:javascript
复制
new Date().getTime().toString(36).concat(performance.now().toString(), Math.random().toString()).replace(/\./g,"")

相关讨论:https://gist.github.com/gordonbrander/2230317

工具

  • ID size 计算器 显示调整时的冲突概率 ID 的字母或size。
  • nanoid-good 以确保你的ID不包含任何淫秽词汇。

undefined

undefined

相关资料

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Nano ID
    • 与 UUID 的比较
      • 基准值
        • 安装
          • API
            • 阻塞
            • 异步
            • 不安全
            • 自定义字母或大小
            • 自定义随机字节生成器
          • 用法
            • React
            • React Native
            • PouchDB and CouchDB
            • CLI
            • 其他编程语言
            • 其他方式生成 ID
            • 工具
            • 相关资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档