我目前正在开发注册系统原型。它非常简单,基本上只是一个.NET表单,可以写入MongoDB。
我所坚持的是为每个用户生成唯一ID /密钥的有效方法。这些ID必须是人类友好的,所以像7个字符长的字母数字字符串,例如A1B2C3X。
到目前为止我看到的解决方案只是使用一个简单的函数来生成随机字符串,然后检查数据库以查看它是否是唯一的(如果不重复,直到找到一个唯一的)。随着数据库条目数量的增加,这当然会变得越来越昂贵。
我的想法是预先计算唯一ID集并将其存储在另一个数据库中。然后,当我需要在用户数据库中添加一个新条目时,我可以从我的id数据库中“弹出”一个id(在常数时间内),并且知道它不存在于用户数据库中而不需要搜索它。
我确信有人必须先做过这样的事情。有没有更好的办法?我不知道为什么我为此苦苦挣扎。非常感谢您的意见。
答案 0 :(得分:11)
在应用程序中生成随机字符串并检查它是否唯一不是一个糟糕的解决方案。不要担心它效率低下,它不是 - 并且绝对不能与其他选择进行比较。它肯定比运行db.user.count()
或保留具有预先计算ID的单独表更快。你只需要做对。
首先,创建新用户的频率如何?可能不经常与其他事物相比,所以整个效率讨论真的没有实际意义。其次,有7个字符的A-Z,0-9这个范围是36 ^ 7或大约780亿。至少可以说,在你开始看到碰撞之前还需要一段时间。
如果您这样做,除非发生碰撞(极不可能),否则不会产生任何性能损失:
_id
getLastError
命令)。这种方式只会在发生碰撞时有额外的工作(而且我真的非常想强调这是多么不可能的事情)。
还有另一种生成唯一用户ID的方法:获取当前的UNIX时间戳(下至第二个),附加主机名的哈希值,然后附加进程ID,最后附加计数器的当前值。这实际上是如何生成Mongo的ObjectId
,并保证每个进程每秒可以生成尽可能多的对象,作为计数器的最大值(在Mongo中为3个字节,因此为1600万个)。如果您对详细信息感兴趣,请参阅ObjectId上的文档:http://www.mongodb.org/display/DOCS/Object+IDs
它具有以下属性:您的用户ID将按创建顺序自然排序,但它的长度为12个字节,因此比7个字符长一点,不幸的是。您可以使用相同的方法并跳过主机名/ pid,并将计数器(如果您愿意也可以是一个随机数)缩短为两个字节,那么您将减少到6个字节,这可能会被挤压到大约9个字节chars AZ,0-9。