群,分布式,微服务区别就不多说了)知识点分为好几个大点:
1.集群中负载均衡
2.分布式数据库(重要是分布式事务)
3分布式缓存(可用redis)
4.分布式锁(可用redis)
5.分布式消息队列(每个服务之间如何通信的,如阿里的rocketMQ)
6.分布式文件系统
(下面简单的总结一下知识点之间的联系,后补充)
现在看springcloub的微服务思路:
客户端的请求首先经过负载均衡(Ngnix),再到达服务网关(Zuul 集群,一个负责网关的集群),然后再到具体的服务(每个服务下又有集群)。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理
zuul:是一个网关服务,不是用来负载均衡的,但是可以搭建他的服务网关集群,他的作用是降级、限流、认证授权、安全,等等
Eureka:分布式中各种服务的注册中心,注册者每一个服务集群有哪几台机器和他们的端口,这个框架技术一般会拿来和zookeeper比较,都是一个开放源码的分布式协调服务,它是集群的管理者。两者最大区别就是zookeeper满足CP,即倾向一致性,而Eureka满足AP,即倾向可用性。(CAP理论见下面分布式事务)。两者要共同解决的问题是如何保证不同机器上的分布式事务数据的一致性,而不是负载均衡。
Feign:A服务要调用B服务时,由他来建立A和B之间的网络连接,基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
Ribbon:比如A服务要调用B服务,但是B服务集群有几百个机器,到底访问哪一台,这个时候就由Ribbon来负载均衡,然后Feign发起请求
**Hystrix:**首先来了解什么是熔断和降级。看看一个场景,如果A调用B服务,但是B服务集群已经挂了,长时间没响应,难道A服务一直在那里等待??按之前的就会一直等,一天没返回就一直等最终导致整个系统崩盘。如果B服务不是必须的,也就是说B服务没有完成也可以正常完成客户需求就可以不等B服务返回就往下执行,把B服务熔断掉,降级了,等他B正常了可以手动恢复数据一致性。没必要等了,请求降级了。Hystrix就是完成一件事的,用不同的线程池去调用服务之间的请求,线程池之间独立,这样子就可以隔离熔断每个子服务。
负载均衡的方式
Ribbon:
在调用接口时,会在eureka(当然也可以是其他的注册中心)注册中心获取服务列表,然后缓存在本地,在本地实现远程调用。属于客户端测负载均衡
Nginx:
客户端所有的请求都会交给Nginx服务器,然后由Nginx实现请求的分发。属于服务器测负载均衡。
负载均衡的算法:
轮询法(Round Robin):
加权轮询(Weight Round Robin):加权随机法也根据后端服务器不同的配置和负载情况,配置不同的权重。不同的是,它是按照权重来随机选取服务器的,而非顺序
随机算法(Random)
源地址HASH算法(当同一IP地址客户端后端服务器列表不变时,每次都会路由到相同的服务器hashCode % serverListSize)
加权随机法(Weight Random)
最小连接数法(Least Connections)
网关集群(如zuul集群)
上游服务器:产生内容的服务器;下图为Nginx负载均衡zuul网关服务集群的配置。80是接受传来的请求接口,接收到请求后至于把请求给哪一个端口处理就看此时轮询到哪一台机器的哪一个端口,下面是三个zuul服务。再由这个zuul服务转发给具体的服务。
分布式数据库(重点解决分布式事务问题;)
垂直分表:在一个数据库中;将一个表按照字段分成多表,每个表存储其中一部分字段。(按照字段分)
垂直分库:指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。(按照业务表分)
水平分库:是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。(按实际数据内容分到不同的数据库)
水平分表:是在同一个数据库内,把同一个表的数据按一定规则(如:取模法)拆到多个表中。(按实际数据内容分到同一个数据库的不同表)
一个数据库只能解决自身的数据库事务的的ACID,分布式中有很多个服务,每一个服务都有自己的专用数据库集群,每一个集群中如何保持数据库的事务是很重要的,这就是数据库的分布式事务。分布式事务,事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
解决分布式事务的方案:以下方案解析参考 CAP理论基础:(Consistency一致性,Available可用性, Partition-tolerance分区容错性),三者不可兼得证明参考 Consistency (一致性):
“all nodes see the same data at the same time”,即更新操作成功并返回客户端后,所有节点在同一时间的数据完全一致,这就是分布式的一致性。一致性的问题在并发系统中不可避免,对于客户端来说,一致性指的是并发访问时更新过的数据如何获取的问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。
Availability (可用性):
可用性指“Reads and writes always succeed”,即服务一直可用,而且是正常响应时间。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。
Partition Tolerance (分区容错性):
即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。
分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,对于用户而言并没有什么体验上的影响。
Base理论:( Basically Available(基本可用)、Soft-state(软状态)和 Eventually Consistent(最终一致性)),三者不可兼得,只可两者。
二阶段提交协议:(准备,提交),
三阶段提交协议:(预备,准备,提交),
阿里的TCC方案:Try,Confirm,Cancel
可靠事件模式:
补偿模式:
分布式锁:控制分布式系统或者不同系统之间共同访问共享资源的锁实现
实现方法:
1.redis实现(用SETNE指令实现)
2.zoopkeeper实现
3.使用memcached的add()方法
4.基于数据库资源表做乐观锁,用于分布式锁
下面详细讲解一下redis如何实现分布式锁的:
设计思路: 设置锁健,及通过设置一个key值,作为锁,key存在在表示有锁,key不存在则表示无锁!
- setnx(lockkey, 当前时间+过期超时时间) ,如果返回1,则获取锁成功;如果返回0则没有获取到锁,转向2。
- get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。
- 计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。
- 判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功(getset指令是在已经获得该锁的的服务再进行getset指令的),获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。
- 在获取到锁之后,当前线程可以开始自己的业务处理,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时
分布式缓存
在上图中,当DB负载过高,我需要为Service机器加缓存时,就遇到一个基本问题:
如果使用local的内存做缓存,则其他Service机器就没办法共用此缓存。
因次,我需要一个可以让所有Service机器共享的缓存,这就是分布式缓存。
常用的分布式缓存组件:Memcached/Redis/Tair等
分布式文件系统
在上图中,当我要存储客户端上传的图片文件时,就会遇到另一个基本问题:我不能把图片存在每个Tomcat的本地文件系统里面,这样的话,其他机器就没办法访问了。我需要一个让所有机器可以共享的文件系统,这就是分布式文件系统。
常用的分布式文件系统:MogileFS/TFS/HDFS/Amazon S3/OpenStack Swift等
当使用了分布式文件系统,对外提供图片url访问服务时,就会遇到另一个基本问题:如果每次文件的访问,都要到分布式文件系统里面去取,效率和负载就可能成为问题。
为此,就需要引入CDN。
常用的CDN厂商,比如ChinCache。当然,现在的各种云存储,比如七牛云,阿里云,腾讯云,已经自带了CDN。
分布式RPC
分布式系统的一个基本问题就是:机器与机器之间如何通信? 我们都知道底层原理是TCP/IP,Socket。
但一般很少有人会去裸写Socket,实现机器之间的通信。这里,最常用的组件就是RPC。
最简单的实现RPC的方式就是使用http。当然,业界有很多成熟的开源RPC框架,如Facebook的Thrift, 阿里的Dubbo,点评的Pigeon。。
在RPC内部,一般都自己实现了负载均衡。还有更复杂的,如多版本,服务降级等。
补充一句:虽然底层原理都是Socket,但使用不同框架/组件时,通常都有其自己的跨机器通信方式,比如MySQLJDBC,RPC, 消息中间件等。
分布式消息中间件
在上图中,没有提及到消息中间件。相对其他基本问题,这个需要一个更适合的业务场景来谈,在以后的章节中,会再详述。
常用的消息中间件,比如老一辈的ActiveMQ/RabbitMQ, 新一点的,阿里的RocketMQ,LinkedIn的Kafka等。
消息中间件的一个典型场景就是:通过最终一致性,解决上面的分布式事务问题。
分布式session问题
在传统的单机版应用中,我们经常使用session。而当单机扩展到多机,单机的session就没办法被其他机器所访问。
此时就需要使用分布式session,把session存放在一个所有Tomcat都可以访问的地方。