分布式系统
特色:
1.系统各组件分布于网络上多个计算机上
2.咱们部署的各功能组件彼此之间仅仅经过消息传递来通讯,达到协调行动的目的。
知足这两点,你的系统就是分布式系统
分布式系统存在的意义:
向上扩展达到瓶颈:
1.即单机上不管你增长内存,磁盘,CPU个数,其性价比很难再提不上去了。
2.性能达到临界点后,性能将不升反降。
3.单点故障没法避免,故障后一切扩展都将不可用。
基于冯诺依曼的计算机架构,对于当前来讲已经没法从单机上获得更好的总体系统性能。摩尔定律说计算机硬件技术会每18个月更新一次,在当今世界也在改变,硬件的提高会逐渐达到提高瓶颈,而数据则会在18个月后翻一倍,因此咱们已经进入一个大数据的时代。另外,摩尔定义也向咱们说明了一个问题,今天你花多大的价钱买的硬件,在一年半(18个月)后都会落后。
多CPU:
硬件技术进步,让单机计算能力出现了太多空闲,所以多线程编程技术就成为了最佳的提升性价比的方式。
多线程编程模型:
1. 互不通讯的线程模型: 这些模型的性能是最好的,执行效率也是最高效的,但实用性可能不高。
2. 基于共享容器协同工做的模型:
A线程运行过程当中,须要从B线程哪里获取一个结果,才能继续运行,若此时A线程直接去启动B线程,
这实际上是至关麻烦的事,若借助中间容器,这里指队列,A线程经过将请求发给队列,而后,B线程
从队列中获取请求,执行结束后将结果再放回队列中,A线程从队列中获取结果后,就能够继续执行了。
这种就是共享容器模型,它能够实现让多个线程并行协同运行。
为了使这种共享容器模型在多线程并行时,访问数据更加安全,它又分为两种类型:
a. 线程安全
指A线程修改了共享容器中的A数据,而C去访问A数据或修改A数据也同样能够,它们之间都是
互相独立,互不干扰的,这种就称为线程安全的模型。
b. 线程不安全
指A线程修改了共享容器中的A数据,而C线程此时也去修改A数据,就可能致使A数据损坏,这种
就称为线程不安全。 对于线程不安全的类型,一般使用加锁的机制 或 Copy on Write(COW)
的方式来保障数据安全,在使用加锁的机制时,若并发线程数不少时,一般会使用互斥锁。
这种方式中线程之间是须要互相通讯的,所以就会形成等待结果的一方将不能继续运行,因此这其实
就会下降多线程并行执行的效率了。
3.经过事件协调的多线程模型
B的某个执行流程依赖于A完成了某种特定操做以后才能进行。那么A就须要在某个特定操做完成以后,
触发一个事件,这个事件能够通知给B,因此B拿到这个事件后,就能够继续运行了,因此在A触发这个
事件以前,B就只能处于等待事件的状态。
多线程 和 多进程模型的区别:
线程之间是可共享父进程内部的不少资源,如:父进程打开的文件句柄,内部信号等等。
进程之间是互相隔离的,它们仅能经过进程间通讯模式进行交互通讯,因此多进程模型比多线程模型,在资源控制方面更为简单。
这些模型的出现,主要是为了使用多CPU,由于,单个CPU已经不能经过提高频率来提高其性能,目前芯片厂商都是经过增长CPU的核心数,借助于多线程编程,来解决单机上面性能的提高问题。但多线程编程又很是复杂,若程序员不能很好的利用多核心来编程,对于多核来讲效益是很小的。
网络I/O:
1.经过阻塞模型,即一个请求过来,在处理它时,其它请求都被阻塞等待第一个请求处理完才能被接入进来进行处理,因此这种模型目前已不在使用。
2.多进程模型,即每一个进程响应一个请求;
3.多线程,多进程,即每一个进程生成多个线程,每一个线程响应一个用户请求。
4.多线程,每一个线程直接响应多个请求。
可是不管是那种方式,每个请求进来都须要有一个对应的套接字。
前端
基于socket实现网络通讯开发,其实现方式主要有三类:
BIO: Blocking IO,即阻塞式IO:一个Socket套接字须要一个进程或一个线程来处理,那么链接的创建读数据写数据的过程都有可能产生阻塞,这种机制就是每进程 或 每线程响应一个请求的模式。
缺点:每一个链接都要占用一个套接字. 【注:套接字有两种:链接和监听套接字】
NIO: Nonblocking IO,非阻塞I/O,它是基于事件驱动(Linux是epoll实现事件驱动的.)的思想,采用Reactor模式,实现响应。
优势: 一个套接字分配个一个线程,而一个线程能够处理多个套接字相关的工做。
AIO:异步IO模式,它也是基于事件驱动的思想,但它采用Proactor模式
如何把应用从单机扩展到多机?
输入、输出设备如何变化?
控制器如何变化?程序员
实现的模式:
透明代理: 即用户访问时,已经给咱们响应的就是服务器,其实多是如下这些,这种就属于对用户透明的.
并且中间的转发控制器就成为网络的中心。以下:
LVS的NAT模型,
Haproxy, Nginx的反向代理
旁路代理
LVS的DR模型
名称服务模式:
DNS: 用户仅第一次访问时,须要查询,DNS经过名称给客户端反馈不一样的解析IP,实现调度控制。
规则服务模式:
规则服务器:在数据库服务中,当数据库很大时,须要分库,分表时,就须要规则服务器在中间作为一个向导,
告诉第一次访问数据的客户端,你须要的数据是分散在多个主机上,仍是一个节点上。
Master/Slave机制:
Master可以处理全部请求,Slave仅作为运算器分担部分读运算任务,Master须要控制给Slave发送数据,
因此Master也是一种控制器。
算法
运算器的变化: 【暂时理解不深】
存储器的变化: 【暂时理解不深】
分布式系统实现的难点:
1.缺少全局时钟: 在单机中,CPU的每秒中能产生不少个时钟频率,可是其它部件的功能频率相对与CPU来讲是极慢的,为了达到步调一致,单机内部经过中断等机制实现协同工做。
2.面对故障时的独立性
3.处理单点故障
4.事务处理:
ACID
2PC(两段式提交)、BASE、CAP、Paxos(帕克索斯:希腊神话中的天马)
大型网站站点的架构演进方式:
LAMT, LNMT(Tomcat)
应用从资源占用的角度分两类:
CPU Bound: CPU密集型,ApplicationServer对CPU占用多。
IO Bound: IO密集型, 数据库对IO占用多。
网站从最开始一台主机上运行一个Nginx代理 + Tomcat应用服务器 + MySQL数据库.数据库
当网站访问量增大时,首先出现告警的多是MySQL数据库,由于磁盘I/O天生是系统的瓶颈,所以数据库先被分离出来,这样数据库压力就变小了。
引入MySQL主从面临的问题:
1. 数据复制的问题
2. 应用选择数据源的问题编程
接着网站访问量继续增大,Tomcat这类应用服务器,Nginx代理等都属于CPU密集型,它们在单机上出现了CPU资源争用的问题,这仅是小问题,更重要的是应用服务器出现了数据访问的热区,基本上会遵循二八定律,这时就必须分离,而且增长应用服务器,你的系统就变成了两台应用服务器,这时前端必须有一个反向代理,因此加上MySQL就是四台主机.但应用服务器分开后,就须要用户访问的会话保存问题,有如下三种解决方案:
Session sticky:会话粘性,存在单点故障,必定其中一台Server宕机,会话将丢失。
ip based:
cookie based:它带来的额外问题是,带宽占用将很是巨大,若一个cookie仅50字节,可是若一天一亿个请求,就有一亿个50字节,有多大?
Session replication: 会话复制,不适合大规模使用,由于一方面会消耗Server的内存,另外一方会带来大量的内网同步Session的流量,影响总体网络环境。
Session server:经过Memcached来集中存储用户会话,扩展性好,适合大规模扩展。
若考虑到网站在一年内可能出现几何增加的可能,如:从200并发到过万的并发,这时使用前两种会话保存就不合适了,就必须使用第三种方案。后端
引入搜索引擎实现全文搜索:
网站演变到这里,咱们须要知道问题的核心在哪里,数据库中的数据最终是要让用户能够查询到的,由于 用户不能在你的网站一个一个网页去翻,而后去找到本身须要的商品,一般都是经过搜索定位到他们须要的商品,那这时仅靠MySQL很难实现了,由于咱们的电商网站的数据库是须要支持事务,但MyISAM存储引擎支持全文索引,但不支持事务,因此它并不是最佳途径,咱们就须要另拿一台服务器专门安装MySQL使用支持全文索引的存储引擎,将现有MySQL的Slave节点上将数据都读出来,在它上面作全文索引,而后,前端本身开发的索引引擎,经过搜索全文索引数据库,来响应用户的搜索请求,因此Slave读取Master上数据的及时性就显得很重要了,由于新上架是商品可否让用户看到,取决于搜索库中有没有从Slave库中读到新商品数据。缓存
引入缓存
当咱们的网站中应用服务器的压力主要集中在对不少静态内容的处理上时,那咱们就须要使用动静分离技术,但比它更使用的此时应该是缓存,在负载均衡器后面第一级,先引入缓存,把不变化的静态内容直接缓存在应用服务器的前端缓存服务器中,甚至还可使用AJAX技术实现缓存网页中的一部分数据,另一部分变化的数据,到后端去计算后获得,好比一个淘宝页面,第一用户看商品页面和第二个用户看的商品页面是同样的,这时就能够缓存这个页面,但有可能第二个用户看时,这个商品已经卖出去了2个,因此仅须要从后端应用服务器上获取这部分变化的库存量信息就能够了,这样能够更大程度减小后端的压力。
引入缓存要考虑两个方面的问题:
1.页面缓存
varnish, squid
2.数据库缓存
由于数据库节点可能也会逐渐增长,而查询缓存仅在数据库本地有效,为了提升命中率,增长数据库缓存也是必须的。
对于数据库缓存,要使用Key-Value类型的存储,而Memcached是其中最具表明性的。
若引入Memcached,将会引入新问题:
a. 须要自行开发程序调用Memcached的API实现存储。
b. 须要自行管理其数据有效期。
注意:
引入缓存,可能不会只有一台,或者说会逐渐增长成多台,这时咱们就能够称这种缓存架构为分布式缓存,在分布式缓存中,要提升数据的命中率,就必须使用哈希算法,来提升命中率。安全
当网站规模继续增大时,接下来面临压力的必定就是数据库的写库。
对于数据库写库的分担,只有数据库拆分这一条路.
垂直拆分:把数据库中不一样的业务的数据拆分到不一样的数据库中,它缓解的是读压力.
假如以电商网站来讲:将它的用户表,交易表,商品表分别分到三个库,但咱们知道,
咱们到淘宝上买的东西,咱们会去搜索用户吗?会搜索其余人的交易信息吗?
不会,甚至也不容许,因此商品表被读的压力就会很大,所以它是必定要作主从的,
其它库能够从数据安全性角度来讲,也能够作主从。
因为数据库级别拆分红多个了,这时咱们访问数据库就必需要知道咱们访问的数据在哪里
因此前端应该还要有规则服务器来告知前端应用数据在那台后端数据库上。服务器
静态内容: 如用户证书,用户生物信息,交易历史记录,商品图片等
FTP上传: 如: 商品图片,用户身份证图片,文档等
水平拆分:把一个单独的表中的数据拆分到多个不一样的数据库服务器中,它缓解的是写压力。
假如立刻要到剁手节,将产生大量用户产生交易信息,交易表可能受不了,那怎么办?
这就须要分担对交易表的写压力,对交易表咱们能够根据用户年龄来拆分,将年轻群体
中消费能力弱的18-20的分到一张表,消费能力较强的21-25分一张表,26-29分一张表,
等等,来拆分表,可是表拆分完了后,该怎么去访问?前端应用怎么知道我要访问的数据
在哪里存储?由此规则服务就更加剧要了。cookie
引入NoSQL: 非关系型数据库
文档数据库
列式数据库
....
DFS: 非结构化数据
TFS, MogileFS: 适用于海量小文件
HDFS, GFS: 少许大文件
CDN的使用:
越向后,系统的访问量越大,这时内部整个机房的扩容若在继续扩大,不在是解决问题最有效的手段,并且主机数量也总有上限,可是前端的压力已经让负载和缓存吃不消了,在这时最佳的手段就是引入CDN,目前国内比较知名的CDN厂家有 BAT,蓝汛等。 CDN它可以实现让用户直接在家门口的缓存服务器上获取要咱们的网站数据,这样就有效的分散了到达咱们主站的流量压力,当用户访问咱们网站时,智能DNS一般会,根据用户所在地区为用户解析域名,它会依据缓存服务器距离用户地理位置最近,或带宽最大等信息,作智能判断并返回用户一个域名,这个域名一般是一个负载均衡器的域名,用户进行二次解析后,获得距离本身最近的缓存集群,该缓存集群的负载均衡器将用户请求接入进来,在后端缓存服务器上查询,若命中,则直接返回数据给用户,若未命中,则向最近的缓存节点查询,无数据则由该缓存节点,向咱们网站发起请求,网站响应该请求时,先查询本地缓存,命中则直接返回,未命中则继续向下,到应用服务器,由应用服务器处理此请求,并经过查询数据库等一系列业务逻辑处理,返回结果给CDN的缓存节点,由该节点再向用户返回数据。
应用拆分:
根据业务特性拆分
根据用户拆分
如: 用户注册应用
用户登陆应用
用户信息维护应用
根据对底层应用的调用进行拆分
异步: 解耦
消息中间件:
它是协调多个应用之间,经过消息传递的方式来实现其功能协调的机制,它的整个工做过程是
经过异步方式实现的。因此它在分布式系统中,是消息接收和发送的基础性软件。
它最大的特色就是:异步和解耦。
MOM:Message-oriented middleware.
现有的比较知名的消息中间件:
RabbitMQ, ActiveMQ, ZeroMQ(ZMQ)
注: 它们仅能工做于它们支持的模型中。
模块化:
服务化:
当网站的结构发展到服务化后,每一个层均可能出现大量重复代码,但这是不可避免的。
一旦架构进入这样的级别,不管是垂直仍是水平拆分都会面临ACID被打破的问题,此时只有两种选择,放弃事务 或 引入分布式事务! 在进行Join查询时,也将变得异常困难,原来依赖与外键实现的约束将无从保证等等问题,都将面临巨大的挑战。面对这些挑战,咱们惟一能作到就是从理论出发,结合实际去构建适合本身实际需求的解决方案。