嗯……这就是我的 CS 知识让我失望的地方。我想编写一个生成唯一参考号的算法。
我不想使用序列号,因为它们会带来安全风险,我想使用字母数字。ref 也将具有最小和最大长度。(我不能使用 GUID 它太长了)
理想情况下,我不想查询我的持久层以查看以前是否使用过 ref。
我可以采用什么策略?
嗯……这就是我的 CS 知识让我失望的地方。我想编写一个生成唯一参考号的算法。
我不想使用序列号,因为它们会带来安全风险,我想使用字母数字。ref 也将具有最小和最大长度。(我不能使用 GUID 它太长了)
理想情况下,我不想查询我的持久层以查看以前是否使用过 ref。
我可以采用什么策略?
如果您担心安全风险,那么您需要一个加密安全的随机数生成器。您应该能够告诉它您想要多少字节(即数字可以有多长)。
If this number will be ever be referenced by humans, I encourage you to follow these guidelines in your solution:
What is the best format for a customer number, order number?
If you can't synchorize with the database to see what the next number will be, and you can't use GUIDs or a comparably long random string, then you need to include some sort of local value in the ID.
e.g., if all clients will be on a known network, you can end each number in each client's ip address D block.
Or, if clients have to login and each user can login only once at a time, you can include their userid in the number somewhere.
我在这里暗中尝试,但是...您想要一个唯一的随机值,但小于 16 个字节。你最好的选择仍然是一个只有 16 个字节的 GUID……你想使用字母数字所以……一些选项。
使用 GUID,但将其编码为 base64,看起来像 7QDBkvCA1+B9K/U0vrQx1A,它是 22 个字节,仍然比本机 Guid 长……但比典型的字符串表示形式短。
请参阅此处的文本编码:http ://en.wikipedia.org/wiki/Globally_Unique_Identifier
另一种选择是对 Guid 进行哈希处理,但您会失去一些唯一性,那么您对非唯一项目的容忍度是多少?
==========
假设您有一个插入表的进程,您可以使用 HiLo 算法并确信您不必每次都访问数据库。您只需将最后一个高值存储在内存中......当进程启动时,您将访问数据库以找出您停止的位置:什么是 Hi/Lo 算法?
我仍然说 Guid 是您最好的选择....16 字节还不错,并且与您想出的大多数字母数字解决方案一样小。
一种方法可能是基于较小的数字子集生成数字。例如,您可以使用基于 godel 编号的二进制序列来生成。例如,在 5z、3y、2x 上将 000 映射到 111 会产生 0、2、3、6、5、10、15、30。
当然,这过于简单化了。但是通过迭代“盐”数字来生成参考编号,您根本不必跟踪参考编号。前提是,或者当然,你有理由确定你不必考虑碰撞。
如果可能在您的应用程序/环境中,您是否考虑将时间作为一部分添加到伪随机生成的数字中?
即 microtime() + rand(10000,99999)
我一直在成功的生产系统中这样做:
把它放在内存中,或者作为一个字符串,或者将这些值放在一起或类似的东西。然后:
请注意,将 UID 缩小到 N 字节会增加 UID 冲突的机会。
第一个列表中的所有输入数据是为了确保如果您有一个由许多计算机组成的集群,您可以获得一个唯一的散列基础。您可以省略其中的一些,但您必须确定它包含的内容对于您将在其上生成 UID 的每台计算机都不同。
将 GUID 截断为所需的大小。
如果您正在生成数字,除非它们是随机且巨大的,否则您最好检查它们是否已被使用。