【问题标题】:Generating Base 64 IDs生成 Base 64 ID
【发布时间】:2016-04-29 14:45:13
【问题描述】:

我认为这个问题主要是基于意见的,但是,出于安全原因,我已经为我的数据库表的可见 ID 列创建了自己的 Base64 ID 生成器,(我看到了 video 为何 YouTube 这样做和尽管我看到其他可能没有问题的安全方式,但这是有道理的)。它可以处理不太可能出现重复的事件,但是,我很想知道这是否被用作 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. 或者他们是否在代码中使用 Base64Encode 而不是自动生成它。

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

更新

我让两个控制台在周末运行,一个使用List,另一个使用HashSet,处理的记录之间的差异在另一个层面上。所以我把上面的代码改成了HashSet而不是List,并将代码设置为自动运行。

【问题讨论】:

    标签: c# database-design youtube base64


    【解决方案1】:

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

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

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

    我认为,一旦数字变大,可以将其拆分为二叉树以充分利用它,一旦每个块例如 100k 或百万达到 50% 或 60% 的使用率,忘记其余部分并移动到下一个范围。

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

    【讨论】:

      猜你喜欢
      • 2017-02-14
      • 2017-06-16
      • 2017-05-31
      • 2011-04-03
      • 2021-01-03
      • 2015-08-09
      • 1970-01-01
      • 2014-11-30
      • 2018-11-17
      相关资源
      最近更新 更多