博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分布式系统
阅读量:7153 次
发布时间:2019-06-29

本文共 2548 字,大约阅读时间需要 8 分钟。

hot3.png

一致性和可扩展性

  一致性是系统内比较复杂的属性,它会随着系统的变化而变化。简单来说,一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。一旦系统具有并行性(分布式只是并行的一种表现),保持一致性就变得困难了,毕竟需要协调全局状态。

事务和一致性

  一致性意义上的事务是指单一的原子操作。也就意味着一系列操作要么全成功,要么全不成功,不涉及中间状态。比如A转账给B,不能存在A余额已经扣除但B余额没有增加的情况。

强一致性和最终一致性

  数据在任一时刻都是被原子性的事务操作所更新的,这种情况称为强一致性,即系统的所有节点可能会从一个完全一致的状态转移到另一个完全一致的状态。最终一致性意味着在一段时间内发生的更新不管跨度多短,系统的不同节点在这段时间内都会有不同的状态,但在一段时间后,节点间的状态最终会达到一致。在分布式环境中,最终一致性通常比强一致性更容易实现。不知道作者为啥很奇怪,这不是很显然的么?哈哈。世界本来就是异步的,异步的就意味着,数据的更新总是有先后的嘛,就看你能不能丈量得到了。

并发性与并行性

  并发性是指两个进程从某一个时刻开始,同时存在,但他们不一定在同一时刻运行,也可以在重叠的时间段内运行。并行性引入了两个进程同时执行的意思。支持并行性意味着也支持并发性,但反过来就不一定了。因为并行性的时间要求更高。分布式系统是支持并行性的,单核心单处理器系统是支持并发性的。

全局一致的分布式状态影响可扩展性

  全局一致的分布式状态违反了现实世界的物理法则,也很难实现。毕竟它在更新状态时,要“暂停整个世界”,以确保系统的每个模块更新到正确的状态,然后所有节点继续工作。其实吧,这也可以实现,但这样做还有神马意义呢。它严重限制了并行处理的能力,降低了可扩展性。

交付保证

  交付保证是建立分布式系统时经常被忽略的一部分,就是如何确保消息消息被送达、处理后返回响应的结果。看看TCP三次握手协议就知道这有多麻烦了。

最多投递一次

  最多投递一次的交付机制最容易实现。因为它就是简单的发送一次消息,然后继续其他工作。这是Akka默认的交付机制,也就是 fire and forget

最少一次

  跟最多一次相反,它允许重复发送数据,以确保被正确处理。但这往往需要存储消息,以便没有收到接收方的确认消息时重发数据。这其实有点麻烦,因为数据存内存吧,可能把内存撑爆,毕竟现在的内存还比较贵,存硬盘吧,存取又比较慢。特别是在海量数据的场景下,就更麻烦了。引入redis等第三方分布式缓存虽然可以折中的解决效率的问题,但也引入了系统的复杂性、不稳定性。

恰好一次交付

  这往往不可能,特别是在分布式系统中,但可以近似做到。恰好一次意味着消息从发送者到接受者只需要恰好一次可靠的传递,没有多余的重复。想想都不可能,其实也没有必要。其实我们经常谈论的“恰好一次”,是对恰好一次的变种:消息从发送者到接受者只经过一次正确的处理!其实就是重复的发消息给接受者,接受者消息只进行了一次业务上的处理,对多余的消息只是简单的进行了应答。

集群单例

  有时候系统中一些区域必须是唯一的。比如全局唯一ID的生成器,这个生成器需要跟踪以往使用的ID或者可能使用单调递增的数值。简单来说就是需要一个全局协调器,一旦不唯一可能造成灾难性的后果。其实我更喜欢局部协调器,这虽然没有解决问题的复杂性,但至少解决了问题影响的范围。幸运的是Akka帮我们实现了这一机制,可以确保整个集群系统中只有一个actor实例可用,也就是集群单例。它运行在集群中存在时间最长的可用节点上。这有时候也是合理的,运行时间最长意味着最稳定,毕竟活了那么久居然没有挂,非常可靠。要不然像Windows那样,天天重启就不好了。幸运的是Akka的gossip机制可以确定哪个节点是运行最久的节点。

  单例就意味着没有并行,往往也意味着性能瓶颈与可用性问题。毕竟单例不可用期间,发送到集群单例中的任何消息都将被缓存,也就意味着消息不能被及时处理。另外,当集群单例进行节点漂移时,全局状态如何进行漂移也是一件棘手的事情。分布式缓存和单例数据库可以保存这个状态,但也无法避免的增加系统的复杂性和不确定性。因为它没有彻底解决问题,只是暂时转移了问题。使用Akka Persistence可以维持状态,在重新创建实例时,可以恢复先前的状态。

  作者建议除非绝对必要,不然尽量避免使用。其实我们可以改变一下思路,把“集群单例”转换成“逻辑单例”,以缩小“单例”不可用时影响的系统的范围。

  在Akka中,集群单例是通过其代理接收消息的,毕竟单例会发生漂移,其ActorRef会发生变化,用代理来消除这一变化是非常合理的。也就是用不变来封装变化,以减少系统的复杂性。

可扩展性

  具备可扩展的系统在处理更高的负载时不会出现故障或性能急剧下降的问题。它与性能的关系微乎其微,优化性能不能保证可扩展性。其实这句话说的有点歧义,因为我觉得这亮点还是有点关系的。毕竟可扩展性是可以用来提高系统高负载时的性能问题的。系统的可扩展性可以分为垂直扩展和水平扩展。垂直扩展意味着增加更多的资源,例如CPU/内存/带宽;水平扩展意味着增加系统的节点数量。在处理某个问题时,如果原来的人忙不过来了,那就有两种方法来解决。一是提高工人的技术熟练程度或用高技能工人替换低产能工人,另外一种就是增加工人数量了。两种方案各有优劣,都需要付出一定的代价。

  一个和可扩展性高度相关的概念是弹性。具有弹性是指具备在运行的系统中增加资源的能力,能够通过增加资源来扩展系统,而不影响客户端。其实就是水平扩展的能力。比如,某件工作需要用到一个限定数量的资源,那么提高工人的数量,并一定能提高工作的效率。使系统具有弹性就是消除这个关键资源,以增加水平扩展的能力,那么怎么增加弹性呢?

避免全局状态

  其实也就是避免关键资源。如果必需,可以用集群单例实现。

避免共享状态

  全局状态其实是共享状态的极端情况,她是集群所有节点之间的共享状态。

转载于:https://my.oschina.net/u/2935389/blog/3034292

你可能感兴趣的文章
Nagios安装和配置详解
查看>>
我和linux的第六天
查看>>
PHP SOAP php调取soap的webservice连接超时的问题
查看>>
项目管理——extjs显示下拉框
查看>>
was 通过 addNode命令向DM添加节点报错
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
常用在线软件获取
查看>>
Netfilter策略路由和uRPF
查看>>
当心!TCP本机客户端连接本机服务器
查看>>
httpd之不记录指定文件类型的日志
查看>>
日期类型格式大全
查看>>
我的友情链接
查看>>
grep用法
查看>>
saltstack 系列(四)centos7使用saltstack源码安装nginx
查看>>
datetimepicker控件 只显示年月日(兼容ie)
查看>>
我的友情链接
查看>>
如何撰写优秀系统运维架构方案及推动实施案例分享
查看>>
MyEclipse10编码解决方案
查看>>
AIX里如何查看文件系统属于哪个VG?
查看>>