Lamport时钟

2021-06-26 15:10:14

使用逻辑时间戳作为值的版本,以允许跨服务器排序值

当存储在多个服务器上的值时,需要一种了解在另一个之前存储的值存储的方式。无法使用系统时间戳,因为壁时钟不是两个不同服务器的单调和时钟值不应进行比较。

表示当天时间的系统时间戳由通常用晶体振荡器构建的时钟机械测量。这种机制的已知问题是,基于晶体振荡的快速或慢速,它可以远离当天的实际时间。为了解决此问题,计算机通常具有像NTP这样的服务,它同步互联网上具有众所周知的时间源的计算机时钟。因此,给定服务器上系统时间的两个连续读数可以有时间倒退。

由于跨服务器的时钟漂移没有上限,因此无法比较两个不同的服务器上的时间戳

mvccstore mvccstore; Lamportclock时钟;公共服务器(mvccstore mvccstore){this.clock =新的Lamportclock(1);这个.mvccstore = mvccstore; }

每当服务器执行任何写入操作时,它应该使用`tick()`方法前进LAMPORT时钟

这样,服务器可以确定在请求之后按下写入,并且在任何其他操作之后服务器已经执行了,因为客户端由客户启动。服务器返回用于将值写入客户端的时间戳。然后,请求客户端使用此时间戳对其他服务器进行任何进一步写入。这样,维持请求的因果链。

考虑使用多个服务器节点的简单键值存储的示例。有两个服务器,蓝色和绿色。每个服务器都负责存储特定的键组。当数据在一组服务器上划分数据时,这是一个典型的方案。使用LAMPORT时间戳作为版本号存储为版本值的值。

接收服务器对其自己的时间戳进行比较和更新并使用它来编写版本化的键值。 public int write(string key,string值,int equestimestamp){//更新自己的时钟来反映因果关系int writeattimestamp = clock.tick(equestTimestamp); mvccstore.put(新版本的key(key,writeattimestamp),值);返回writeattimestamp; }

用于写入该值的时间戳返回给客户端。客户端通过更新自己的时间戳来跟踪最大时间戳。它使用此时间戳来发出任何进一步的写入。

Lamportclock时钟=新的Lamportclock(1); public void write(){int server1writtenat = server1.write("姓名"" alice",clock.getlatesttime()); clock.updateto(server1writtenat); int server2writtenat = server2.write("标题" servervices",clock.getlatesttime()); clock.updateto(server2writtenat); asserttrue(server2writtenat> server1writtenat); }

即使客户端与带有领导者和追随者组的领导者通信的当客户端,每个组都有相同的技术也适用于特定键。客户向本集团的领导者发送请求,如上所述。 LAMPORT时钟实例由该组的领导者维护,并且可以更新与上一节中讨论的完全相同的方式。

Lamport时钟存储的值仅部分排序。如果两个客户端存储两个单独的服务器中的值,则时间戳值不能用于在服务器上排序。在以下示例中,Bob上的Bob存储的标题在时间戳2处。但是如果Bob存储在Alice上或在Server Blue上的名称中存储了名称之后,则无法确定。

对于单个领导者 - 跟随服务器组,其中一个领导者总是负责存储值,版本化值中讨论的基本实现足以维护因果关系。

在这种情况下,键值存储可以保留整数符号。 每次从写导向日志应用键值写命令时,它会递增版本计数器。 然后它用递增版本计数器构造新密钥。 只有领导者负责递增版本计数器,追随者使用相同的版本号。 int版本= 0; mvccstore mvccstore = new mvccstore(); @Override公共完成肥料<响应> 放(字符串键,字符串值){return server.propose(new setvalueCommand(key,value)); 私人响应applysetvaluecommand(setvaluecommand setvaluecommand){getlogger()。信息("设置键值" + setvalueCommand); 版本=版本+ 1; mvccstore.put(新版本的key(setvaluecommand.getkey(),版本),setvaluecommand.getValue()); 响应响应= response.success(版本); 回复响应; } 数据库如[MongoDB]和[蟑螂]使用Lamport时钟的变型来实现[MVCC]存储