生成人类可读/可用,简短但唯一的ID

时间:2012-03-03 05:19:22

标签: .net database identity

  • 需要处理> 1000但是<每天10000条新记录

  • 无法使用GUID / UUID,自动递增数字等。

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

  • 想重用现有的,众所周知的算法(如果有的话)

还有什么吗?

5 个答案:

答案 0 :(得分:95)

baseurl和bit.ly用于缩写的URL。这是一种易于理解的方法,用于创建“独特的”人类可读ID。 当然,您必须存储创建的ID并在创建时检查重复项以确保唯一性。 (请参阅答案底部的代码)

基本62唯一性指标

基地62中的5个字符将为您提供62 ^ 5个唯一ID = 916,132,832(~10亿) 每天10k ID,你可以获得91k +天

基础62中的6个字符将为您提供62 ^ 6个唯一ID = 56,800,235,584(56亿以上) 每天10k ID,您可以获得超过500万天

基本36个唯一性指标

6个字符将为您提供36 ^ 6个唯一ID = 2,176,782,336(2亿个)

7个字符将为您提供36 ^ 7个唯一ID = 78,364,164,096(780亿)

<强>代码:

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

答案 1 :(得分:14)

我建议将http://hashids.org/转换为字符串(使用salt)。

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

包含JavaScript,Ruby,Python,Java,Scala,PHP,Perl,Swift,Clojure,Objective-C,C,C ++ 11,Go,Erlang,Lua,Elixir,ColdFusion,Groovy,Kotlin,Nim的库,VBA,CoffeeScript和Node.js&amp; .NET。

答案 2 :(得分:6)

我有与OP相似的要求。我查看了可用的库,但大多数是基于随机性,我不想要它。我真的找不到任何基于随机而且仍然很短的东西...所以我最终根据the technique Flickr uses滚动自己,但修改为需要较少的协调并允许更长时间离线。

简而言之:

  • 中央服务器发出ID块,每个ID块包含32个ID
  • 本地ID生成器维护一个ID块池,以便在每次请求时生成ID。当池运行不足时,它会从服务器中获取更多ID块以再次填充它。

缺点:

  • 需要中央协调
  • ID或多或少是可预测的(不如常规数据库ID,但它们不是随机的)

优点

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

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

以下是项目:

suid - 分布式服务 - 短而甜的唯一ID

suid-server-java - Java EE技术堆栈的Suid服务器实现。

这两个库都可以在自由的Creative Commons开源许可下使用。 希望这可以帮助其他人寻找简短的唯一ID。

答案 3 :(得分:3)

当我为几年前开发的应用程序解决了这个问题时,我使用了 base 36 。我需要生成人类可读的合理唯一数字(无论如何在当前日历年内)。我选择使用从当年1月1日午夜开始的时间(因此每年,时间戳可以重复)并将其转换为基数为36的数字。如果正在开发的系统遇到致命问题,它会生成通过Web界面向最终用户显示的基本36号码(7个字符),然后可以将遇到的问题(和号码)转发给技术支持人员(谁然后可以使用它来查找堆栈跟踪开始的日志中的点)。对于用户来说,像 56af42g7 这样的数字比 2016-01-21T15:34:29.933-08:00 或随机UUID等时间戳更容易阅读和中继的 5f0d3e0c-da96-11e5-b5d2-0a1d41d68578

答案 4 :(得分:0)

我真的很喜欢仅使用Base64格式编码GUID并截断尾随==以获得22个字符的字符串的简便性(它需要一行代码,并且您始终可以将其转换回GUID)。 可悲的是,它有时包含+和/字符。对于数据库来说还可以,对于URL来说不是很好,但是它帮助我理解了其他答案:-)

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

我们发现将Guid(16字节)转换为ASCII 使用Base64表示法会导致可用且仍然唯一 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'(字符串 长度:36)将获得Base64表示形式: 'iYgk5hIqWkCwbZaVuCwKnA =='(字符串长度:24)

Base64表示形式以'=='字符结尾。你可以 只需将它们截断,而不会影响唯一性。离开你 标识符只有22个字符。