《大型网站系统与JAVA中间件实践学习笔记》-1

时间:2023-03-09 12:59:51
《大型网站系统与JAVA中间件实践学习笔记》-1

第一章:分布式系统介绍

  定义:分布式系统是一组分布在网络上通过消息传递进行协作的计算机组成系统。

分布式系统的意义

  • 升级单机处理能力的性价比越来越低
  • 单机处理器能力存在瓶颈
  • 处于稳定性和可用性考虑

阿姆达尔定律:s(P)=1/((1-p)+p/N)

  其中P指的是程序中可并行的部分的程序在单核上执行的时间的占比,N表示处理器的个数(核心数)。S(N)是指程序在N个处理器相对单个处理器的提升速度比。

单进程多线程和多进程的区别

  线程是属于进程的,一个进程内的多个线程共享进程的内存空间;而多个进程之间的内存空间是相对独立的,因此多个进程间通过内存共享、交换数据的方式与多个线程间的方式就有所不同。多进程相对于单进程多线程的方式来说,资源控制更容易实现,此外多进程中单个进程出现问题不会造成整体不可用。

分布式系统的难点

  1. 缺乏全局时钟
  2. 面对故障的独立性。在分布式系统,整个系统的一部分有问题而其它部分正常是经常出现的情况,我们称之为故障的独立性。
  3. 单点故障。在整个分布式系统中,如果某个角色或者功能只有单台机器在支撑,那个这个节点称为单点,发生的故障称为单点故障。在分布式系统中要尽量避免出现单点。如果不能把单机实现变为集群实现,那么一般还有两种选择:
    • 给这个单点做好备份,能够在出现问题是进行恢复,并且尽量做到自动恢复,降低恢复所需要使用的时间。
    • 降低单点故障的影响范围。

  4.事务的挑战。

第二章:大型网站及架构的演进过程

1.从一个单机交易网站说起

《大型网站系统与JAVA中间件实践学习笔记》-1

  所有的功能模块和数据在单台服务器上,通过各个模块之间通过JVM内部的方法调用来进行交互,而应用和数据库之间是通过JDBC进行访问的。

2.单机负载告警,数据库与应用分离

《大型网站系统与JAVA中间件实践学习笔记》-1

  随着访问量的增加,服务器负载持续升高,考虑将应用服务器和数据库服务器分离。

3.应用服务器负载告警,如何让应用服务器走向集群

  应用服务器压力变大时,根据对应用服务器的监测结果,可以考虑将服务器从一台变为两台,增加服务器后急需解决如下连个问题:

  1. 用户对于应用服务器的选择问题,可以通过在应用服务器前增加负载均衡设备来解决。
  2. Session问题。

3.1引入负载均衡设备

  引入负载均衡设备后的架构

《大型网站系统与JAVA中间件实践学习笔记》-1

3.2解决应用服务器的Session问题

  HTTP协议本生是无状态协议,需要基于HTTP协议支持回话(Session State)状态机制。具体的实现方式为:在回话开始时,分配一个唯一的回话标识(SessionID),通过Cookie把这个标识告诉浏览器,以后每次请求的时候,浏览器会带上这个会话标识告诉服务器请求数据那个会话。在Web服务器上,各个会话有独立的存储,保存不同的回话信息。如果遇到禁用Cookie的情况,一般的做法就是把这个回话标识放到URL的参数中。

《大型网站系统与JAVA中间件实践学习笔记》-1

《大型网站系统与JAVA中间件实践学习笔记》-1

  如上图所示,如果第一次网站请求在左边的服务器,那么Session保存在左边的服务器上,如果不做处理,就不能保证每次请求都落在同一台服务器上,这就是Session问题。

Session Stickey

  保证同一个回话的请求都落在同意Web服务器上,称为Session Stickey。

《大型网站系统与JAVA中间件实践学习笔记》-1

  这种方案可以让同样的Session请求每次都发送到同一个服务器进行处理,非常利于对Session进行服务器端本地缓存。不过带来以下问题:

  1. 如果服务器宕机或者重启,那个这台服务器上的回话数据会丢失。
  2. 回话是应用层信息,那么负载均衡要将同一个回话请求都保存到同一个Web服务器上的话,就需要进行应用层负载均衡,这个开销比第四层的交换要大。
  3. 负载均衡器会变为一个有状态节点,要将会话到具体Web服务器的映射保存。和无状态的几点相比,内存消耗更大,容灾方面会更麻烦。
Session Replication

  Session Replication在Web 服务器之间增加了会话数据同步机制,通过保证不同Web服务之间的Session数据的一致,来解决Session问题。一般的应用容器都支持Session Replication。和Session Replication相比,它对负载均衡设备没有要求,但是其本生也存在一些缺点。

  1. 同步Session数据造成了网络带宽的开销。
  2. 每台服务器都要保存保存所有的Session数据,如果整个集群的Session数很多,每台机器用户保存Session的数据占据内存严重。

