Google Spanner


 分布式
分布式系统有各种定义,个人理解:拥有一个以上的时序即为分布式系统。

传统系统,也就是图灵机或者冯诺依曼计算机,只有一个时序。
图灵机是串行系统,所有事件顺序发生。
冯式计算机作为图灵机的具体实现,通过唯一时钟发生频率,每Tick里只完成单个事件,也只有一个时序。

单时序系统的优点是简单可控,通过唯一时序操作数据,可以保证因果固定性,同样的操作必然产生同样的结果,也就是逻辑可控。

单时序系统的天然缺陷是吞吐量的制约。
为了在单时序系统上提高吞吐量,我们不停提高工业精度,但越来越困难:摩尔定律失效,磁录密度增加缓慢,等等。
世界本身是并发的,我们用串行手段来数字化世界,注定走不远。

分布式系统通过集成多个单时序系统,用并发来解决吞吐量问题,这是有效的方法,目前超级计算机都是通过并发来提高性能。

多时序系统带来的问题是:如何让内部的每个单时序系统看到的数据都经历了同样顺序的操作?保证这一点才能保证因果一致。

这就是通常说的一致性问题,有人以为一致性是指“数据都一样”,这是不精确的。
一致性有很多个级别,“每时每刻数据都一样”是最高的理想状态,“如果没有新操作,各单时序系统的数据将在一段时间后达成一致”是最低的保证,也就是最终一致性。
不能保证最终一致性的系统,就不能保证固定的因果逻辑,就会出问题。

提供最简单的数据一致性的系统架构是我们最常用的单点提交系统,也就是以某个固定的单时序系统为准绳,数据向其提交完毕才算当次操作完成。
比如大多数网站应用,数据以进入数据库为准。

这种简单方案的问题和单时序系统一样,数据需要在准绳系统上串行操作,吞吐量仍旧受制约。可称之为伪分布式系统。
此方案称为垂直划分,利用了多个系统对数据进行不同阶段的处理,突破了单时序系统上限。

如果仔细设计,垂直划分可以有很高的性能。
比如将数据做成多级索引结构,那么只有顶级索引需要在准绳系统上提交,而顶级索引的数据量通常不大。
这就是我们通常所说的数据库分库分表。

垂直划分与应用逻辑结合紧密,维护代价量大。
要想更好突破单时序系统性能制约,更好的办法是允许多个系统并发地操作数据。

并发操作有两种情况,一种是顺序操作,即A对数据D操作完毕之后,D传输到B,B再操作D。顺序操作和单系统上的单时序不一样,它仅仅是“碰巧”而非强制。
另一种情况是冲突性操作,即A对数据D操作的同时,B也在对处于B本地的数据D进行操作,它将产生数据的不同分支版本,不同分支无法自动合并。

分布式系统的关键是数据在各子系统时序一致性,引申出来就是要解决冲突。
具体说,要解决:
1,冲突检测,每子系统拿到数据的不同版本需要能独立检测出是否冲突。
2,冲突决策, 决策结果在每子系统需要一致。

如果分布式系统的每两个子系统都两两互联,形成完全对等网络,那就不需要额外的数据记录连接的拓扑结构。
但目前的网络设施仍旧基于串行模型,这样的连接会超出网络吞吐量。 所以实用型的连接是雪花型的拓扑结构。
这样,对于一个自维护的半对等的分布式系统,它需要额外的拓扑数据来记录当前的连接模型。

拓扑数据和应用数据由于用途不同,通常使用不同的冲突算法。

拓扑数据需要即时决策,如果决策过程太长可能造成期间系统连接异常,造成冲突上升等问题。
同时拓扑数据是可抛弃的,发生冲突时,没被选中的数据版本可以简单地抛弃。
典型的应用场景是Leader选择。

在实际运行的分布式系统上,对于拓扑数据,无一例外地使用了Paxos算法进行冲突决策。
包括Google的Chubby、新发布的Spanner,亚马逊S3等。
Paxos简单说就是对数据进行选举、使用多数同意的冲突解决方案,选举过程有冲突发现机制,详情参见论文。

对于应用数据,实时性要求低,冲突算法的选择余地较大。

亚马逊的S3系统,使用VectorClock的算法来处理应用数据冲突。
它很简单,A处理D的时候为D附加“A:1”的信息,B接着处理时加上“B:2”,详情参见论文。
这样,比较两个D的附加信息,就可以知道它们的操作时序是否有蕴涵关系,如果是,则新D覆盖旧D。如果无蕴涵关系,则发生了冲突,同时保留两个D。

VectorClock算法使用同时保留的策略来解决冲突,同样也保证了最终一致性。
其实VectorClock也可以做自动合并,在A、B都能获得同样的D的情况下,固定的算法可以在A、B上分别产生一致性的分支选择。
但自动合并后的D与合并前的D的各分支的后继版本均会再次冲突,因此直接保留多版本是比较好的策略。

Google的Spanner则有不同的方案,对于数据D的写操作均会带上时间戳T,应用层在读取D的时候需要指定T。相当于D按T分解成了多个版本,而且每个版本只会写入一次(下述),这就避免了冲突。

Spanner通过几个策略保证D的每个T版本只写入一次:
1,写入时在通过选举出来的Leader上进行单点锁定提交,保证了T时刻无冲突,只有一个 版本写入。
2,当写入时T与上次写入的T相同时,即为检出冲突,此时使用延迟写入当前版本来解决冲突。
3,原子钟和GPS提供了全局同步时间TrueTime,假设其最大误差为delta,那么在与上版本冲突时,最多需要延迟delta时间,就可以保证不冲突。

分布式系统提起来吓人,核心算法并不复杂,只是各家的论文都语焉不详,实在令人郁闷。

你可能感兴趣的:(Google Spanner)