是否有分布式密钥生成的GUID替代方案?

时间:2012-05-29 20:23:15

标签: c# .net database guid crc

我的情况是:

  1. 我有许多客户端应用程序,它们使用本地数据库(MS SQL,MS Access - 抱歉,这是Enterprise系统,我必须支持遗留...)
  2. 我不知道客户之间的任何趋势 - 现在它是~10但它可能 每年约100人。
  3. 来自这些表的数据来到我的中央服务器并放入一个公用表
  4. 有时现有(客户)数据已更改 - 我必须执行更新/删除操作
  5. 我不想使用GUID(.NET类型System.Guid) - 很难在MS Access上简单地实现和支持。此外,它是not good for performance
  6. 我需要快速搜索该公用表,因此最好使用intlong int作为PK
  7. 所以,我想:

    1. 避免碰撞的独特之处(它将用作PK)
    2. 应该有intlong int
    3. 插入前必须是可分配的客户端
    4. 我目前的解决方案是从以下连接中获取CRC:

      • ProcessodID
      • Bios日期
      • 用户名(字符串,硬件\用户相关数据)
      • DateTime.Now(UNC)

      目前它对我有用,但也许有更好的方法来实现我的目标? 您自己的任何评论,建议,示例或经验?

      更新:客户端和服务器之间的同步是定期操作,因此每天可以发生2-3次(它是配置变量)

4 个答案:

答案 0 :(得分:2)

如果来自多个表的数据来到一个中央表,并且您需要解决这些记录的更改,那么我的建议是使用两列作为您的中央表的PK。一列可以是来自客户端的标识字段(非唯一),一列可以是您分配给客户端应用程序的客户端代码(非唯一)。来自ID和客户端代码的聚合将是您的PK

此解决方案的优点是不需要对客户端应用程序进行任何更改(可能会将一些身份代码发送到您可以用于某些安全措施的中央服务器) 当然,如果客户群增长(希望如此),您需要为每个客户端保留一个集中的代码表。中心表上的搜索不应该是一个问题,因为您使用两个数字(或身份代码的短字符串)。

答案 1 :(得分:1)

您始终只需添加一个数字的PK列,并(根据您使用的数据库)设置序列或标识来处理它。

您还可以在当前拥有的多个列上创建索引,以帮助加快搜索速度。

答案 2 :(得分:1)

您可以实施key table

基本上,密钥表只是一个包含一条记录的表:下一个可用的整数键。当程序需要生成密钥时,它会增加密钥表中的密钥。它现在保留了以前可用的密钥。它可以将该键分配给它喜欢的任何键,并确保它不会与以相同方式拉出的任何其他键冲突。这是LightSpeed ORM默认工作的方式。它比使用内置标识列的好处是,您可以在将项目ID插入数据库之前分配它们,因此可以在一次插入所有项目之前定义项目关系。

如果您担心冲突,可以在读取和递增下一个可用密钥之前锁定/解锁密钥表。如果您知道需要一次插入多个项目,则可以将该键增加多少而不是多次增加。如果您猜测应用程序将来某个时候需要一定数量的密钥,您可以预留一系列顺序密钥,并在内部跟踪它们。如果您不全部分配密钥,这可能会浪费密钥,但可以防止对数据库的过度调用。

答案 3 :(得分:1)

只需使用int64密钥,在客户端使用负数递增数字,从0开始(从-1开始),然后在同步后使用正递增数字在服务器端,当您将数据从客户端同步到服务器时然后,您只需返回新的正面服务器端编号。我相信更新记录上的密钥很简单,如果没有,那么只需删除旧密码并插入一个带有值的新密钥。

这是一种非常简单的方法,可以获得客户端唯一密钥和可更新数据,而无需担心解决方案导致的问题,最好只是随机冲突,具体取决于您的crc检查的大小。

如果你没有使用GUID设置(MSDN用于System.Guid.NewGuid()表示MAC地址作为值的一部分并使它们非常独特)那么你的回答是复合键(而不是基于复合键的crc的键)!除非您拥有比128位GUID更多的熵,否则请不要认为您的CRC解决方案不太可能发生碰撞而不是GUID,您只需为自己做更多的工作。

正如我所指出的那样,你可以使用int64空间的整个负面谱来识别非同步的,因此是临时的唯一ID号。然后,在写入中央服务器时,您甚至可以获得聚集索引的额外潜在好处。

假设您的客户端数据键如下所示:

-5, -4, 76, 78, 79

这意味着需要将-4和-5插入到中心位置,然后将其ID更新为新值(在此示例中可能为8081)。

如果您想进一步了解GUID的唯一性和发生碰撞的可能性,我建议您阅读recent上的Eric Lippert的posts博客topic。至于Access方面,你可以只使用.ToString()并将它们转换为文本键。但是,由于我提供的解决方案适用于int / int64空间,因此不需要这样做。