什么是Hi / Loalgorithm?

什么是Hi / Loalgorithm?

我在NHibernate文档中find了这个(这是一个生成唯一键的方法,第5.1.4.2节),但是我还没有find一个很好的解释。

我知道Nhibernate处理它,我不需要知道里面,但我只是好奇。

基本的想法是你有两个数字组成一个主键 – “高”号和“低”号。 一个客户端基本上可以增加“高”序列,知道它可以安全地生成具有各种“低”值的前一个“高”值的整个范围内的键。

例如,假设您有一个“高”序列,当前值为35,“低”数字在0-1023范围内。 然后,客户端可以将序列增加到36(对于其他客户端在使用35时能够生成密钥)并且知道关键字35/0,35 / 1,35 / 2,35 / 3 … 35/1023是全部可用。

它可以非常有用(特别是与ORMs)能够设置在客户端的主键,而不是插入没有主键的值,然后提取到客户端。 除了其他任何东西,这意味着你可以很容易地做出父母/子女的关系,并在做任何插入之前,把钥匙放在适当的位置,这使得配料更简单。

除了Jon的回答:

它用于能够断开连接。 然后,客户端可以向服务器请求一个hi号码并创build增加lo号码的对象。 在lo范围用完之前,不需要联系服务器。

比Hi-Lo分配器好,是“线性块”分配器。 这使用一个类似的基于表的原则,但分配小,方便大小的块,并产生良好的人性化的价值观。

create table KEY_ALLOC ( SEQ varchar(32) not null, NEXT bigint not null, primary key (SEQ) ); 

要分配下一个,比如20个键(这些键然后作为一个范围保存在服务器中,并根据需要使用):

 select NEXT from KEY_ALLOC where SEQ=?; update KEY_ALLOC set NEXT=(old value+20) where SEQ=? and NEXT=(old value); 

提供你可以提交这个事务(使用重试来处理争用),你已经分配了20个密钥,并且可以根据需要分配它们。

这个scheme的块大小只有20个,比从Oracle序列中分配要快10倍,并且在所有的数据库中都是100%的可移植的。 分配performance相当于hi-lo。

与Ambler的想法不同,它将键空间视为连续的线性数字线。

这避免了组合键的推动力(这从来不是一个好主意),并且避免了在服务器重新启动时浪费整个字。 它产生了“友好的”,人类的关键价值观。

安布勒先生的想法,比较而言,分配高16位或32位,并产生大的人类不友好的键值作为高字增量。

分配的键比较:

 Linear_Chunk Hi_Lo 100 65536 101 65537 102 65538 .. server restart 120 131072 121 131073 122 131073 .. server restart 140 196608 

实际上,我早在九十年代就与安布勒先生通信,向他提出了这个改进scheme,但是他太过坚持和固执地承认使用线性数字线的优点和简单明了。

在devise方面,他的解决scheme在数字线(复合键,大型hi_word产品)上比Linear_Chunk更复杂,但没有相对的优势。 他的devise在math上被certificate是不足的。

hi / loalgorithm将序列域分成“hi”组。 “hi”值是同步分配的。 每个“hi”组被给予最大数量的“lo”条目,可以通过离线分配而不必担心并发的重复条目。

  1. “hi”令牌由数据库分配,两个并发呼叫保证看到唯一的连续值
  2. 一旦检索到“hi”标记,我们只需要“incrementSize”(“lo”条目的数量)
  3. 标识符范围由以下公式给出:

     [(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1) 

    “lo”值将在以下范围内:

     [0, incrementSize) 

    从以下的起始值开始应用:

     [(hi -1) * incrementSize) + 1) 
  4. 当所有“lo”值被使用时,一个新的“hi”值被取出并且循环继续

你可以在这篇文章中find更详细的解释:

这个视觉呈现也很容易遵循:

在这里输入图像描述

虽然hi / lo优化器可以优化标识符的生成,但是在其他系统将行插入到数据库中的时候却不能很好地发挥作用,而不知道我们的标识符策略。

Hibernate提供了池优化器,它将高/低发生器策略与互操作性序列分配机制相结合。 这个优化器既有效又可与其他系统互操作,比以前的传统hi / lo标识符策略更好。

我发现Hi / Loalgorithm非常适合基于我的经验的复制场景的多个数据库。 想象一下吧。 你在纽约(别名01)有一个服务器,在洛杉矶有另一台服务器(别名02),那么你有一个PERSON表…所以在纽约当一个人创build…你总是使用01作为HI值而LO值是下一个安全性。 例如。

  • 010000010 Jason
  • 010000011 David
  • 010000012西奥

在洛杉矶你总是使用HI 02。例如:

  • 020000045鲁珀特
  • 020000046奥斯瓦尔德
  • 020000047马里奥

所以,当你使用数据库复制(不pipe是什么品牌的)时,所有的主键和数据都可以轻松而自然地组合起来,而不用担心重复的主键,链接等。

这是在这种情况下最好的方法。