《大型网站系统与JAVA中间件实践学习笔记》-1

Session 集中存储
《大型网站系统与JAVA中间件实践学习笔记》-1

  该方案的问题:

  1. 读写Session数据引入了网络操作,这相对于本地数据读取来说,问题就在于存在时延和不稳定性。
  2. 如果集中的Session服务器或者集群有问题,会对应用产生严重影响。
Cookie Based

  该方案通过Cookie来传递Session数据,将Session数据存放在Cookie中,然后在Web服务器上从Cookie中生成对应的Session数据。相对于Session 集中存储,这个方案不会依赖一个外部存储系统,也就不存在从外部系统获取、写入Session数据的网络时延。

《大型网站系统与JAVA中间件实践学习笔记》-1

  该方案存在的不足:

  1. Cookie长度的限制。
  2. 安全性。
  3. 带宽消耗。
  4. 性能影响。每次Http请求和响应都带有Session数据,对于Web服务器来说,在同样的处理情况下,响应的结果会减少,支持的并发数就越多。

4.数据库读压力变大,读写分离

采用数据库作为读库

《大型网站系统与JAVA中间件实践学习笔记》-1

  读写分离导致的问题:

  1. 数据复制问题。
  2. 数据源选择问题

  数据库系统一般都提供了数据复制功能,但是对于数据复制还需要考虑数据复制的时延问题。数据复制延迟会带来数据短期不一致问题。于此同时,对于写操作主要走主库,事务中的读也要走主库,也要考虑到备库相对于主库的延迟。

搜索引擎其实是一个读库

  搜索引擎要工作,首要的一点是需要根据被搜索的数据来构建索引。

《大型网站系统与JAVA中间件实践学习笔记》-1

  搜索集群的使用方式和读库的使用方式是一样的。可以从两个维度对搜索系统构建索引的方式进行划分:一种是按照全量/增量划分,另一种是按照实时/非实时划分。搜索引擎的技术解决了站内搜索时某些场景下的读的问题,提供更好的查询效率。

加速数据读取的利器-缓存

数据缓存

  大型系统中的数据缓存主要用于分担数据库的读的压力。一般在缓存中存放的是“热”数据而不是全部数据。应用访问缓存,如果缓存不存在,则从数据读出数据后放入缓存。

《大型网站系统与JAVA中间件实践学习笔记》-1

  使用缓存来加速数据的读取情况,一个很关键的指标是缓存命中率,因此缓存命中率较低,意味着还有不少的请求回到数据库中。同时数据的分布于更新策略也要结合具体的场景来考虑。在分布上,要考虑的问题是需要避免局部热点,并且缓存服务器扩展或者缩容要尽量平滑。而在缓存的更新上,后有定时失效、数据变更时失效和数据变更时更新等策略。

5. 引入分布式存储系统

  分布式存储系统起到存储的作用,也就是提供读写支持。相对于读写分离中“读”源,分布式存储系统更多是直接替代主库。分布式存储系统通过集群提供了一个高容量、高并发访问、数据冗余容灾的支持。

《大型网站系统与JAVA中间件实践学习笔记》-1

6. 读写分离后数据库又遇到瓶颈

专库专用,数据垂直拆分

  垂直拆分的意思就是把数据库中不同的业务数据拆分到不同的数据库中。

《大型网站系统与JAVA中间件实践学习笔记》-1

  不同业务的数据从原来的一个数据库中拆分到多个数据库中,就需要考虑如何处理原来单机中跨业务的事务。一种办法是使用分布式事务,其性能明显要低于单机事务;另一种办法就是去掉事务或者不去追求强事务支持。对数据库进行垂直拆分之后,解决了把所有业务数据放在一个数据库的压力问题。并且也可以根据不同的业务特点进行优化。

垂直拆分后的单机遇到瓶颈,数据库水平拆分

  数据库的水平拆分就是把同一个表中的数据拆分到两个数据库中。产生数据水平拆分的原因是某个业务的数据表的数据量或者更新量达到了单个数据库的瓶颈,这是就可以把这个表拆分到两个或者多个数据库中。数据库水平拆分会给业务带来一些影响:首先,要解决SQL路由的问题;其次主键的处理也会变得不同;最后由于同一个业务数据被拆分到了不同的数据库中,因此一些数据查询需要从两个数据库中读取数据,如果数据量较大需要分页就会比较难以处理。

7. 数据库问题解决之后,应用面对的挑战

拆分应用

  随着业务的发展,应用的功能越来越多,应用也会越来越大,这是需要把应用拆开,从一个应用变为两个甚至多个应用。

走服务化的路

  业务之间的访问不仅是单机内部的方法调用了,还引入了远程的服务调用;其次共享的代码不再是散落在不同的应用中了,这些实现被放在各个服务中心。

《大型网站系统与JAVA中间件实践学习笔记》-1