分布式系统你会设计了吗?不会阿里架构师来教你设计(3)
这是为了防止发出新的lease而引起不断有新的cache节点持有lease,形成活锁。优化的手段是:一旦A进入修改流程,不是盲目屏蔽读请求,而是对读请求只返回数据不返回lease。造成cache节点只能读取数据,不能cache数据。进一步的优化是返回当前已发出的lease的最大值。这样同样能避免活锁问题。 A在修改元数据时需要等待所有lease过期 优化手段是:A主动通知各个持有lease的节点,放弃lease并清除cache中相关数据。如果收到cache节点的reply,确认协商通过,则可以提前完成修改动作;如果中间失败或超时,则进入正常等待lease过期的流程,不会影响协议正确性。 2.3.2 lease机制的深入分析 (1) lease定义 lease是由颁发者授予的再某一有效期内的承诺。颁发者一旦发出lease,无论接收方是否收到,无论后续接收方处于何种状态,只要lease不过期则颁发者一定严守承诺;另一方面,接受者在lease的有效期内可以使用颁发者的承诺,一旦lease过期则一定不能继续使用。 (2) lease的解读 由于lease仅仅是一种承诺,具体的承诺内容可以非常宽泛,可以是上节中数据的正确性,也可以是某种权限。例如并发控制中同一时刻只给某一个节点颁发lease,只有持有lease才能修改数据;例如primary-secondary中持有lease的节点具有primary身份等等 (3) lease的高可用性 有效期的引入,非常好的解决了网络异常问题。由于lease是确定的时间点,所以可以简单重发;一旦受到lease之后,就不再依赖网络通信 (4) lease的时钟同步 工程上将颁发者有效期设置的比接受者打,大过时钟误差,来避免对lease有效性产生影响。 2.3.3 基于lease机制确定节点状态。 在分 布式系统中确定一个节点是否处于正常工作状态困难的问题。由可能存在网络分化,节点的状态无法通过网络通信来确定的。 例如: a b c 互为副本 a为主节点,q为监控节点。q通过ping来判断abc的状态,认为a不能工作。就将主节点切换成b。但是事实上仅仅是ping没收到,a自己认为自己没有问题,就出现了 a b都觉得自己是主节点的“双主”问题。 解决方法是q在发送heartbeat时加上lease,表示确认了abc的状态,并允许节点在lease有效期内正常工作。q给primary节点一个特殊的lease,表示该节点作为primary工作。一旦q希望切换primary,只需要等待之前primary的lease过期,避免出现双主问题。 2.3.4 lease的有效期时间选择 工程上一般选择10秒钟 2.4 Quorum机制 2.4.1 Write-all-read-one 对于某次更新操作Wi,只有在所有N个副本上都更新成功,才认为是一次“成功提交的更新操作”,对应的数据为“成功提交的数据”,数据版本为Vi。 缺点: 频繁读写版本号容易成为瓶颈 N-1个副本成功的情况下,仍然被认为更新失败 2.4.2 Quorum定义 WARO最大程度增强读服务可用性,最大程度牺牲写服务的可用性。将读写可用性折中,就会得到Quorum机制: Quorum机制下,某次更新Wi一旦在所有N个副本中的W个副本上成功,就称为“成功提交的更新操作”,对应的数据为“成功提交的数据”。令R > N - W,最多需要读取R个副本则一定能读到Wi更新后的数据Vi。 由此可见WARO是Quorum中W = N时的一个特例。 2.4.3 读取最新成功提交的数据 Quorum的定义基于两个假设: 读取者知道当前已提交的版本号 每次都是一次成功的提交 现在取消这两个假设,分析下面这个实际问题: N = 5, W = 3, R = 3,某一次的副本状态为(V2 V2 V2 V1 V1)。理论上读取任何3个副本一定能读到最新的数据V2,但是仅读3个副本却无法确定读到最新的数据。 例如读到的是(V2 V1 V1),因为当副本状态为(V2 V1 V1 V1 V1)时也会读到(V2 V1 V1),而此时V2版本的数据是一次失败的提交。因此只读3个无法确定最新有效的版本是V2还是V1。 解决方案: 限制提交的更新操作必须严格递增,只有前一个更新操作成功后才可以提交下一个。保证成功的版本号连续 读取R个副本,对其中版本号最高的数据:若已存在W个,则该数据为最新结果;否则假设为X个,则继续读取其他副本直到成功读取W个该版本的副本。如果无法找到W个,则第二大的版本号为最新成功提交的版本。 因此单纯使用Quorum机制时,最多需要读取R + (W - R - 1) = N个副本才能确定最新成功提交的版本。实际工程中一般使用quorum与primary-secondary结合的手段,避免需要读取N个副本。 2.4.4 基于Quorum机制选择primary 在primary-secondary协议中引入quorum机制:即primary成功更新W个副本后向用户返回成功 当primary异常时需要选择一个新的primary,之后secondary副本与primary同步数据 通常情况下切换primary由监控节点q完成,引入quorum之后,选择新的primary的方式与读取数据相似,即q读取R个副本,选择R个副本中版本号最高的副本作为新的primary。新primary与除去q选举出的副本外,其余的至少W个副本完成数据同步后,再作为新的primary。 蕴含的道理是: R个副本中版本号最高的副本一定蕴含了最新的成功提交的数据。 虽然不能确定版本号最高的数据 == 这个最新成功提交的数据,但新的primary立即完成了对W个副本的更新,从而使其变成了成功提交的数据 例如:N = 5 W = 3 R = 3的系统,某时刻副本状态(V2 V2 V1 V1 V1),此时V1是最新成功提交的数据,V2是处于中间状态未成功提交的数据。V2是作为脏数据扔掉,还是作为新数据被同步,完全取决于能否参与q主持的新primary的选举大会。如果q选择(V1 V1 V1),则在接下来的更新过程中 V2会被当成脏数据扔掉;如果q选择(V2 V1 V1)则V2会将V1更新掉,成为最新成功的数据。 2.5 日志技术 日志技术不是一种分布式系统技术,但分布式系统广泛使用日志技术做down机恢复。 2.5.1 数据库系统日志回顾 数据库的日志分为 undo redo redo/undo no-redo/no-undo四种,这里不做过多介绍。 2.5.2 redo与check point (编辑:ASP站长网) |