我正在寻找一种能够生成适合两者的标识符的算法,例如在外部使用。 URL以及具有以下要求的持久性:
我查看了各种解决方案,但我发现的所有解决方案都有一些重要的权衡。例如:
修改:为什么这个标题偏离主题?这些要求描述了可以提供许多合法解决方案的特定问题。事实上,这里的一些解决方案非常好,我很难选择一个标记作为答案。
答案 0 :(得分:5)
如果可能的话,我会保持用户要求(简短,可读)和数据库要求(增量,快速索引)分开。面向用户的需求发生变化。您不希望修改表格,因为明天您决定更改面向用户ID的长度或其他细节。
一种方法是使用用户友好的字符生成您的ID,例如
23456789ABCDEFGHJKLMNPQRSTUVWXYZ
并随便随意。
但是,当插入数据库时,不要将该值作为它引用的记录的主键,甚至将其存储在该表中。使用标识主键将其插入自己的表中,然后将int
或bigint
键存储到您的记录中。
这样您的主表可以拥有增量主键。如果您需要通过其友好的"来引用记录。然后你加入你的友好身份证表。
我的猜测是,如果您生成足够多的这些ID,而您又关注索引性能,那么人类用户检索这些值的速度将会低很多。因此,友好ID表中随机值的稍微慢一点的查找不会成为问题。
答案 1 :(得分:1)
以下使用已知唯一的ID(因为它来自关系数据库中的唯一ID列)和随机的字母和数字序列来生成令牌:
public static string GenerateAccessToken(string uniqueId) // generates a unique, random, and alphanumeric token
{
const string availableChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
using (var generator = new RNGCryptoServiceProvider())
{
var bytes = new byte[16];
generator.GetBytes(bytes);
var chars = bytes.Select(b => availableChars[b % availableChars.Length]);
var token = new string(chars.ToArray());
return uniqueId + token;
}
}
保证令牌既是唯一的又是随机的(或者至少是"伪随机")。您可以通过更改bytes
的长度来操纵长度。
避免混淆" 0"和" O"或" l"和" 1",您可以从availableChars
删除这些字符。
修改强>
我刚刚意识到这并没有通过"没有数据库检查"要求,虽然当我使用这样的代码时,我总是已经在内存中有一个我知道包含唯一ID的实体,所以我希望这同样适用于你的情况。我不认为可以完全满足您的所有要求,所以我希望这仍然是属性的良好平衡。
答案 2 :(得分:1)
您是否尝试过提示?
Proquint是一个PRO-nouncable QUINT-uplet,交替明确的辅音和元音,例如:" lusab"。
我认为他们几乎满足了你的所有要求。
我已经在.NET的端口上工作,您可以将其下载为Proquint.NET。
答案 3 :(得分:0)
我之前实施的一个简单的解决方案并不能满足您的所有约束条件,但如果您对问题的看法略有不同,则可能会被接受。
首先,我使用了一个函数来篡改数据库ID func(id) => y
和func(y) => id
。 (我使用了Feistel cipher,here是实现这样一个函数的一个例子。)其次,将obfusticated id转换为base 62,使其变短并且对url友好。 (您可以使用较小的字符集来实现人性化)这将创建从数据库ID到字符串标识符的一对一映射。在我的实现中,1,2相应地映射到2PawdM,5eeGE8,我可以从字符串2PawdM和5eeGE8获得数据库ID 1,2。当您使用不同的obfustication函数时,映射可能完全不同。
使用此解决方案,标识符本身不是增量,但是,因为标识符直接映射到数据库ID,所以您可以计算相应的数据库ID,并直接在id列上执行任何数据库查询。您不需要生成字符串标识符并将其存储到数据库,当您使用自动递增的id列存储记录时,数据库本身可以保证唯一性。