生成Base 64 ID

时间:2016-04-29 14:45:13

标签: c# database-design youtube base64

我认为这个问题主要是基于意见的,但是,出于安全原因,我已经为我的数据库表的可见ID列创建了自己的Base64 ID生成器(我看到video为什么YouTube会这样做虽然我认为其他安全方式可能并不存在问题,但它仍然有意义。它处理 HIGHLY 不太可能发生重复的事件,但是,我很想知道这是否被用作YouTube视频ID的标准。

Program.cs的

class Program
{
    static void Main(string[] args)
    {
        var ids = new HashSet<string>();
        var count = 0; // for testing only
        while (count < 8)
        {
            ids.Add(Base64Id.GenerateId(ids));
            Console.ReadLine();
            count++; // for testing only
        }
    }
}

Base64Id.cs

public static class Base64Id
{
    private static int IdSize = 1; // Should be 11
    private static readonly string[] AllowedChars = {
        "0", "1", "2", "3", "4", "5", "6", "7"//,
        //"8", "9", "a", "b", "c", "d", "e", "f",
        //"g", "h", "i", "j", "k", "l", "m", "n",
        //"o", "p", "q", "r", "s", "t", "u", "v",
        //"w", "x", "y", "z", "A", "B", "C", "D",
        //"E", "F", "G", "H", "I", "J", "K", "L",
        //"M", "N", "O", "P", "Q", "R", "S", "T",
        //"U", "V", "W", "X", "Y", "Z", "-", "_"
    };

    private static Random _random = new Random();

    /// <summary>
    /// To generate a Base64 ID and check to make sure the ID is not already in use.
    /// </summary>
    /// <param name="usedIds">List of IDs already in use from the Database or other source.</param>
    /// <returns>New Base64 ID</returns>
    public static string GenerateId(HashSet<string> usedIds)
    {
        var autoGenId = "";

        do
        {
            autoGenId = "";
            for (var i = 0; i < IdSize; i++)
                autoGenId += GetRandomChar();
#if DEBUG
            _DEBUG_(usedIds.Count() + 1, autoGenId);
#endif
        }
        while (IsTaken(autoGenId, usedIds));

        return autoGenId;
    }

    private static string GetRandomChar()
    {
        var i = _random.Next(0, AllowedChars.Length);
        return AllowedChars[i];
    }

    private static bool IsTaken(string id, HashSet<string> usedIds)
    {
        var check = usedIds.Any(i => id.Contains(i));
        if (check)
            return true;


        return false;
    }

    private static void _DEBUG_(int count, string id)
    {
        Console.WriteLine(String.Format("{0}:\t{1}", count, id));
    }
}

我相信这对于我的目的来说就像一个魅力,并且没有任何问题,就像在测试期间那样。 然而,一旦我将其缩小到8个字符并且ID大小为长度1,由于在8个预期输出中只有6个发生后不断循环,它会引发严重错误。

我知道这是来自每次被击中的随机数,而且可供选择的次数越少,循环就越可能发生。

我知道如何解决这个问题,但是按照我计划的规模,想到这个很疯狂,例如拥有一个包含所有可能性的数组/列表并删除所选ID。

这是我的问题;

  
      
  1. Youtube之类的人是否知道这个问题,并且由于可能的ID大小而不在乎。
  2.   
  3. 他们在课堂上有更多的想法。
  4.   
  5. 他们不关心如此高数字的处理成本,并处理每一个小细节。
  6.   
  7. 或者他们在代码中使用Base64Encode而不是自动生成它。
  8.   

我想知道您对如何改进代码的意见和建议,或者甚至是如此重要的数字。我已经回答了我认为可能的改进方法。

更新

我在周末离开了两个游戏机,一个使用List,另一个使用HashSet,处理过的记录之间的差异在另一个层面上。因此,我已将上述代码更改为HashSet而不是List,并将代码设置为自动运行。

1 个答案:

答案 0 :(得分:1)

我认为,对于可能的ID数量,不需要进行大量的处理,以确保ID是唯一的,因为有 73,786,976,294,838,206,464,它会进一步到达列表的末尾。 可能性。

说十个可能的ID 1 - &gt; 10,如果已经选择了2,那么下一次,它有20%的可能性被复制,如果选择了8,则有80%的几率,每次。使用概率,这将叠加并降低获得唯一ID的机会。

一旦数字很低,这很安静,第一次需要14539279次迭代,第二次需要662984次迭代才能显示所有8个唯一ID。数字越大,我知道要达到这个突破点需要更长的时间,但情况会更糟。

我认为,一旦数字变得更大,可以将其拆分为二叉树,以便充分利用它,一旦说每个块几十万或百万达到50%或60%的使用,忘记其余的和进入下一个范围。

我认为这可能是尝试加速处理可能列表后期阶段的唯一ID的好方法。