3

Sqids: 简短唯一ID生成器

 1 week ago
source link: https://colobu.com/2024/05/05/Sqids-short-unique-identifiers-generators/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Sqids(发音为squids, 鱿鱼)是一个开源库,允许您从数字中生成简短的唯一且看起来随机的标识符, 而且这些ID是URL安全的,你可以同时编码几个数字, 也可以剔除常见的脏话或者政治敏感的单词。你可以把它想象成一个十进制到十六进制的转换器,但它还具备一些额外的功能。
比如:https://example.com/Lqj8a0

先前它叫做Hashids, 但是由于商标问题,我不得不更改名称。Sqids是Short Quick Unique Identifiers的缩写。

为什么需要简短的唯一ID

适合场景

  • 为日志生成唯一的事件 ID
  • 为网站上的产品/对象生成 ID(如 YouTube 为视频所做的那样)
  • 为文本消息生成短 ID
  • 电子邮件中的确认码
  • 商品优惠码
  • 起止时间戳合并缩写
  • 地理位置编码
  • 临时的token

不适合场景

  • 任何敏感数据
  • 生成的 ID 不是哈希值,可以解码回数字。例如,它们可能不是用户 ID 的好选择,因为一旦解码,它们可能会泄露你的应用程序的用户数量

Sqids的特性

🆔 从非负数字生成短 ID
✅ 易于编码和解码
🫣 自动生成的 ID 不包含常见的禁用词
🎲 支持通过打乱字母顺序来自定义 ID
🥳 44个语言库, 比如Go、Rust、C、C++、Bash、Java、Python、JavaScript等
📌 每个版本都生成相同的 ID
🍻 带有宽松许可的小型库 (MIT许可)

Sqids 你可以可以自定义字母表。更长的字母表产生的ID更短,更短的字母表产生的ID更长。默认字母表包含大写和小写字母,因此默认ID是区分大小写的。

使用同样的输入和相同的字母表,生成的ID是唯一的。

Sqids可以将一个或多个非负数编码为单个ID。您可以编码的数字数量没有限制,但可以编码的数字大小有限(取决于实现语言)。
比如您可以编码开始时间和结束时间的UNIX时间戳为一个ID,或者您可以将数据库分片号与主键一起编码,并节省额外的数据库查询。

Sqids 有什么限制

  • Sqids 不能编码负数。
  • 最小字母表长度是 3 个字符。
  • 字母表中不能包含任何多字节字符。
  • Sqids 不能生成固定长度的 ID,只能生成至少达到某个长度的 ID。最小长度参数范围在 0 到 255 之间。
  • Sqids 可以尝试重新生成长度最多为字母表长度减一的 ID。

屏蔽列表可以防止某些单词出现在您的 ID 中。这是有益的,因为生成的 ID 可能会出现在公共场所,如 URL 中。

Sqids 附带了一个默认屏蔽列表,其中包含了几种语言中最基本的不雅和不当词汇。当然,您也可以用自己的词汇来扩展这个屏蔽列表。

屏蔽列表中的单词匹配是不区分大小写的。

少于 3 个字符的短单词不会被屏蔽。长度为 3 个字符的单词必须与 ID 完全匹配。如果 4 个或更多字符的单词是 ID 的子字符串,则会触发匹配。

如果屏蔽列表中的单词包含数字(leet 术语),则只有当它们位于 ID 的开头或结尾时才会触发匹配。

ID 是否合法

解码 ID 通常会产生某种数值输出,但这并不一定意味着该 ID 是规范的。为了检查 ID 是否有效,您可以重新编码解码后的数字,并检查 ID 是否匹配。

不自动执行此操作的原因是,如果将来默认屏蔽列表发生更改,我们不希望自动使过去生成的、现在可能与新屏蔽列表单词匹配的 ID 失效。

官方提供了一个Go语言的库:sqids/sqids-go

以下是一个简单的示例:

package main
import (
"fmt"
"time"
"github.com/sqids/sqids-go"
func main() {
s, _ := sqids.New()
id, _ := s.Encode([]uint64{1234567890}) // "PcHfYmv"
fmt.Println(id)
start := time.Now().Unix()
end := time.Now().Add(24 * time.Hour).Unix()
id, _ = s.Encode([]uint64{uint64(start), uint64(end)}) // "s6eUn008oGU27p"
fmt.Println(id)
numbers := s.Decode(id) // [1714879533 1714965933]
fmt.Println(numbers)

New函数还提供额外的参数,用来定制字母表、最小长度和黑名单:

type Options struct {
Alphabet string
MinLength uint8
Blocklist []string
s, _ := sqids.New(sqids.Options{
Alphabet: "FxnXM1kBN6cuhsAvjW3Co7l2RePyY8DwaU04Tzt9fHQrqSVKdpimLGIJOgb5ZE",
id, _ := s.Encode([]uint64{1, 2, 3}) // "B4aajs"
numbers := s.Decode(id) // [1, 2, 3]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK