30公分初探分布式架构演进

分布式系统的意义

1.升级单机处理能力的性价比越来越低 单机的处理能力主要依靠CPU,内存,磁盘.通过更好硬件做垂直扩展的方式来提升性能,成本会越来越高.

2.单机处理能力存在瓶颈 单机处理能力存在瓶颈,CPU,内存都会有自己的性能瓶颈,也就是说就算你是土豪不惜成本去提升硬件,但是硬件的发展速度和性能 是有限制的.

3.稳定性和可用性这两个指标很难达到 单机系统存在可用性和稳定性的问题,这两个指标又是我们必须要去解决的

 

分布式架构的常见概念

集群

例子: 小饭店原来只有一个厨师,切菜洗菜备料炒菜全干.后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜, 这两个厨师的关系是集群

分布式

例子: 为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了, 又请了个配菜师,两个配菜师关系是集群

节点

节点是指一个可以独立按照分布式协议完成一组逻辑的程序个体.在具体项目中,一个节点表示的是一个操作系统上的进程.

副本机制

副本(replica/copy)指在分布式系统中为数据或服务提供的冗余. 数据副本指在不同节点上持久化同一份数据,当出现某一个节点的数据丢失时,可以从副本上读取到数据.数据副本是分布式系统中 解决数据丢失问题的唯一手段. 服务副本表示多个节点提供相同的服务,通过主从关系来实现服务的高可用方案.

中间件

中间件位于操作系统提供的服务之外,又不属于应用,他是位于应用和系统层之间为开发者方便的处理通信,输入输出的一类软件,能 够让用户关心自己应用的部分.

架构的发展过程

阶段一:单应用架构

网站的初期也可以认为是互联网发展的早期,我们经常会在单机上跑我们所有的程序和软件. 把所有软件和应用都部署在一台机器上,这样就完成一个简单系统搭建,这个时候讲究的是效率.

阶段二:应用服务器和数据库服务器分离

随着网站的上线,访问量逐步上升,服务器负载慢慢升高.在服务器还没有超载的时候,我们应该做好规划,提升网站的负载能力.假如 代码层面的优化已经没办法继续提高,在不提高单台机器性能的前提下,增加机器是一个比较好的方式,投入产出比非常高.这个阶段 增加机器的主要目的是将web服务器和数据库服务器拆分,这样不仅提高了单机的负载能力,也提高了容灾能力.

阶段三:应用服务器集群-应用服务器负载告警

随着访问量的继续增加,单台应用服务器已经无法满足需求.在假设数据库服务器还没有遇到性能问题的时候,我们可以增加应用服 务器,通过应用服务器集群将用户请求分流到各个服务器中,从而继续提升负载能力.此时多台应用服务器之间没有直接的交互,他们 都是依赖数据库各自对外提供服务

(1)用户请求由谁转发到具体应用服务器

(2)session一致性

阶段四:数据库压力变大,数据库读写分离

架构演变到这里,并不是终点.上面我们把应用层性能拉上来了,但是数据库的负载也在慢慢增大,那么怎么去提高数据库层面的负载 呢?有了前面的思路以后,自然会想到增加服务器.但是假如我们单纯的把数据库一分为二,然后对于后续数据库的请求,分别负载到 两台数据库服务器上,那么一定会造成数据库不统一的问题.所以我们一般先考虑读写分离的方式

这个架构图的变化会带来几个问题

(1)主从数据库之间的同步;可以使用mysql自带的master-slave方式实现主从复制

(2)对应数据源的选择;采用第三方数据库中间件,例如mycat

阶段五:使用搜索引擎缓解读库压力

数据库做读库的话,对模糊查找效率不是很好,像电商类的网站,搜索是非常核心的功能,即便是做了读写分离,这个问题也不能有效解 决.那么这个时候就需要引入搜索引擎了 使用搜索引擎能够大大提高我们的查询速度,但是同时也会带来一些附加的问题,比如维护索引的构建.

阶段六:引入缓存机制缓解数据库压力

随着访问量的持续增加,逐渐出现许多用户访问同一部分内容的情况,对于这些热点数据,没必要每次都从数据库去读取,我们可以使 用缓存技术,比如memcache,redis来作为我们应用层的缓存;另外在某些场景下,比如我们对用户的某些IP的访问频率做限制,那这 个放内存中又不合适,放数据库又太麻烦,这个时候可以使用NoSql的方式比如mongodb来替代传统的关系型数据库

阶段七:数据库的水平/垂直拆分

我们的网站演进的变化过程,交易,商品,用户的数据还在同一个数据库中,尽量采取了增加缓存,读写分离的方式,但是随着数据库压 力的持续增加,数据库瓶颈任然是个最大的问题.因此我们可以考虑对数据的垂直拆分和水平拆分

