曾经架构在我以前看来,多么高大上的词啊,可望不可及;
在看了很久分布式的文章、书籍和架构后试着总结了一番;
此文的应用场景是超大用户系统的发展进程;
下面大家就听我娓娓道来吧~
最开始的应用是单一的应用,入下图;
1、单一应用
在诞生之初始,应用与数据库是部署在同一台机器上,这时的用户量、数据量规模都比较小,这样的架构既简单实用、便于维护,成本又低,成为了这个时代的主流架构方式。随着用户量的增大,访问量急剧增加;于是到了下一步;
2、垂直应用
配置三台服务器,一个应用服务器,一台DB服务器,一台文件服务器;
垂直型应用架构,是指将一个大的单一应用拆分成若干个小的单一应用,这样每个应用的压力大约有原来的1/n(粗略估计值)。这种拆分方式为后来的技 术发展奠定了基础,每次架构的变化都与这次有着密不可分的关系——分治(将一个大的问题按一定业务规则分成若干个小的问题,逐个解决)。 一台文件服务器挂了但还是能访问应用和数据库的; 这样将应用分成不同的业务,可以提升访问效率;
这时我们发现有很多业务的访问,非常集中;即2 8原则,80%的业务集中在20%的数据上,于是我们可以使用缓存技术讲这20%的数据缓存下来,性能一下子就上来了;缓存又分为两种,一种是本地缓存(Local Cache),一种是远程缓存(Remote Distributed Cache);远程缓存又分为单机缓存和分布式缓存;
这时我们使用了缓存的技术,性能的瓶颈来到了服务器,单台再强大的服务器也不行了,于是我们使用了服务器集群
通过Nginx的反向代理,通过负载均衡的调度,可以在一定程度上解决服务器处理能力的瓶颈;
负载均衡的策略有:
轮询:每一次来自网络的请求轮流分配给内部中的服务器,从1至N然后重新开始。此种均衡算法适合于服务器组中的所有服务器都有相同 的软硬件配置并且平均服务请求相对均衡的情况。实现简单,但存在服务器的处理能力不同的情况;
权重:根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器A的权值被设计 成1,B的权值是3,C的权值是6,则服务器A、B、C将分别接受到10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务 器得到更多的使用率,避免低性能的服务器负载过重。考虑了服务器处理能力的不足;
随机均衡:把来自网络的请求随机分配给内部中的多个服务器。
地址散列:又分为原IP地址散列,目标IP地址散列; 针对目标IP地址的负载均衡,但它是一种静态映射算法,通过一个散列(Hash)函数 将一个目标IP地址映射到一台服务器。
还有基于以上几种延伸出来的策略,比如:
最小连接:可以使集群中的服务器负载得更均匀;
权重最小连接:客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡 算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服 务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器, 使均衡更加符合实际情况,负载更加均衡。此种均衡算法适合长时处理的请求服务,如FTP。
服务器是做集群了,系统的性能是得到优化了,但是问题又来了;seesion如何管理?
假设一个用户登录了A服务器,session信息存储到了A服务器上了,假设我们使用的负载均衡策略是用的地址散列,根据ip进行hash散列;可以保证用户的登录信息在A服务器上访问到,但是某些特殊情况,可能存在同一台服务器被散列到了巨多的请求压力过大,某些服务器又没有什么压力这时性能瓶颈又来了~
那么我们用轮询或者最小连接的负载均衡策略好了;用户登录了A服务器,session信息存储到了A服务器上,但第二次访问的时候呢,访问的是B服务器,这时存贮在A服务器上的session信息,我们在B服务器上是读取不到的;这时候我们就要解决session管理的问题了;
Browser1 访问应用时,它的seesionID 可能一开始是存在 服务器A上的,如果这个A服务器挂掉了,Browser1又要去访问服务器2,而服务器二又是没有用户Browser1的seesionID;这时的解决方案是:Browser1经过Nginx把session存到A服务器上时,会把Browser1的seesion复制到B服务器上;也就是这两个服务器都保持着Browser1的sessionID;
好的,这个时候session共享的问题解决了,但新问题又出来了,A服务器跟B服务器之间要不断的同步session信息,当大量的用户都在线的时候,服务器之间占用的内存会过多,不适合做大规模的集群,只适合一些机器不多的情况; 不要着急,解决方案还是有的:那就是使用Cookie;
大家应该都知道session和cookie的区别吧,这里就不做过多的介绍了;
我们让携带着session信息的cookie去访问我们的应用服务器,这种方式解决了session共享的问题,但是问题又来了.......
cookie的长度是有限制的,cookie是保存在浏览器上的,安全性也是一个问题; 怎么办呢....
我们可以增加一个seesion的服务器;
这样,用户的请求路径就变成了,Browser1通过Nginx请求到A服务器,然后把Browser1的session存到session服务器中,当想获取用户的seesion的时候,往session服务器里拿就是的了; 把所有的session 都放到session服务器当中就解决 了这个问题; 但此时session服务器又是单点的,为了保证可用性,在用户量大的时候,可以将session服务器做成集群;
好的,关于session的问题又解决了;但问题又来了!!!
一个庞大的系统毕竟是给大量的用户使用的,随着用户量的增加,系统的升级再所难免,这时的瓶颈不在服务器的处理上,不在负载均衡的策略上,不在缓存技术上了,而是在数据库上了;
如果是上面这个架构图,我们的读与写的操作,都要经过同一个数据库服务器,在大量用户访问的情况下,数据库的并发量有限,为了保证数据的四大特性难免会发生阻塞;我们可以将数据库进行读写分离,来保证数据库的高可用性;
写的操作放在主库,读的操作方在从库;于是就有了下面这个图;
Master是主库,Slave是从库,所有的写操作将引入主库,读操作引入从库;极大程度的缓解数据库锁之间的竞争;提高了并发吞吐和负载能力。
数据库的问题暂时解决了;以后还会有还有新的问题吗?还会有的~如何提高不同地区的访问速度?应用服务器增加了集群,数据库服务器也读写分离了,但文件服务器呢??于是有了下面这个架构图;
使用CDN可以很好的解决不同的地区访问速度的问题,又把文件服务器改成了集群的形式;在使用分布式文件系统的时候又有问题了...
1、如何不影响已经部署在线上的业务访问,不能让某个图片突然就访问不到了;
2、是否需要备份服务器?
3、是否要重新做域名解析?
这一块的问题待补充吧.... 因为我还没有把那个分布式文件存储系统的书看完。。以后会补充好的
这是数据库又他瞄的出问题了,读写分离还是慢啊,怎么办?我们使用专库专用的方式来进行数据的垂直拆分;
不同的业务,使用自己的库,这样,读写数据,并发量上不去的问题问题就都解决了;但是每个业务用的数据库都不一样又会有哪些新问题的?
1、跨业务的事务,跨库的事务; 可以用分布式事务来解决
2、随着业务用户群体的不断变大,某单个数据库又会成为性能的瓶颈;这时我们又要将单个数据进行水平拆分;架构图如下,只是把users库分为users1、users2; 这是不是和开始的All in one 到垂直拆分类似了?
在水平拆分后,又会有sql路由的问题,假设我们有一个用户,他的信息是存在了users1当中还是user2当中了呢?
同时还有出现分页的问题;假设有这么个需求,让我们查询2016年双11有多少用户在淘宝下过单,这些用户存在不同的数据库中,后台的运营管理系统如何进行展示呢?分页也是一个问题。
写了这么多,大家可以看到,大型系统架构的演进过程中有非常多的问题;但是遇到问题的解决思路肯定会是类似这个样子的;
那么我们可以理解解决高性能问题,可以将单一的应用垂直拆分成几个不同的业务去划分;
解决高可用的问题,我们可以将单点的服务器做成集群;比如上图,如果负载均衡的服务器挂了,后面一系列的应用服务器集群是不是都没办法用了?
解决高并发的问题,以后再说哈~~
公司的业务需求不同,性能需求也不同;上面的这个架构图可能也不是最后的形态;我想每个公司的业务不同,架构肯定也是不同的;
这漫长的演变过程中还有系统的安全性,数据分析,监控,反作弊等问题需要解决;
最后的SOA架构,微服务化,消息队列,任务调度,多机房部署这些名词我也紧紧只有浅薄的了解;
知识越学越多,想到淘宝的系统得多么的庞大才能支撑起上亿的并发量。想想就觉得恐怖,大神们太牛逼了;
同样的,任何网站的架构都是从小做起的,学习也是,希望菜鸟几年后也能成长起来~~
上面只是对分布式系统架构的演进进行了介绍,并没有介绍当前流行的一些分布式技术如何在当中使用;以后会娓娓道来......静待.......