2008-12-10 52 views
6

Hrm ...这里是我的CS知识让我失望的地方。我想编写一个算法来生成一个唯一的参考号。生成唯一的参考号码策略

我不想使用连续数字,因为它们引入了安全风险,我想使用 字母数字。裁判也有一个最小和最大长度。 (我不能使用一个GUID它太长)

理想情况下,我不想查询我的持久层,以查看是否之前使用过ref。

我可以采用哪些策略?

+0

为什么序列号会成为安全风险? – Juliet 2008-12-10 17:26:57

+0

因为你可以猜测下一个数字是什么。想象一下,如果您的银行按顺序分配了帐号......您可以轻松找到一系列帐号。 – JoshBerke 2008-12-10 17:38:50

回答

2

如果您担心安全风险,那么您需要一个密码安全的随机数生成器。你应该能够告诉它你想要多少字节(即数字可以多长)。

2

如果这个数字将永远是被人引用,我鼓励你遵循这些准则在您的解决方案:

What is the best format for a customer number, order number?

如果你不能与数据库synchorize,看看下一个数将是,并且您不能使用GUID或一个相对较长的随机字符串,那么您需要在ID中包含某种本地值。

例如,如果所有的客户端都在一个已知的网络上,则可以结束每个客户端的IP地址D块中的每个号码。

或者,如果客户端必须登录并且每个用户一次只能登录一次,则可以在其中的某个编号中包含其用户标识。

-1

将GUID截断为所需的大小。

如果你正在生成数字,除非它们是随机的和巨大的,否则你最好检查它们是否被使用过。

1

我在黑暗中刺穿了这里,但是......你想要一个随机值,它将是唯一的,但少于16个字节。你最好的选择仍然是一个只有16字节的GUID ....你想使用字母数字......所以有些选项。

使用一个GUID,但对其进行编码base64看起来像7QDBkvCA1 + B9K/U0vrQx1A这是22个字节,它仍然是一个本地GUID ...但比典型的字符串表示更短。

见文本编码这里:http://en.wikipedia.org/wiki/Globally_Unique_Identifier

另一种选择是散列的GUID,但是你将失去一些独特性,该怎么在这里是你的容忍水平非唯一的项目吗?

==========

假设你有一个单一的过程中插入你可以emlpoyee一个高住低训algorithim并相信你不必每次都打DB表。你只是在内存中存储最后一个高值...当进程启动时,你会去分贝找出你离开的地方:What's the Hi/Lo algorithm?

我还是说Guid是你最好的选择... .16字节并不差,并且会与您想出的大多数字母数字解决方案一样小。

0

一种方法可能是基于较小的数字子集生成数字。例如,您可以使用二进制序列根据godel编号生成。例如,在5z,3y,2x上将000映射到111会得到0,2,3,6,5,10,15,30。

当然,这太简单了。但通过迭代“盐”数字来生成参考数字,您根本不必跟踪参考数字。当然,如果你有理由相信你不需要考虑碰撞事故。

0

如果可能在您的应用程序/环境中,您是否考虑添加时间作为伪随机生成数字的一部分?

即microtime中()+兰特(10000,99999)

0

我一直在生产系统中成功这样做:

  • 以当前时间(UTC,与微秒级精度)
  • 你的进程ID,线程ID
  • 您的计算机名称
  • 盐值(基本上是一个独特的程序字符串)
  • 一个随机值(最好是加密级PRNG)

将它放在内存中,可以是字符串,也可以是XOR值或其他类似值。 然后:

  • 用例如SHA-1
  • 对生成的数字执行模N将输出缩小为N个字节
  • 转换为十六进制或可打印的内容(如果需要)。

请注意,将UID缩小到N个字节会增加发生UID冲突的机会。

第一个列表中的所有输入数据都是为了确保您获得散列的唯一基础,前提是您拥有多台计算机的集群。你可以省略其中的一些,但是你必须确定它包含的东西会使你生成UID的每台计算机都有所不同。