垂直拆分:把数据库中不同业务数据拆分到不同的数据库

水平拆分:把同一个表中的数据拆分到两个甚至更多的数据库中

水平拆分的原因是某些业务数据量已经达到了单个数据库的瓶颈,这时可以采取将表拆分到多个数据库中

阶段八:应用的拆分

随着业务的发展,业务越来越多,应用的压力也越来越大.工程规模也越来越庞大,这个时候可以考虑将应用拆分,按照领域模型将我们 的用户,商品,交易拆分成多个子系统. 这样拆分之后,可能会有一些相同的代码,比如用户操作,在商品和交易都需要查询,所以会导致每个系统都会有用户查询访问相关操 作.这些相同操作一定是要抽象出来,否则就会是一个坑.所以通过走服务化路线的方式来解决

服务拆分以后,各个服务之间如何进行远程通信?

通过RPC技术,比如典型的有:webservice,hessian,http,RMI等等

前期通过这些技术能够很好的解决各个服务之间通信问题,但是,互联网的发展是持续的,所以架构的演变和优化还在持续.

分布式系统的难点:

毫无疑问,分布式系统对于集中式系统而言, 在实现上会更加复杂.分布式系统将会是更难理解,设计,构建和管理的,同时意味着应用 程序的根源问题更难发现.

三态

在集中式架构中,我们调用一个接口返回的结果只有两种,成功或者失败,但是在分布式领域中,会出现超时这个状态

分布式事务

这是一个老生常谈的问题,我们都知道事务是一系列操作的原子性保证,再单机的情况下,我们能够依靠本机的数据库连接和组件轻 易做到事务的控制,但是在分布式情况下,业务原子性操作可能是跨服务的,这样就导致了分布式事务,例如A和B操作分别是不同服务 下的同一个事务操作,A调用B,A如果可以清楚的知道B是否成功提交从而控制自身的提交还是回滚操作,但是在分布式系统中调用会 出现一个新状态就是超时,就是A无法知道B是成功还是失败,这个时候A是提交本地事务还是回滚呢?其实这是一个很难的问题,如果 强行保证事务一致性,可以采取分布式锁,但是那样会增加系统复杂度而且会增大系统的开销,而且事务跨越的服务越多,消耗的资源 越大,性能越低,所以最好的解决方案就是避免分布式事务.

还有一种解决方案就是重试机制,但是重试如果不是查询接口,必然涉及到数据库的变更,如果第一次调用成功但是没返回成功结果, 那调用方第二次调用对调用方来说依然是重试,但是对于被调用方来说是重复调用,例如A向B转账,A-100,B+100,这样会导致A扣了 100,而B增加200.这样的结果是不是我们期望的,因此需在要写入的接口做幂等设计.多次调用和单次调用是一样的效果.通常可以设 置一个唯一键,在写入的时候查询是否已经存在,避免重复写入.但是幂等设计的一个前提就是服务是高可用,否则无论怎么重试都不 能调用返回一个明确的结果,调用方会一直等待,虽然到了极端情况还是需要人肉补偿处理.其实根据CAP和BASE理论,不可能在高 可用分布式情况下做到一致性,一般都是最终一致性保证.

负责均衡

每个服务单独部署,为了达到高可用,每个服务至少是两台机器,因为互联网公司一般使用可靠性不是特别高的普通机器,长期运行宕 机概率很高,所以两台机器能够大大降低服务不可用的可能性,更大型项目会采用十几台甚至上百台来部署一个服务,这不仅是保证 服务的高可用,更是提升服务的QPS,但是这样又带来一个问题,一个请求过来到底路由到哪台机器?路由算法很多,有DNS路由,如果 session在本机,还会根据用户id或者cookie等信息路由到固定的机器,当然现在应用服务器为了扩展的方便都会设计为无状态 的,session会保存到专有的session服务器,所以不会涉及到拿不到session问题.那路由规则是随机获取么?这是一个方法,但是实际 情况肯定比这个复杂,在一定范围内随机,但是在大的范围会分为很多个域,例如如果为了保证异地多活的多机房,多机房调用开销太 大,肯定会优先选择同机房的服务,这个要参考具体的机器分布来考虑.

一致性

数据被分散或者复制到不同机器上,如何保证各台主机之间的数据的一致性将成为一个难点.

故障的独立性

分布式系统由多个节点组成,整个分布式系统完全出问题的概率是存在的,但是在时间中出现更多的是某个节点出问题,其他节点都 没问题.这种情况下我们实现分布式系统时需要考虑的更加全面.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值