生成人类可读/可用的、简短但惟一的 ID

  • 每天需要处理大于1000但小于10000个新记录

  • 不能使用 GUID/UUID,自动增量号码等。

  • 理想情况下应该是5或6个字符长,当然可以是 alpha

  • 希望重用现有的,众所周知的算法,如果可用

外面有什么吗?

71928 次浏览

Tinyurl 和 bit.ly 使用基数62作为缩写 URL。这是一种创建“唯一”、人类可读的 ID 的众所周知的方法。当然,您必须存储创建的 ID,并在创建时检查是否有重复的 ID,以确保惟一性(见答案底部的代码)

基62唯一性度量

以62为基数的5个字符将给出62 ^ 5个惟一 ID = 916,132,832(? 10亿) 每天10000的身份证,91000多天都没问题

以62为基数的6个字符将给出62 ^ 6个惟一 ID = 56,800,235,584(56 + 十亿) 每天10000个身份证,5百多万天都没问题

基本36唯一性度量

6个字符将给出36 ^ 6个唯一 ID = 2,176,782,336(2 + 十亿)

7 chars will give you 36^7 unique IDs = 78,364,164,096 (78+ billion)

密码:

public void TestRandomIdGenerator()
{
// create five IDs of six, base 62 characters
for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase62(6));


// create five IDs of eight base 36 characters
for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase36(8));
}


public static class RandomIdGenerator
{
private static char[] _base62chars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
.ToCharArray();


private static Random _random = new Random();


public static string GetBase62(int length)
{
var sb = new StringBuilder(length);


for (int i=0; i<length; i++)
sb.Append(_base62chars[_random.Next(62)]);


return sb.ToString();
}


public static string GetBase36(int length)
{
var sb = new StringBuilder(length);


for (int i=0; i<length; i++)
sb.Append(_base62chars[_random.Next(36)]);


return sb.ToString();
}
}

产出:

z5KyMg
wd4SUp
uSzQtH
UPrGAT
UIf2IS


QCF9GNM5
0UV3TFSS
3MG91VKP
7NTRF10T
AJK3AJU7

我推荐使用 http://hashids.org/将任意数字(例如 DB ID)转换为字符串(使用 salt)。

它允许将这个字符串解码回数字。 因此您不需要将它存储在数据库中。

Has libs for JavaScript, Ruby, Python, Java, Scala, PHP, Perl, Swift, Clojure, Objective-C, C, C++11, Go, Erlang, Lua, Elixir, ColdFusion, Groovy, Kotlin, Nim, VBA, CoffeeScript and for Node.js & .NET.

我有与 OP 类似的要求。我研究了可用的图书馆,但大多数都是随机的,我不想那样。我不能真正找到任何东西,不是基于随机的,仍然很短... 所以我结束了滚动我自己的基于 the technique Flickr uses,但修改,需要更少的协调,并允许更长的时间离线。

简而言之:

  • 中央服务器发出由32个 ID 组成的 ID 块
  • The local ID generator maintains a pool of ID blocks to generate an ID every time one is requested. When the pool runs low it fetches more ID blocks from the server to fill it up again.

缺点:

  • Requires central coordination
  • ID 或多或少是可预测的(比普通的 DB id 少,但它们不是随机的)

好处

  • 保持在53位内(Javascript/PHP 整数的最大大小)
  • Very 短 ID
  • 36进制编码,非常便于人类阅读,书写和发音
  • ID 可以在需要再次与服务器联系之前在本地生成很长一段时间(取决于池设置)
  • 理论上没有碰撞的可能

我已经为客户端发布了一个 Javascript 库,以及一个 JavaEE 服务器实现。用其他语言实现服务器也应该很容易。

以下是这些项目:

Suid - 分布式服务-唯一的 ID,简短和甜蜜

Java EE 技术栈的 Suid-server-Java -Suid-server 实现。

这两个图书馆都有自由知识共享的开源许可证。 Hoping this may help someone else looking for short unique IDs.

I used base 36 when I solved this problem for an application I was developing a couple of years back. I needed to generate a human readable reasonably unique number (within the current calendar year anyway). I chose to use the time in milliseconds from midnight on Jan 1st of the current year (so each year, the timestamps could duplicate) and convert it to a base 36 number. If the system being developed ran into a fatal issue it generated the base 36 number (7 chars) that was displayed to an end user via the web interface who could then relay the issue encountered (and the number) to a tech support person (who could then use it to find the point in the logs where the stacktrace started). A number like 56af42g7 is infinitely easier for a user to read and relay than a timestamp like 2016-01-21T15:34:29.933-08:00 or a random UUID like 5f0d3e0c-da96-11e5-b5d2-0a1d41d68578.

我真的很喜欢简单地使用 Base64格式编码 GUID,并截断后面的 = = 以获得一个22个字符的字符串(它只需要一行代码,您总是可以将其转换回 GUID)。 遗憾的是,它有时包含 + 和/字符。对于数据库来说还可以,对于 URL 来说不是很好,但是它帮助我欣赏了其他的答案: -)

来自 https://www.codeproject.com/Tips/1236704/Reducing-the-string-Length-of-a-Guid的 Christiaan van Bergen

我们发现将 Guid (16字节)转换为 ASCII 使用 Base64的表示导致了 < strong > 可用且仍然独特 MessageID 只有22个字符。

var newGuid = Guid.NewGuid();
var messageID = Convert.ToBase64String(newGuid.ToByteArray());


var message22chars = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0,22);

例如: Guid‘ e6248889-2a12-405a-b06d-9695b82c0a9c’(string Length: 36)将得到 Base64表示形式: ‘ iYgk5hIqWkCwbZaVuCwKnA = =’(字符串长度: 24)

Base64表示以’= =’字符结束 just truncate these, without any impact on the uniqueness. Leaving you 标识符的长度仅为22个字符。