其他理论框架面试题

巩固基础,砥砺前行 。
只有不断重复,才能做到超越自己。
能坚持把简单的事情做到极致,也是不容易的。

Zookeeper中的领导者选举的流程是怎样的?

Zookeeper集群中节点之间数据是如何同步的
Mysql索引使用的是B+树,因为索引是用来加快查询的,而B+树通过对数据进行排序所以是可以提高查询速度的,然后通过一个节点中可以存储多个元素,从而可以使得B+树的高度不会太高,在Mysql中一个Innodb页就是一个B+树节点,一个Innodb页默认16kb,所以一般情况下一颗两层的B+树可以存2000万行左右的数据,然后通过利用B+树叶子节点存储了所有数据并且进行了排序,并且叶子节点之间有指针,可以很好的支持全表扫描,范围查找等SQL语句。

什么是CAP理论

CAP理论是分布式领域中非常重要的一个指导理论,C(Consistency)表示强一致性,A(Availability)表示可用性,P(Partition Tolerance)表示分区容错性,CAP理论指出在目前的硬件条件下,一个分布式系统是必须要保证分区容错性的,而在这个前提下,分布式系统要么保证CP,要么保证AP,无法同时保证CAP。
分区容错性表示,一个系统虽然是分布式的,但是对外看上去应该是一个整体,不能由于分布式系统内部的某个结点挂点,或网络出现了故障,而
导致系统对外出现异常。所以,对于分布式系统而言是一定要保证分区容错性的。
强一致性表示,一个分布式系统中各个结点之间能及时的同步数据,在数据同步过程中,是不能对外提供服务的,不然就会造成数据不一致,所以
强一致性和可用性是不能同时满足的。
可用性表示,一个分布式系统对外要保证可用。

CAP理论,BASE理论

Cpnsistency (一致性):
即更新操作成功并返回客户端后,所有节点在同一时间的数据完全一致。
对于客户端来说,一致性指的是并发访问时更新过的数据如何获取的问题。
从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。
Availability(可用性):
即服务一直可用,而且是正常响应时间。系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体
验不好的情况。
Partition Tolerance(分区容错性):
即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,对于用户而言并没有什么体验上的影响
CP和AP:分区容错是必须保证的,当发生网络分区的时候,如果要继续服务,那么强一致性和可用性只能2选1
BASE是Basically Available(基本可用)
Soft state (软状态)和Eventually consistent(最终一致性)
BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
基本可用:
•响应时间上的损失:正常情况下,处理用户请求需要0.5s返回结果,但是由于系统出现故障,处理用户请求的
时间变为3s。
系统功能上的损失:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的部分
非核心功能无法使用。
软状态:数据同步允许一定的延迟
最终一致性:系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态,不要求实时

你知道CAP定理和BASE理论吗?

CAP定理
Consistency一致性(节点或系统中所有可用数据)
在分布式环境下,一致性是指数据在多个副本之间能否保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操。
·如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。

Consistency一致性
一致性指“all nodes see the same data at the same time”,即所有节点在同一时间的数据完全一致。
一致性是因为多个数据拷贝下并发读写才有的问题,因此理解时一定要注意结合考虑多个数据拷贝下并发读写的场景。对于一致性,
以分为从客户端和服务端两个不同的视角。
对于一致性,可以分为从客户端和服务端两个不同的视角
对于一致性,可以分为从客户端和服务端两个不同的视角。
客户端
从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题。
服务端
·从服务端来看,则是更新如何分布到整个系统,以保证数据最终一致。
对于一致性,可以分为强/弱/最终一致性三类
、从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。
强一致性
·对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。
弱一致性
其他理论框架面试题_第1张图片
·如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
Availability 可用性
。可用性指“Reads and writes always succeed”,即服务在正常响应时间内一直可用。
对于一个可用性的分布式系统,每一个非故障的节点必须对每一个请求作出响应。所以,一般我们在衡量一个系统的可用性的时候,
是通过停机时间来计算的。

通常我们描述一个系统的可用性时,我们说淘宝的系统可用性可以达到5个9,意思就是说他的可用水平是99.999%,即全年停机时
间不超过(1-0.99999)36524※60=5.256 min,这是一个极高的要求。
好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。一个分布式系统,上下游
设计很多系统如负载均衡、WEB服务器、应用代码、数据库服务器等,任何一个节点的不稳定都可以影响可用性。
Partition Tolerance 分区容错性
分区容错性指”the system continues to operate despite arbitrarl
message
loss or failure of system”,即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。
分区容错性和扩展性紧密相关。在分布式应用中,可能因为一些分布式的原因导致系统无法正常运转。好的分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,或者是机器之间有网络异常,将分布式系统分隔未独立的几个部分,各个部分还能维持分布式系统的运作,这样就具有好的分区容错性。
简单点说,就是在网络中断,消息丢失的情况下,系统如果还能正常工作,就是有比较好的分区容错性。

那么CAP理论中的一致性、可用性和分区容忍性不能同时满足呢?

定理指出对于一个分布式系统来说不可能同时满足以上三种特性。在理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又导致丧失了P性质。也就是说,如图所示的三者交叉的位置,是不可能实现的。既然CAP三者同时满足的条件是不可能的,所以在系统设计的时候就需要作出取舍,比如弱化某些特性来支持其他两者。
弱化一致性 对结果不敏感的应用,可以允许在新版本上线后过一段时间才能更新成功,不保证强一致性,保持最终状态的一致性。典型的
如,静态网站。
弱化可用性 对结果一致性很敏感的应用,如银行取款机,当系统发生故障时停止服务。如清结算,转账等。目前的paxos、raft等算法都是为
保证强一致而设计的。这些系统会在 内部异常时拒绝或者阻塞客户端请求。
弱化分区容错性 现实中,网络分区出现概率较小,但难以避免。实践中,网络通信通过双通道等机制增强可靠性,达到高稳定的网络通信。

CP和AP架构的取舍

其实在实际工程中,可用性和一致性并不是完全对立的,我们往往关注的是如何在保持相对一致性的前提下,提高系统的可用性。
至于是使用CP或者AP架构,则取决于业务对一致性的要求。
CP架构:放弃可用性,追求一致性和分区容错性
举个栗子,ZooKeeper就是采用了CP一致性。
Zookeeper Service

ZooKeeper 是一个分布式的服务框架,主要用来解决分布式集群中应用系统的协调和移置性问题。在ZooKeeper中,对应每一个事务操作请求,ZooKeeper都会为其分配一个全局唯一的事务ID,每个事务ID对应一次更新操作,从这些事务ID中可以间接识别出ZooKeeper 处理这些事务操作请求的全局顺序。
AP架构:放弃强一致性,追求分区容错性和可用性
举个栗子,Eureka就采用了AP可用性。
Eureka 是Spring Cloud 微服务技术栈中的服务发现组件。

什么是BASE理论

由于不能同时满足CAP,所以出现了BASE理论:
1.BA:Basically Available,表示基本可用,表示可以允许一定程度的不可用,比如由于系统故障,请求时间变长,或者由于系统故障导致部分非核
心功能不可用,都是允许的
2.S:Soft state:表示分布式系统可以处于一种中间状态,比如数据正在同步
3.E: Eventually consistent,表示最终一致性,不要求分布式系统数据实时达到一致,允许在经过一段时间后再达到一致,在达到一致过程中,系统也是可用的

BASE理论

Basically Available(基本可用)
分布式系统在出现不可预知故障的时候,允许损失部分可用性
Soft state (软状态)
软状态也称为弱状态,和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允
许系统在不同节点的数据副本之间进行数据听不的过程存在延时。
Eventually consistent (最终一致性)
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要
系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性
那我们再来看看 Base 理论(Basically Available(基本可用)、Soft state(软状态)、Eventually consistent(最终一致性)的缩写);它基于CAP定理逐步演化来的,它是CAP中一致性和可用性权衡的结果,其核心思想是即使系统无法达到强一致性,可以根据应用自身的业务特点,采用适当的方式来使系统达到最终一致性。
基本可用是指当分布式系统发生故障的时候,允许损失部分可用性。常见的有以下几种情况:
响应时间上的损失:正常情况下,一个在线搜索引擎需要再0.5秒之内返回给用户响应的查询结果,但由于出现故障,查询结果的响应时
间增加到了1~2秒。
功能上的损失:通常的做法是降级服务,如对于展示一些有序元素的页面,但部分组件出现故障时,这个时候可不展示有序元素,降级为
无序元素列表。
软状态是指允许系统中的数据存在中间状态,并认为该中间状态的存在不影响系统的整体可用性,即允许系统不同节点的数据副本之间进行数

什么是RPC

RPC,表示远程过程调用,对于Java这种面试对象语言,也可以理解为远程方法调用,RPC调用和HTTP调用是有区别的,RPC表示的是一种调用远程方法的方式,可以使用HTTP协议、或直接基于TCP协议来实现RPC,在Java中,我们可以通过直接使用某个服务接口的代理对象来执行方法,而底层则通过构造HTTP请求来调用远端的方法,所以,有一种说法是RPC协议是HTTP协议之上的一种协议,也是可以理解的。

dubbo 负载均衡策略都有哪些?

  1. RandomLoadBalance
  2. RoundRobinLoadBalance
  3. LeastActiveLoadBalance
  4. ConsistentHashLoadBalance

dubbo 工作原理

其他理论框架面试题_第2张图片

Tomcat的最大线程数为什么默认是200?

首先,200只是一个默认值,一般默认值代表大多数情况,按照自己的情况进行修改,所以我们不应该纠结为什么是200,而不是300,这里我们应该想的是,为什么是200,而不是20,因为我们都知道并不是线程越多越好,我们一般会根据计算机的核心数来设置线程数,比如16核,那么要么我们就设置16个线程,或32个线程,怎么也不会设置到200个线程,那么Tomcat为什么默认给的是200,给的这么大呢?
我个人认为,之所以这么设置,是为了用户体验。
举个例子,假如你去银行取钱,但是现在只有一台点钞机,正常来说,就开一个窗口就好了,反正就一台点钞机,那对于客户来说,到底是开一个窗口让人心里舒服些,还是开10个窗口
让人舒服些呢?
按我去银行取钱的经验来说,是10个,因为我不想排队,这样能让我更快的感受到自己被服务了,虽然服务过程会比较慢。
回到Tomcat,也是一样的,Tomcat中的线程是用来处理客户所发送过来的HTTP请求的,如果只有16个线程,那就表示同一个时刻只能处理16个请求,如果每个请求都需要查询数据库,
都需要进行磁盘10或网络10,那这16个线程一下子就被这16个请求占用完了,当第17个请求过来时,就没有线程能处理它了,只能排队等着,设置会被拒绝服务。
而Tomcat把线程数设置为200,显而易见,此时Tomcat就能同时处理200个请求了,这个对于发送请求的客户来说体验是比较好的,自己发送的请求正在被处理了,虽然可能会慢一些,
但是我更加不愿意排队。

什么是集群脑裂?如何解决脑裂问题?

什么是脑裂
脑裂(split-brain)就是“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”,我们都知道,如果一个人有多个大脑,并且相互独立的话,那么会导致人体“手舞足蹈”
“不听使
脑裂通常会出现在集群环境中,比如ElasticSearch、Zookeeper集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如ElasticSearch集群中有Master节点,Zookeeper集群中有Leader节点

本篇文章着重来给大家讲一下Zookeeper中的脑裂问题,以及是如果解决脑裂问题的。
Zookeeper集群中的脑裂场景
对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由6台zkServer所组成的一个集群,部署在了两个机房:

其他理论框架面试题_第3张图片
正常情况下,此集群只会有一个Leader,那么如果机房之间的网络断了之后,两个机房内的zkServer还是可以相互通信的,如果不考虑过半机制,
其他理论框架面试题_第4张图片

这就相当于原本一个集群,被分成了两个集群,出现了两个“大脑”,这就是脑裂。

对于这种情况,我们也可以看出来,原本应该是统一的一个集群对外提供服务的,现在变成了两个集群同时对外提供服务,如果过了一会,断了的网络突然联通了,那么此时就会出现问题了,两个
集群刚刚都对外提供服务了,数据该怎么合并,数据冲突怎么解决等等问题。
刚刚在说明脑裂场景时,有一个前提条件就是没有考虑过半机制,所以实际上Zookeeper集群中是不会出现脑裂问题的,而不会出现的原因就跟过半机制有关。
过半机制
在领导者选举的过程中,如果某台zkServer获得了超过半数的选票,则此zkServer就可以成为Leader了。

其他理论框架面试题_第5张图片

当机房中间的网络断掉之后,机房1内的三台服务器会进行领导者选举,但是此时过半机制的条件是set.size(>3,也就是说至少要4台zkServer才能选出来一个Leader,所以对于机房1来说它不能选
出一个Leader,同样机房2也不能选出一个Leader,这种情况下整个集群当机房间的网络断掉后,整个集群将没有Leader。
而如果过半机制的条件是set.size(>=3,那么机房1和机房2都会选出一个Leader,这样就出现了脑裂。所以我们就知道了,为什么过半机制中是大于,而不是大于等于。就是为了防止脑裂。
如果假设我们现在只有5台机器,也部署在两个机房:

此时过半机制的条件是set.size0>2,也就是至少要3台服务器才能选出一个Leader,此时机房件的网络断开了,对于机房1来说是没有影响的,Leader依然还是Leader,对于机房2来说是选不出来
Leader的,此时整个集群中只有一个Leader。
所以,我们可以总结得出,有了过半机制,对于一个Zookeeper集群,要么没有Leader,要没只有1个Leader,这样就避免了脑裂问题。

如何设计一个RPC框架?

首先,RPC表示远程过程调用,在Java中表示远程方法调用,所以,一个RPC框架就是一个能支持调用远程方法的框架
作为一个RPC框架,那最核心的就是网络调用了,也就是如何高效的调用远程方法,比如:
1.通过网络,要发送哪些数据,比如至少得发送类名或接口名、要调用的方法名、调用方法时传入的参数等
2.方法参数通常是对象,那如果要通过网络发送对象,就要考虑序列化和反序列化,那使用何种序列化机制也是要考虑的
3.确定好了要发送的数据后,那通过什么方式发出去呢,是直接通过Socket发出去呢,还是利用HTTP发出去
4.如果利用HTTP来发,那是用HTTP1.1呢,还是用HTTP2呢,请求头放什么数据,请求体放什么数据呢?
5.如何直接通过Socket来发,那就需要自己设计一个数据格式了,类似与HTTP协议,不然服务端接收到字节流之后不知道该如何解析字节流
6.确定好数据格式和网络传输方式之后,就要考虑是否支持异步,是否支持回调等功能了
7.另外像负载均衡、服务容错、服务路由、服务重试等功能也要一步步丰满起来了,那这又是一大堆需要考虑的了
所以,对于如何设计一个RPC框架,大体思路是先设计一个最小可用的远程调用框架,然后不断优化性能,然后再不断扩展其功能,作为成为一个成熟的RPC框架,甚至于一个微服务框架

Dubbo 的整体架构设计及分层

五个角色:
注册中心registry:服务注册与发现服务提供者provider:暴露服务服务消费者consumer:调用远程服务
监控中心monitor:统计服务的调用次数和调用时间
容器container:服务允许容器
调用流程:
1:container容器负责启动、加载、运行provider
2:provider在启动时,向regisitry中心注册自己提供的服务
3:consumer在启动时,向regisitry中心订阅自己所需的服务
4:regisitry返回服务提供者列表给consumer,如果有变更,registry将基于长连接推送变更数据给consumer
5:consumer调用provider服务,基于负载均衡算法进行调用
6:consumer调用provider的统计,基于短链接定时每分钟一次统计到monitor
分层:
接口服务层(Service):面向开发者,业务代码、接口、实现等
配置层(Config):对外配置接口,以ServiceConfig和ReferenceConfig为中心
服务代理层(Proxy):对生产者和消费者、dubbo都会产生一个代理类封装调用细节,业务层对远程调用无感
服务注册层(Registry): 封装服务地址的注册和发现, 以服务 URL 为中心
路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心
监控层(Monitor): RPC调用次数和调用时间监控
远程调用层(Protocal):封装RPC调用
信息交换层(Exchange):封装请求响应模式,同步转异步
网络传输层(Transport):抽象 mina 和netty 为统一接口,统一网络传输接口
数据序列化层(Serialize):数据传输的序列化和反序列化

Dubbo的架构设计是怎样的?

Dubbo中的架构设计是非常优秀的,分为了很多层次,并且每层都是可以扩展的,比如:
1.Proxy服务代理层,支持JDK动态代理、javassist等代理机制
2.Registry注册中心层,支持Zookeeper、Redis等作为注册中心
3.Protocol远程调用层,支持Dubbo、Htpp等调用协议
4.Transport网络传输层,支持netty、mina等网络传输框架
5. Serialize数据序列化层,支持JSON、Hessian等序列化机制
各层说明
.config 配置层:对外配置接口,以ServiceConfig, ReferenceConfig为中心,可以直接初始化配置类,也可以通
过spring 解析配置生成配置类
proxy 服务代理层:服务接口透明代理,生成服务的客户端Stub 和服务器端Skeleton,以ServiceProxy为中心,扩
展接口为 ProxyFactory
.registry 注册中心层:封装服务地址的注册与发现,以服务 URL为中心,扩展接口为 RegistryFactory,Registry.
RegistryService
.cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster,
Directory, Router, LoadBalance
. monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics为中心,扩展接口为MonitorFactory,Monitor
MonitorService
protocol 远程调用层:封装RPC调用,以 Invocation,Result为中心,扩展接口为 Protocol,Invoker,
Exporter
.exchange 信息交换层:封装请求响应模式,同步转异步,以Request,Response为中心,扩展接口为 Exchanger
, ExchangeChannel, ExchangeClient, Exchangeserver
.transport 网络传输层:抽象mina 和netty 为统一接口,以 Message为中心,扩展接口为 Channel,Transporter
, Client, Server, Codec
.serialize 数据序列化层:可复用的一些工具,扩展接口为Serialization,ObjectInput,ObjectOutput,
Threadpool
关系说明
·在RPC中,Protocol是核心层,也就是只要有Protocol+Invoker+ Exporter 就可以完成非透明的RPC调用,然后在
Invoker 的主过程上Filter 拦截点。
图中的Consumer 和Provider 是抽象概念,只是想让看图者更直观的了解哪些类分属于客户端与服务器端,不用Client 和Server 的原因是Dubbo在很多场景下都使用Provider,Consumer,Registry,Monitor 划分逻辑拓普节点,保拮统一概念。
M7/d P3 01:58/02:15

dubbo和springcloud对比

1、dubbo由于是二进制的传输,占用带宽会更少
2、springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用SON报文,消耗会更大
3、dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决
4、springcloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
5、dubbo只是springcloud的一个子集,解决的是分布式中的服务调用问题,而springcloud提供了全套的解决方案

dubbo集群容错策略有哪些

Failover Cluster失败自动切换:dubbo的默认容错方案,当调用失败时自动切换到其他可用的节点,具体的重试
次数和间隔时间可通过引用服务的时候配置,默认重试次数为1也就是只调用一次。
Failback Cluster失败自动恢复:在调用失败,记录日志和调用信息,然后返回空结果给consumer,并且通过定时
任务每隔5秒对失败的调用进行重试
Failfast Cluster快速失败:只会调用一次,失败后立刻抛出异常
Failsafe Cluster失败安全:调用出现异常,记录日志不抛出,返回空结果
Forking Cluster并行调用多个服务提供者:通过线程池创建多个线程,并发调用多个provider,结果保存到阻塞队
列,只要有一个provider成功返回了结果,就会立刻返回结果
Broadcast Cluster广播模式:逐个调用每个provider,如果其中一台报错,在循环调用结束后,抛出异常。

Dubbo是如何完成服务导出的?

1.首先Dubbo会将程序员所使用的@DubboSeryice注解或@Service注解进行解析得到程序员所定义的服务参数,包括定
义的服务名、服务接口、服务超时时间、服务协议等等,得到一个ServiceBean。
2.然后调用ServiceBean的export方法进行服务导出
3.然后将服务信息注册到注册中心,如果有多个协议,多个注册中心,那就将服务按单个协议,单个注册中心进行注册
4.将服务信息注册到注册中心后,还会绑定一些监听器,监听动态配置中心的变更
5.还会根据服务协议启动对应的Web服务器或网络框架,比如Tomcat、Netty等

Dubbo是如何完成服务引入的?

1.当程序员使用@Reference注解来引入一个服务时,Dubbo会将注解和服务的信息解析出来,得到当前所引用的服务
名、服务接口是什么
2.然后从注册中心进行查询服务信息,得到服务的提供者信息,并存在消费端的服务目录中
3.并绑定一些监听器用来监听动态配置中心的变更
4.然后根据查询得到的服务提供者信息生成一个服务接口的代理对象,并放入Spring容器中作为Bean

Dubbo的架构设计是怎样的?

Dubbo中的架构设计是非常优秀的,分为了很多层次,并且每层都是可以扩展的,比如:
1.Proxy服务代理层,支持JDK动态代理、javassist等代理机制
2.Registry注册中心层,支持Zookeeper、Redis等作为注册中心
3.Protocol远程调用层,支持Dubbo、Htpp等调用协议
ansnor网络传输层支结netvmina等网络店输框架

Dubbo是如何完成服务引入的?

1.当程序员使用@Reference注解来引入一个服务时,Dubbo会将注解和服务的信息解析出来,得到当前所引用的服务
名、服务接口是什么
2.然后从注册中心进行查询服务信息,得到服务的提供者信息,并存在消费端的服务目录中
3.并绑定一些监听器用来监听动态配置中心的变更
4.然后根据查询得到的服务提供者信息生成一个服务接口的代理对象,并放入Spring容器中作为Bean

Dubbo是什么?能做什么?

Dubbo是阿里巴巴开源的基于Java的高性能 RPC分布式服务框架,现已成为Apache 基金会孵化项目。致力于提
供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有
dubbo这样的分布式服务框架的需求,本质上是个远程服务调用的分布式框架
其核心部分包含:
1.远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应“模式的信息交换方式,透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2.集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路
由,动态配置等集群支持,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3.自动发现:基于注册中心目录服务,服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口
名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

dubbo支持的协议有哪些

Dubbo协议(官方推荐协议)
•采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用)
大文件上传时,可能出现问题(不使用Dubbo文件上传)
RMI(Remote Method Invocation)协议
•JDK自带的能力。可与原生RMI互操作,基于TCP协议、短连接
Hessian协办议
·可与原生Hessian互操作,基于HTTP协议,对于数据包比较大的情况比较友好
·需Hessian.jar支持,Htp短连接的开销大,它的参数和返回值都需要实现Serializable接口
http协议
Webservice:基于CXF的Frontend-simple和Transports-http实现;基于WebService的远程调用协议。
。序列化:SOAP文本序列化
。适用场景:系统集成,跨语言调用。
Thrif:Thrift是Facebook捐给Apache的一个RPC框架,
·语言中立
·平台中立

Dubbo支持的注册中心有哪些?

Zookeeper(官方推荐)
优点:支持分布式
缺点::受限于Zookeeper的特性
Multicast:组播协议允许将一台主机发送的数据通过网络路由器和交换机复制到多个加入此组播的主机,是一种
一对多的通讯方式。每一台服务提供方和服务消费方都可以看作是注册中心的一部分
·优点:去中心化,不需要单独安装软件.
·缺点:Provider和Consumer和Registry不能跨机房(路由)
不需要启动任何中心节点,只要广播地址一样,就可以互相发现,组播受网络结构限制,只适合小规模应用或
开发阶段使用。

Redis
·优点:支持集群,性能高
。缺点:要求服务器时间同步.否则可能出现集群失败问题
Simple
·优点:标准RPC服务,没有兼容问题
缺点·不支结作群

Dubbo支持哪些负载均衡策略

1.随机:从多个服务提供者随机选择一个来处理本次请求,调用量越大则分布越均匀,并支持按权重设置随机概率
2.轮询:依次选择服务提供者来处理请求,并支持按权重进行轮询,底层采用的是平滑加权轮询算法
3.最小活跃调用数:统计服务提供者当前正在处理的请求,下次请求过来则交给活跃数最小的服务器来处理
4.一致性哈希:相同参数的请求总是发到同一个服务提供者

Dubbo是如何完成服务导出的?

1.首先Dubbo会将程序员所使用的@DubboService注解或@Service注解进行解析得到程序员所定义的服务参数,包括定
义的服务名、服务接口、服务超时时间、服务协议等等,得到一个ServiceBean。
2.然后调用ServiceBean的export方法进行服务导出
3.然后将服务信息注册到注册中心,如果有多个协议,多个注册中心,那就将服务按单个协议,单个注册中心进行注册
4.将服务信息注册到注册中心后,还会绑定一些监听器,监听动态配置中心的变更
5.还会根据服务协议启动对应的Web服务器或网络框架,比如Tomcat、Netty等

Dubbo是如何完成服务引入的?

1.当程序员使用@Reference注解来引入一个服务时,Dubbo会将注解和服务的信息解析出来,得到当前所引用的服务
名、服务接口是什么
2.然后从注册中心进行查询服务信息,得到服务的提供者信息,并存在消费端的服务目录中
3.并绑定一些监听器用来监听动态配置中心的变更
4.然后根据查询得到的服务提供者信息生成一个服务接口的代理对象,并放入Spring容器中作为Bean

dubbo中Zk集群挂掉,发布者和订阅者还能通信么?

可以。
因为当启动dubbo容器时,消费者考z0okeeper拉取注册的生产者地址列表,时,都会按照本地的地址列表,以载玲食的策略去进行调用。但是zookeepef者发现。
·注册中心对等集群,任意一台宕掉后,会自动切换到另一台·注册中心全部宕掉,服务提供者和消费者仍可以通过本地缓存通讯·服务提供者无状态,任一台宕机后,不影响使用
”服务提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务者恢复

选举算法Quorum 机制、WARO

waro:一种简单的副本控制协议,写操作时、只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。优先保证读、任何节点读到的数据都是最新数据,牺牲了更新服务的可用性、只要有一个副本若机了,写服务就不会成功。但只要有一个节点存活、仍能提供读服务
Quorum 机制:10个副本,一次成功更新了三个,那么至少需要读取八个副本的数据,可以保证读到了最新的数据。无法保证强一致性,也就是无法实现任何时刻任何用户或节点都可以读到最近一次成功提交的副本数据。需要配合一个获取最新成功提交的版本号的metadata服务,这样可以确定最新已经成功提交的版本号,然后从已经读到的数据中就可以确认最新写入的数据

session的分布式方案

1、采用无状态服务,抛弃session
2、存入cookie(有安全风险)
3、服务器之间进行Session同步,这样可以保证每个服务器上都有全部的Session信息,不过当服务器数量比较
多的时候,同步是会有延迟甚至同步失败;
4、IP绑定策略
使用Nginx(或其他复杂均衡软硬件)中的IP绑定策略,同一个IP只能在指定的同一个机器访问,但是这样做
失去了负载均衡的意义,当挂掉一台服务器的时候,会影响一批用户的使用,风险很大;
5、使用Redis存储
把Session放到Redis中存储,虽然架构上变得复杂,并且需要多访问一次Redis,但是这种方案带来的好处也
是很天的:
·实现了 Session共享;
可以水平扩展(增加Redis服务器);
服务器重启Session不丢失(不过也要注意Session在Redis中的刷新/生效机制)
不仅可以跨服务器Session共享,甚至可以跨平台(例如网页端和APP端)。

Spring Cloud和Dubbo的区别

底层协议:springcloud基于http协议,dubbo基于Tcp协议,决定了dubbo的性能相对会比较好
注册中心:Spring Cloud 使用的eureka,dubbo推荐使用zookeeper
模型定义:dubbo 将一个接口定义为一个服务,SpringCloud 则是将一个应用定义为一个服务
Springcloud是一个生态,而Dubbo是SpringCloud生态中关于服务调用一种解决方案(服务治理)

zk的watch机制实现原理

pew Zookeeper(String connectstring, int sessionTimeout, Watcher watcher)
这个Watcher将作为整个ZooKeeper会话期间的上下文,一直被保存在客户端ZKWatchManager的defaultwatcher
也可以动态添加watcher:getData(),exists,getChildren。
分布式环境下的观察者模式:通过客服端和服务端分别创建有观察者的信息列表。客户端调用相应接口时,首先将对应的Watch事件放到本地的ZKWatchManager中进行管理。服务端在接收到客户端的请求后根据请求类型判断是否含有Watch事件,并将对应事件放到WatchManager中进行管理。
在事件触发的时候服务端通过节点的路径信息查询相应的Watch事件通知给客户端,客户端在接收到通知后,首先查询本地的ZKWatchManager 获得对应的Watch信息处理回调操作。这种设计不但实现了一个分布式环境下的观察者模式,而且通过将客户端和服务端各自处理Watch事件所需要的额外信息分别保存在两端,减少彼此通信的内容。大大提升了服务的处理性能
客户端实现过程:
标记该会话是一个带有Watch事件的请求
通过 DataWatchRegistration类来保存watcher事件和节点的对应关系
客户端向服务器发送请求,将请求封装成一个Packet对象,并添加到一个等待发送队列outgoingQueue中调用负责处理队列outgoingQueue 的SendThread 线程类中的readResponse方法接收服务端的回调,并在最后执行 finishPacket()方法将 Watch 注册到 ZKWatchManager,sendThread通过发送path 路径和watcher为true,到server 注册watch事件。
ZKWatchManager保存了 MapdataWatchers、MapexistsWatchers、 Map childrenWatchers 三个集合,客户端会在 dataWatchers中会添加一个key为path 路径的本地事件
服务端实现过程:
•解析收到的请求是否带有Watch注册事件,通过 FinalRequestProcessor 类中的processRequest 函数实现
的。当getDataRequest.getWatch()值为True时,表明该请求需要进行 Watch监控注册。
将对应的Watch事件存储到WatchManager,通过 zks.getZKDatabase0).getData 函数实现,
WatchManger 该类中有HashMapwatchTable,key为path,Watcher 是一
个客户端网络连接封装,当节点变化时会通知对应的连接(连接通过心跳保持)
服务端触发过程:
调用WatchManager中的方法触发数据变更事件
封装了一个具有会话状态、事件类型、数据节点3种属性的WatchedEvent对象。之后查询该节点注册的Watch 事件,如果为空说明该节点没有注册过Watch 事件。如果存在Watch 事件则添加到定义的Wathcers集合中,并在WatchManager 管理中删除。最后,通过调用process方法向客户端发送通知
客户端回调过程:
使用SendThread.readResponse()方法来统一处理服务端的相应
将收到的字节流反序列化转换成 WatcherEvent对象。调用eventThread.queueEvent()方法将接收到的事
件交给EventThread线程进行处理
从ZKWatchManager 中查询注册过的客户端Watch信息。查询到后,会将其从ZKWatchManager的管理中
删除。因此客户端的Watcher机制是一次性的,触发后就会被删除
将查询到的Watcher 存储到waitingEvents队列中,调用 EventThread类中的run方法循环取出在
waitingEvents队列中等待的Watcher事件进行处理

zk的初始化选举和崩溃选举过程

zxId:事务id,sld:节点id
先对比zxld,再对比sld,先投自己,选票内容(zxId,sld),遇强改投
投票箱:每个节点在本地维护自己和其他节点的投票信息,改投时需要更新值息,并广播
节点状态:
•LOOKING,竞选状态。
FOLLOWING,随从状态,同步leader状态,参与投票。
OBSERVING,观察状态,同步leader状态,不参与投票。
LEADING,领导者状态。
初始化:没有历史数据,5个节点为例
节点1启动,此时只有一台服务器启动,它发出去的请求没有任何响应,所以它的选举状态一直是LOOKING状

节点2启动,它与节点1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以serverld值较大的服
务器2胜出,但是由于没有达到半数以上,所以服务器1,2还是继续保持LOOKING状态
节点3启动,与1、2节点通信交互数据,服务器3成为服务器1,2,3中的leader,此时有三台服务器选举了3,所
以3成为leader
节点4启动,理论上服务器4应该是服务器1,2,3,4中最大的,但是由于前面已经有半数以上的服务器选举了服
务器3,所以它只能切换为follower
·节点5启动,同4一样
崩溃选举:
·变更状态,leader故障后,follower进入looking状态
各节点投票,先投自己(zxId,sId),再广播投票,
接收到投票,对比zxId和sld,如果本节点小、则将票改为接收的投票信息,并记录投票信息,重新广播。否
则本节点大、则可不做处理
统计本地投票信息,超过半数,则切换为leading状态并广播

zk的会话管理机制

客户端连接zk,有z分配一个全局唯—的sessionld,客户端需要配置超时时间timeQyt并传到zk,zk会据此计算会话下一次超时的时间点,zk根据这个时间点按照分桶策略进行分开存放,zk会给session设置一个isClosing属性、如果检测到超时会将该属性标记为关闭
会话状态:CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE
SessionTracker:zk中的会话管理器,负责会话的创建、管理和清理
sessionsWithTimeout:一个ConcurrentHashMap,用来管理会话的超时时间
sessionsByld:HashMap,维护sessionld到session的映射
sessionsSets:HashMap,会话超时后进行归档,便于恢复和管理
ExpiractionTime = CurrentTime + SessionTimeout
SessionTracker根据ExpiractionTime 将session进行分桶管理,同时按照一定的时间间隔进行定期检查,
客户端读写请求都可以将session的超时时间重置,SessionTracker会将session进行分桶迁移,如果没有读写请
求,客户需要发送ping心跳链接,否则session超时会被清除
会话清理:
标记isClosing为关闭,此时该会话有新的请求也无法处理
发起会话关闭请求,同步到整个集群,使用提交的方式
收集需要清理的临时节点,先获取内存数据库中会话对应的临时节点集合,如果此时有删除节点的请求到达,将请求对应的节点路径从集合中移除,避免重复删除,如果有创建节点请求到达、则将请求中的路径添加到集合中
。添加删除事务变更,将节点删除事务添加到outstandingChanges中,触发watch
删除临时节点
·移除会话
。关闭连接
连接断开后客户端可以重连zk,如果该session未过期,session重新变为CONNECTED
如果时间超过sessinTimeout,服务器则会进行会话的清理工作,如果此时ZK客户端才恢复连接,则会收到State
为Expired的watchedEvent,并断开与服务器的连接。
重连:断开后更换服务器链接,RECONNECTING状态,会将会话迁移到新连接的服务器上
当一个客户端发一个心跳请求个服务端,但是网络延时,导致服务端没有收到,过一会后,客户端连接上了另一个新的服务端,在这之后,之前的心跳被旧的服务端收到了,这时候旧的服务端会被提醒,当前session已经被转移了,然后旧的服务端会关闭这个连接。客户端一般不会感知到这个异常,因为旧连接一般都会被关闭。但是还有一个特殊情况,两个客户端同时使用保存这的session id+密码来重新连接服务端,第一个连接成功,紧着第二个又连接成功,这会导致第一个连接被关闭,然后就是这两个客户端无限重连了

zk的数据模型和节点类型

数据模型:树形结构
zk维护的数据主要有:客户端的会话(session)状态及数据节点(dataNode)信息。
zk在内存中构造了个DataTree的数据结构,维护着path到dataNode的映射以及dataNode间的树状层级关系。为了提高读取性能,集群中每个服务节点都是将数据全量存储在内存中。所以,zk最适于读多写少且轻量级数据的应用场景。
数据仅存储在内存是很不安全的,zk采用事务日志文件及快照文件的方案来落盘数据,保障数据在不丢失的情况下
能快速恢复。
树中的每个节点被称为一Znode
Znode 兼具文件和目录两种特点。可以做路径标识,也可以存储数据,并可以具有子 Znode。具有增、删、改.
查等操作。
Znode具有原子性操作,读操作将获取与节点相关的所有数据,写操作也将 替换掉节点的所有数据。另外,每一个节点都拥有自己的ACL(访问控制列表),这个列表规定了用户的权限,即限定了特定用户对目标节点可以执行的操作
Znode 存储数据大小有限制。每个Znode的数据大小至多1M,常规使用中应该远小于此值。
Znode 通过路径引用,如同Unix中的文件路径。路径必须是绝对的,因此他们必须由斜杠字符来开头。除此以外,他们必须是唯一的,也就是说每一个路径只有一个表示,因此这些路径不能改变。在 ZooKeeper 中,路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息。
持久节点:一旦创建、该数据节点会一直存储在zk服务器上、即使创建该节点的客户端与服务端的会话关闭了、该
节点也不会被删除
临时节点:当创建该节点的客户端会话因超时或发生异常而关闭时、该节点也相应的在zk上被删除。
有序节点:不是一种单独种类的节点、而是在持久节点和临时节点的基础上、增加了一个节点有序的性质。

zk的数据同步原理

根据这三个参数的大小对比结果,选择对应的数据同步方式。
peerLastZxid:Learner服务器(Follower或observer)最后处理的zxid。
minCommittedLog:Leader服务器proposal缓存队列committedLog中的最小的zxid。maxCommittedLog:Leader服务器proposal缓存队列committedLog中的最大的zxid。Zookeeper中数据同步一共有四类,如下。
DIFF:直接差异化同步
peerlastZxid^于minCommittedLog和maxCommittedLog之间
TRUNC+DIFF:先回滚再差异化同步
当Leader服务器发现某个Learner包含了一条自己没有的事务记录,,那么就需要让该Learner进行事务回滚到
Leader服务器上存在的
TRUNC:仅回滚同步
peerlastZxid大于maxCommittedLog,Leader会要求Learner回滚到ZXID值为maxCommitedLog对应的事
务操作
SNAP:全量同步
peerLastZxid 小于minCommittedLog
在初始化阶段,Leader服务器会优先初始化以全量同步方式来同步数据
learner先向leader注册,上报peerLastZxid

zk分布式锁实现原理

•上来直接创建一个锁节点下的一个接一个的临时顺序节点
。如果自己不是第一个节点,就对自己上一个节点加监听器
。只要上一个节点释放锁,自己就排到前面去了,相当于是一个排队机制。
而且用临时顺序节点,如果某个客户端创建临时顺序节点之后,自己宕机了,zk感知到那个客户端宕机,会自动删
除对应的临时顺序节点,相当于自动释放锁,或者是自动取消自己的排队。解决了惊群效应

zk和eureka的区别

zk:CP设计((强一致性),目标是一个分布式的协调系统,用于进行资源的统一管理。
当节点crash后,需要进行leader的选举,在这个期间内,zk服务是不可用的。
eureka:AP设计(高可用),目标是一个服务注册发现系统,专门用于微服务的服务发现注册。
Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时如果发现连接失败,会自动切换至其他节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)
同时当eureka的服务端发现85%以上的服务都没有心跳的话,它就会认为自己的网络出了问题,就不会从服务列表中删除这些失去心跳的服务,同时eureka的客户端也会缓存服务信息。eureka对于服务注册发现来说是非常好的选择。

zk实际如何存储dubbo生产者和消费者信息?

zk中一个客户端修改了某个节点的数据,其他客户端能够马上获取到这个最新数据吗?

Zookeeper集群中节点之间数据是如何同步的

1.首先集群启动时,会先进行领导者选举,确定哪个节点是Leader,哪些节点是Follower和Observer
2.然后Leader会和其他节点进行数据同步,采用发送快照和发送Diff日志的方式
3.集群在工作过程中,所有的写请求都会交给Leader节点来进行处理,从节点只能处理读请求
4. Leader节点收到一个写请求时,会通过两阶段机制来处理
5. Leader节点会将该写请求对应的日志发送给其他Follower节点,并等待Follower节点持久化日志成功
6.Follower节点收到日志后会进行持久化,如果持久化成功则发送一个Ack给Leader节点
7.当Leader节点收到半数以上的Ack后,就会开始提交,先更新Leader节点本地的内存数据
8.然后发送commit命令给Follower节点,Follower节点收到commit命令后就会更新各自本地内存数据
9.同时Leader节点还是将当前写请求直接发送给Observer节点,Observer节点收到Leader发过来的写请求后直接执行更新
本地内存数据
10.最后Leader节点返回客户端写请求响应成功
11.通过同步机制和两阶段提交机制来达到集群中节点数据一致

Dubbo支持哪些负载均衡策略

1.随机:从多个服务提供者随机选择一个来处理本次请求,调用量越大则分布越均匀,并支持按权重设置随机概率
2.轮询:依次选择服务提供者来处理请求,并支持按权重进行轮询,底层采用的是平滑加权轮询算法
3.最小活跃调用数:统计服务提供者当前正在处理的请求,下次请求过来则交给活跃数最小的服务器来处理

Zookeeper中的领导者选举的流程是怎样的?

对于Zookeeper集群,整个集群需要从集群节点中选出一个节点作为Leader,大体流程如下:
1.集群中各个节点首先都是观望状态,一开始都会投票给自己,认为自己比较适合作为leader
2.然后相互交互投票,每个节点会收到其他节点发过来的选票,然后pk,先比较zxid,zxid大者获胜,zxid如果相等则比较
myid,myid大者获胜
3.一个节点收到其他节点发过来的选票,经过PK后,如果PK输了,则改票,此节点就会投给zxid或myid更大的节点,并将
选票放入自己的投票箱中,并将新的选票发送给其他节点
4.如果pk是平局则将接收到的选票放入自己的投票箱中
5.如果pk赢了,则忽略所接收到的选票
6.当然一个节点将一张选票放入到自己的投票箱之后,就会从投票箱中统计票数,看是否超过一半的节点都和自己所投的
节点是一样的,如果超过半数,那么则认为当前自己所投的节点是leader
7.集群中每个节点都会经过同样的流程,pk的规则也是一样的,一旦改票就会告诉给其他服务器,所以最终各个节点中的
投票箱中的选票也将是一样的,所以各个节点最终选出来的leader也是一样的,这样集群的leader就选举出来了

说说你了解的分布式锁实现

分布式锁所要解决的问题的本质是:能够对分布在多台机器中的线程对共享资源的互斥访闸。在这个原理上可以有很多的实现方式:
1.基于Mysql,分布式环境中的线程连接同一个数据库,利用数据库中的行锁来达到互斥访问,但是MysqI的加锁和释放锁的性能会比较低,不适合真正的实际生产环境2.基于Zookeeper,Zookeeper中的数据是存在内存的,所以相对于Mysq/性能上是适合实际环境的,并且基于Zookeeper的顺序节点、临时节点、Watch机制能非常好的来实现的分布式锁
3.基于Redis,Redis中的数据也是在内存,基于Redis的消费订阅功能、数据超时时间,lua脚本等功能,也能很好的实现的分布式锁

Dubbo的负载均衡策略

Dubbo目前支持:
1.平衡加权轮询算法2.加权随机算法3.一致性哈希算法4.最小活跃数算法

还读过哪些框架源码介绍一下你还熟悉的

这个问题比较广泛,你即可以说:HashMap、线程池等JDK自带的源码,也可以说Mybatis、Spring Boot、SpringCloud、消息队列等开发框架或中间件的源码

Dubbo是如何做系统交互的

Dubbo底层是通过RPC来完成服务和服务之间的调用的,Dybbo支持很多协议,比如默认的dubbo协议,比如http协议、比如rest等都是支持的,他们的底层所使用的技术是不
太一样的,比如dubbo协议底层使用的是netty,也可以使用mina,http协议底层使用的tomcat或jetty。
服务消费者在调用某个服务时,会将当前所调用的服务接口信息、当前方法信息、执行方法所传入的入参信息等组装为一个Invocation对象,然后不同的协议通过不同的数据组织方式和传输方式将这个对象传送给服务提供者,提供者接收到这个对象后,找到对应的服务实现,利用反射执行对应的方法,得到方法结果后再通过网络响应给服务消费者。
当然,Dubbo在这个调用过程中还做很多其他的设计,比如服务容错、负载均衡、Filter机制、动态路由机制等等,让Dubbo能处理更多企业中的需求。

定时任务实现原理

优先队列:基于小顶堆实现,每次新增任务需要进行堆化,取任务时取堆顶元素、调整堆架构,时间复杂度是
o(logN)
时间轮算法:是一个环形队列,按照时间的单位区分,每个时间单位里面是一个链表、用来存储定时任务,像时钟一样轮询环形队列,取出链表中的任务执行,如果超出了环形队列的时间粒度、可以使用多级时间轮,即使用不同维度的时间单位,就跟时钟或者水表一样,这一层的走了一圈,下一层的才走了一格,时间复杂度为0(1)

对比两阶段,三阶段有哪些改进

第一阶段(prepare):每个参与者执行本地事务但不提交,进入ready 状态,并通知协调者已经准备就绪。
第二阶段(commit)当协调者确认每个参与者都ready后,通知参与者进行commit 操作;如果有参与者 fail,则发送 rollback命令,各参与者做回滚。
问题:
单点故障:一旦事务管理器出现故障,整个系统不可用(参与者都会阻塞住)
·数据不一致:在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与
者接收到 commit消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
响应时间较长:参与者和协调者资源都被锁住,提交或者回滚之后才能释放
不确定性:当协事务管理器发送commit之后,并且此时只有一个参与者收到了commit,那么当该参与者与
事务管理器同时岩机之后,重新选举的事务管理器无法确定该条消息是否提交成功。
三阶段协议:主要是针对两阶段的优化,解决了2PC单点故障的问题,但是性能问题和不一致问题仍然没有根本解决

TCC(补偿事务):Try、Confirm、Cancel

针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作
Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作既回滚操作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel操作若执行失败,TM会进行重试。
TCC模型对业务的侵入性较强,改造的难度较大
每个操作都需要有try、conf}rm、
cande1三个接口实现
confirm 和cancel接口还必须实现幂等性。
消息队列的事务消息:
·发送prepare消息到消息中间件
发送成功后,执行本地事务
。如果事务执行成功,则commit,消息中间件将消息下发至消费端(commit前,消息不会被消费)
。如果事务执行失败,则回滚,消息中间件将这条prepare消息删除
消费端接收到消息进行消费,如果消费失败,则不断重试

集群、分布式、SOA、微服务的概念及区别

集群:不同服务器部署同一套应用服务对外提供访问,实现服务的负载均衡或者互备(热备,主从等),指同一种组
件的多个实例,形成的逻辑上的整体。单个节点可以提供完整服务。集群是物理形态
分布式:服务的不同模块部署在不同的服务器上,单个节点不能提供完整服务,需要多节点协调提供服务(也可以
是相同组件部署在不同节点、但节点间通过交换信息协作提供服务),分布式强调的是工作方式
SOA:面向服务的架构,一种设计方法,其中包含多个服务,服务之间通过相互依赖最终提供一系列的功能。一
个服务通常以独立的形式存在于操作系统进程中。各个服务之间通过网络调用。
.中心化实现:ESB(企业服务总线),各服务通过ESB进行交互,解决异构系统之间的连通性,通过协议转换、消息解析、消息路由把服务提供者的数据传送到服务消费者。很重,有一定的逻辑,可以解决一些公用逻辑的问题。
·去中心化实现:微服务
微服务:在SOA上做的升华,微服务架构强调的一个重点是业务需要彻底的组件化和服务化,原有的单个业务系
统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成
服务单一职责
轻量级通信:去掉ESB总线,采用restapi通信

简述Base理论

cap理论的一种妥协,由于cap只能二取其一,base理论降低了发生分区容错时对可用性和一致性的要求
1、基本可用:允许可用性降低(可能响应延长、可能服务降级),
2、软状态:指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性。
2、最终一致性:节点数据同步可以存在时延),但在一定的期限后必须达成数据的一致,状态变为最终状态

简述CAP理论

数据一致性fconsistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能到这个数据,对调用者而言数据具有强一致性(strong consistency)。服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待
·分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务
如果选择了CA而放弃了P,那么当发生分区现象时,为了保证C,系统需要禁止写入,当有写入请求时,系统返回error(例如,当前系统不允许写入),这又和A冲突了,因为A要求返回no error和notimeout。因此,分布式系统理论上不可能选择CA架构,只能选择CP或者 AP架构。
反证:
如果CAP三者可同时满足,由于允许P的存在,则一定存在节点之间的丢包,如此则不能保证C
因为允许分区容错,写操作可能在节点1上成功,在节点2上失败,这时候对于Client 1(读取节点1)和Client 2(读取节点2),就会读取到不一致的值,出现不一致的情况。如果要保持一致性,写操作必须同时失败,也就是降低系统的可用性。

dubbo的SPI机制

spi: service provider interface 服务发现机制
通过接口全限定名找到指定目录下对应的文件,获取具体的实现类然后加载即可,做到了灵活的替换具体的实现
类。

简述dubbo的分层设计

Service,业务层,就是咱们开发的业务逻辑层。
Config,配置层,主要围绕 ServiceConfig和ReferenceConfig,初始化配置信息。
Proxv,代理层,服务提供者还是消费者都会生成一个代理类,使得服务接口透明化,代理层做远程调用和返回

dubbo服务暴露过程

Dubbo采用URL的方式来作为约定的参数类型。
protoco1://username:password@host:port/path?key=value&key=value
protoco1:指的是dubbo 中的各种协议,如:dubbo thrift http
username/password:用户名/密码
host/port:主机/端口
path:接口的名称
parameters:参数键值对
ServiceBean实现了ApplicationListener,监听ContextRefreshedEvent时间,在Spring IOC容器刷新完成后调用onApplicationEvent方法,服务暴露的启动点。根据配置得到URL,再利用Dubbo SPI机制根据 URL的参数选择对应的实现类,实现扩展。
通过javassist 动态封装服务实现类,统一暴露出 Invoker 使得调用方便、屏蔽底层实现细节,然后封装成exporter存储起来,等待消费者的调用,并且会将URL注册到注册中心,使得消费者可以获取服务提供者的信息。
一个服务如果有多个协议那么就都需要暴露,比如同时支持 dubbo 协议和hessian协议,那么需要将这个服务用
两种协议分别向多个注册中心(如果有多个的话)暴露注册。
1、检测配置,如果有些配置空的话会默认创建,并且组装成URL。
2、根据URL进行服务暴露、创建代理类intoker、根据URL得知具体的协议,根据Dubbo SPl选取实现类实现
exporter.
3、如果只是本地暴露,将exporter存入ServiceConfig的缓存
4、远程暴露,先通过registry 协议找到RegistryProtocol进行export,将URL中export=dubbo://…先转换成
exporter,然后获取注册中心的相关配置,如果需要注册则向注册中心注册,并且在
ProviderConsumerRegTable 这个表格中记录服务提供者,其实就是往一个ConcurrentHashMap中将塞入invoker,key 就是服务接口全限定名,value是一个set,set 里面会存包装过的invoker,根据URL上Dubbo协议暴露出exporter,打开Server调用NettyServer 来监听服务

dubbo服务调用过程

调用某个接口的方法会调用之前生成的代理类,然后会从cluster 中经过路由的过滤、负载均衡机制选择一个
invoker 发起远程调用,此时会记录此请求和请求的ID等待服务端的响应。
服务端接受请求之后会通过参数找到之前暴露存储的map,得到相应的exporter,然后最终调用真正的实现类,
再组装好结果返回,这个响应会带上之前请求的ID。
消费者收到这个响应之后会通过ID去找之前记录的请求,然后找到请求之后将响应塞到对应的Future中,唤醒
等待的线程,最后消费者得到响应。

dubbo服务引入过程

饿汉式是通过调用ReferenceBean的afterPropertiesSet方法时引入服务。
懒汉式是只有当这个服务被注入到其他类中时启动引入流程,也就是说用到了才会开始服务引入。默认使用懒汉
式,如果需要使用饿汉式,可通过配置dubbo:reference的 init 属性开启。
ReferenceBean实现了FactoryBean接口,当对任意服务Interface进行自动注入或者getBean获取时,就会触
发getObjectO函数的服务引用过程。
·本地引入走 injvm 协议,到服务暴露的缓存中取exporter。
·直连远程引入服务,测试的情况下用,不需要启动注册中心,由Consumer 直接配置写死Provider的地址,
然后直连即可。
注册中心引入远程服务,Consumer 通过注册中心得知Provider的相关信息,然后进行服务的引入
获取注册中心实例,向注册中心注册自身,并订阅providers、configurators、routers节点,触发
Dubbolnvoker的生成,cluster将多个服务调用者进行封装,返回一个invoker,
通过配置构建一个map,然后利用map来构建URL,再通过URL上的协议利用自适应扩展机制调用对应的protocol.refer 得到相应的invoker。然后再构建代理,封装invoker 返回服务引用,之后Comsumer 调用这个代理类
bilibili BV1jG411M77d P51 00:44/08:49

简述paxos算法

Paxos算法解决的是一个分布式系统如何就某个值(决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各个节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能够得到一个一致的状态。为了保证每个节点执行相同的操作序列,需要在每一条指令上执行一个“一致性算法“以保证每个节点看到的指令一致。在Paxos算法中,有三种角色:Proposer(提议者),Acceptor(接受者),Learners(记录员)
Proposer提议者:只要Proposer发的提案Propose被半数以上的Acceptor接受,Proposer就认为该提案例的
value被选定了。
Acceptor接受者:只要Acceptor接受了某个提案,Acceptor就认为该提案例的value被选定了
Learner记录员:Acceptor告诉Learner哪个value被选定,Learner就认为哪个value被选定。
Paxos算法分为两个阶段,具体如下:
阶段一(preprae):
(a) Proposer 收到client请求或者发现本地有未提交的值,选择一个提案编号N,然后向半数以上的Acceptor发送
编号为N的Prepare请求。
(b)Acceptor 收到一个编号为N的Prepare请求,如果该轮paxos
·本节点已经有已提交的value记录,对比记录的编号和N,大于N则拒绝回应,否则返回该记录value及编号没有已提交记录,判断本地是否有编号N1,N1>N、则拒绝响应,否则将N1改为N(如果没有N1,则记录N),并响应prepare
阶段二(accept):
(a)如果Proposer 收到半数以上Acceptor 对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept 请求给半数以上的Acceptor。V就是收到的响应中编号最大的value,如果响应中不包含任何value,那么V就由Proposer自己决定。
(b)如果 Acceptor 收到一个针对编号为N的提案的Accept请求,Acceptor对比本地的记录编号,如果小于等于
N,则接受该值,并提交记录value。否则拒绝请求
Proposer 如果收到的大多数Acceptor响应,则选定该value值,并同步给leaner,使末响应的Acceptor达成一致
活锁:accept时被拒绝,加大N,重新accept,此时另外一个proposer也进行相同操作,导致accept一致失败,
无法完成算法
multi-paxos:区别于paxos只是确定一个值,multi-paxos可以确定多个值,收到accept请求后,则一定时间内不再accept其他节点的请求,以此保证后续的编号不需要在经过preprae确认,直接进行accept操作。此时该节点成为了leader,直到accept被拒绝,重新发起prepare请求竞争leader。

简述raft算法

概念:
分布式一致性算法:raft会先选举出leader,leader完全负责replicated log的管理。leader负责接受所有客户端更新请求,然后复制到follower节点,并在“安全”的时候执行这些请求。如果leader故障,followes会重新选举出新的leader
,三种状态:一个节点任一时刻处于三者之一
oleader:处理所有的客户端请求(如果客户端将请求发给了Follower,Follower将请求重定向给Leader)
ofollower:不会发送任何请求,只会简单地响应来自Leader或Candidate的请求
ocandidate:用于选举产生新的leader(候选人)
term:任期,leader产生到重新选举为一任期,每个节点都维持着当前的任期号oterm是递增的,存储在log日志的entry中,代表当前entry是在哪一个term时期写入。每个任期只能有一个leader或者没有(选举失败)。
每次rpc通信时传递该任期号,如果RPC收到任期号大于本地的、切换为follower,小于本地任期号则返回错误信息。
两个RPC通信:
oRequestVote RPC:负责选举,包含参数lastIndex,lastTerm
oAppendEntries RPC:负责数据的交互。
日志序列:每一个节点上维持着一份持久化Log,通过一致性协议算法,保证每一个节点中的Log保持一致,并且顺序存放,这样客户端就可以在每一个节点中读取到相同的数据
状态机:日志序列同步到多数节点时,leader将该日志提交到状态机,并在下一次心跳通知所有节点提交状态
机(携带最后提交的lastindex)
何时触发选举:
集群初始化时,都是follower,随机超时,变成candidate,发起选举

匹配上则追加到自己的日志序列
匹配不上则拒绝请求,leader将日志index调小,重新同步直至匹配上,follower将leader的日志序列覆盖到
本地
一旦新的日志序列条目变成majority的了,将日志序列应用到状态机中
Leader在状态机里提交自己日志序列条目,然后返回结果给客户怡
Leader下次发送AppendEntries RPC时,告知follower已经提交的日志序列条目信息(lastindex)
•follower收到RPC后,提交到自己的状态机里
提交状态机时,如果term为上一任期,必须与当前任期数据一起提交,否则可能出现覆盖已提交状态机的日志
新选举出的leader—定拥有所有已提交状态机的日志条目
•leader在当日志序列条目已经复制到大多数follower机器上时,才会提交日志条目。
·而选出的leader的logIndex必须大于等于大多数节点,因此leader肯定有最新的日志
安全原则:
·选举安全原则:对于一个给定的任期号,最多只会有一个领导人被选举出来
状态机安全原则:如果一个leader已经在给定的索引值位置的日志条目应用到状态机中,那么其他任何的服务器在这个索引位置不会提交一个不同的日志
领导人完全原则:如果某个日志条目在某个任期号中已经被提交,那么这个条目必然出现在更大任期号的所有
领导人中
领导人只附加原则:领导人绝对不会删除或者覆盖自己的日志,只会增加
日志匹配原则:如果两个日志在相同的索引位置的日志条目的任期号相同,那么我们就认为这个日志从头到这
个索引位置之间全部完全相同

简述TCC事务模型

TCC(补偿事务)
Try. Confirm, Cancel
针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作
Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作既回滚操作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel操作若执行失败,TM会进行重试。
TCC模型对业务的侵入性较强,改造的难度较大,每个操作都需要有try、confirm、cance1三个接口实现
TCC中会添加事务日志,如果Confirm或者Cancel阶段出错,则会进行重试,所以这两个阶段需要支持幂等;如
果重试失败,则需要人工介入进行恢复和处理等。

什么是ZAB协议

ZAB协议是Zookeeper用来实现一致性的原子广播协议,该协议描述了Zookeeper是如何实现一致性的,分为三个阶段:
1.领导者选举阶段:从Zookeeper集群中选出一个节点作为Leader,所有的写请求都会由Leader节点来处理
2.数据同步阶段:集群中所有节点中的数据要和Leader节点保持一致,如果不一致则要进行同步
3.请求广播阶段:当Leader节点接收到写请求时,会利用两阶段提交来广播该写请求,使得写请求像事务一样在其他节点上执行,达到节点上的数
据实时一致
但值得注意的是,Zookeeper只是尽量的在达到强一致性,实际上仍然只是最终一致性的。

简述zab协议

ZAB 协议是为分布式协调服务Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议,实现分布式数据一致性所有客户端的请求都是写入到 Leader进程中,然后,由Leader 同步到其他节点,称为Follower。在集群数据同步的过程中,如果出现Follower 节点崩溃或者Leader 进程崩溃时,都会通过Zab协议来保证数据一致性
ZAB协议包括两种基本的模式:崩溃恢复和消息广播
消息广播:
集群中所有的事务请求都由 Leader节点来处理,其他服务器为Follower,Leader将客户端的事务请求转换为事
务Proposal,并且将Proposal分发给集群中其他所有的Follower。
完成广播之后,Leader等待Follwer反馈,当有过半数的Follower反馈信息后,Leader将再次向集群内
Follower 广播Commit 信息,Commit 信息就是确认将之前的Proposal提交。
Leader 节点的写入是一个两步操作,第一步是广播事务操作,第二步是广播提交操作,其中过半数指的是反馈的
节点数>=N/2+1,N是全部的Follower节点数量。
崩溃恢复:
·初始化集群,刚刚启动的时候
•Leader 崩溃,因为故障宕机
Leader失去了半数的机器支持,与集群中超过一半的节点断连
此时开启新一轮 Leader 选举,选举产生的Leader会与过半的Follower进行同步,使数据一致,当与过半的机器
同步完成后,就退出恢复模式,然后进入消息广播模式
整个ZooKeeper 集群的一致性保证就是在上面两个状态之前切换,当Leader服务正常时,就是正常的消息广播模式;当Leader不可用时,则进入崩溃恢复模式,崩溃恢复阶段会进行数据同步,完成以后,重新进入消息广播阶段。
zxid 是Zab协议的一个事务编号,Zxid是一个64位的数字,其中低32位是一个简单的单调递增计数器,针对
客户端每一个事务请求,计数器加 1;而高 32位则代表 Leader 周期年代的编号。
Leader周期(epoch),可以理解为当前集群所处的年代或者周期,每当有一个新的Leader选举出现时,就会从这个Leader 服务器上取出其本地日志中最大事务的Zxid,并从中读取epoch值,然后加1,以此作为新的周期ID。高32位代表了每代Leader的唯一性,低32位则代表了每代Leader中事务的唯一性。

zab节点的三种状态:

following:服从leader的命令
leading:负责协调事务
election/looking:选举状态

Zookeeper的典型应用场景

通过对Zookeeper 中丰富的数据节点进行交叉使用,配合Watcher 事件通知机制,可以非常方便的构建一系列分
布式应用中会涉及的核心功能,如:
(1)数据发布/订阅:配置中心
(2)负载均衡:提供服务者列表
(3)命名服务:提供服务名到服务地址的映射
(4)分布式协调/通知:watch机制和临时节点,获取各节点的任务进度,通过修改节点发出通知
(5)集群管理:是否有机器退出和加入、选举master
(7)分布式锁
(8)分布式队列
第一类,在约定目录下创建临时目录节点,监听节点数目是否是要求的数目。
第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。在特定的目录下创建PERSISTENT_SEQUENTIAL节点,创建成功时Watcher通知等待的队列,队列删除序列号最小的节点用以消费。此场景下Zookeeper的znode 用于消息存储,znode存储的数据就是消息队列中的消息内容,SEQUENTIAL序列号就是消息的编号,按序取出即可。由于创建的节点是持久化的,所以不必担心队列消息的丢失问题。

简述zk的命名服务、配置管理、集群管理

命名服务:
通过指定的名字来获取资源或者服务地址。Zookeeper可以创建一个全局唯一的路径,这个路径就可以作为一个名字。被命名的实体可以是集群中的机器,服务的地址,或者是远程的对象等。一些分布式服务框架(RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据特定的名字来获取资源的实体、服务地址和提供者信息等
配置管理:
实际项目开发中,经常使用.properties或者xml需要配置很多信息,如数据库连接信息、fps地址端口等等。程序分布式部署时,如果把程序的这些配置信息保存在zk的znode节点下,当你要修改配置,即znode会发生变化时,可以通过改变zk中某个目录节点的内容,利用watcher通知给各个客户端,从而更改配置。
集群管理:
集群管理包括集群监控和集群控制,就是监控集群机器状态,剔除机器和加入机器。zookeeper可以方便集群机器的管理,它可以实时监控znode节点的变化,一旦发现有机器挂了,该机器就会与zk断开连接,对应的临时目录节点会被删除,其他所有机器都收到通知。新机器加入也是类似。

zk的数据模型

ZK的数据模型是一种树形结构,具有一个固定的根节点(/),可以在根节点下创建子节点,并在子节点下继续创建下一级节点。每一层级用 /隔开,且只能用绝对路径(get /work/task1)的方式查询ZK节点,而不能用相对路径
。持久节点:
将节点创建为持久节点,该数据节点会一直存储在ZK服务器上,即使创建该节点的客户端与服务端的会话关
闭了,该节点依然不会被删除,除非显式调用delete函数进行删除操作。
临时节点:
如果将节点创建为临时节点,那么该节点数据不会一直存储在ZK服务器上。当创建该临时节点的客户端会话
因超时或发生异常而关闭时,该节点也相应在ZK服务器上被删除。也可以主动调用delete删除。
有序节点:
有序节点并不算一种单独种类的节点,而是在持久节点和临时节点的基础上,增加一个节点有序的性质。创建有序节点的时候,ZK服务器会自动使用一个单调递增的数字作为后缀,追加到创建的节点后边。例如一个客户端创建了一个路径为works/task-的有序节点,那么Zookeeper 将会生成一个序号并追加到该节点的路径后,最后该节点的路径为works/task-1。
节点内容:一个二进制数组(byte data0),用来存储节点的数据、ACL访问控制、子节点数据(因为临时节点不
允许有子节点,所以其子节点字段为null),记录自身状态信息的stat。
stat+节点路径可以查看状态信息
czxid:创建节点的事务id
mzxid:最后一次被更新的事务id
pzxid:子节点最后一次被修改的事务id
ctime:创建时间
mtime:最后更新时间
version:版本号、表示的是对节点数据内容,子节点信息或ACL信息的修改次数
可以避免并发更新问题,使用之前获取的版本进行CAS操作更新cversion:子节点版本号
aversion:acl的版本号
ephemeralOwner:创建节点的sessionld,如果是持久节点、值为0
dataLenght:数据内容长度
numChildren:子节点个数

简述zk中的观察者机制

peerType=observer
server.1:1ocalhost:2181:3181:observer
观察者的设计是希望能动态扩展zookeeper集群又不会降低写性能。
如果扩展节点是follower,则写入操作提交时需要同步的节点数会变多,导致写入性能下降,而follower又是参与
投票的、也会导致投票成本增加
observer是一种新的节点类型,解决扩展问题的同时,不参与投票、只获取投票结果,同时也可以处理读写请求,写请求转发给leader。负责接收leader同步过来的提交数据,observer的节点故障也不会影响集群的可用性,
跨数据中心部署。把节点分散到多个数据中心可能因为网络的延迟会极大拖慢系统。使用observer的话,更新操
作都在一个单独的数据中心来处理,并发送到其他数据中心,让其他数据中心的节点消费数据。
无法完全消除数据中心之间的网络延迟,因为observer需要把更新请求转发到另一个数据中心的leader,并处理
同步消息,网络速度极慢的话也会有影响,它的优势是为本地读请求提供快速响应。

简述你对RPC、RMI的理解

RPC:在本地调用远程的函数,远程过程调用,可以跨语言实现httpClient
RMI:远程方法调用,java中用于实现RPC的一种机制,RPC的java版本,是2EE的网络调用机制,跨JVM调用对象
的方法,面向对象的思维方式
直接或间接实现接口java.rmi.Remote 成为存在于服务器端的远程对象,供客户端访问并提供一定的服务远程对象必须实现java.rmi.server.UniCastRemoteobject类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
public interface IService extends Remote {
string service(string content) throws RemoteException;
public class ServiceImpl extends UnicastRemoteobject implements IService
private String name;
public ServiceImpl(String name) throws RemoteException
this.name = name;
@override
public String service(string content)

讲下Zookeeper watch机制

客户端,可以通过在znode上设置watch,实现实时监听znode的变化
Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置
了Watch的客户端
·父节点的创建,修改,删除都会触发Watcher事件。
。子节点的创建,删除会触发Watcher事件。
一次性:一旦被触发就会移除,再次使用需要重新注册,因为每次变动都需要通知所有客户端,一次性可以减轻压
力,3.6.0默认持久递归,可以触发多次
轻量:只通知发生了事件,不会告知事件内容,减轻服务器和带宽压力
×
Watcher 机制包括三个角色:客户端线程、客户端的WatchManager以及ZooKeeper服务器
1.客户端向ZooKeeper 服务器注册一个Watcher 监听,
2.把这个监听信息存储到客户端的WatchManager中
3.当ZooKeeper 中的节点发生变化时,会通知客户端,客户端会调用相应Watcher 对象中的回调方法。watch
回调是串行同步的

简述CAP理论

CAP理论是分布式领域非常重要的一个理论,很多分布式中间件在实现时都需要遵守这个理论,其中:
1.C表示一致性:指的的是分布式系统中的数据的一致性
2.A表示可用性:表示分布式系统是否正常可用
3.P表示分区容器性:表示分布式系统出现网络问题时的容错性
CAP理论是指,在分布式系统中不能同时保证C和A,也就是说在分布式系统中要么保证CP,要么保证AP,也就是一致性和可用性只能取其一,如果想要数据的一致性,那么就
需要损失系统的可用性,如果需要系统高可用,那么就要损失系统的数据一致性,特指强一致性。
CAP理论太过严格,在实际生产环境中更多的是使用BASE理论,BASE理论是指分布式系统不需要保证数据的强一致,只要做到最终一致,也不需要保证一直可用,保证基本可
用即可
图的深度遍历和广度遍历
1.图的深度优先遍历是指,从一个节点出发,一直沿着边向下深入去找节点,如果找不到了则返回上一层找其他节点
2.图的广度优先遍历只是,从一个阶段出发,向下先把第一层的节点遍历完,再去遍历第二层的阶段,知道遍历到最后一层
快排算法
快速排序算法底层采用了分治法。
基本思想是:
1.先取出数列中的第一个数作为基准数
2.将数列中比基准数大的数全部放在它的右边,比基准数小的数全部放在它的左边

请谈谈ZooKeeper对事务性的支持

ZooKeeper对于事务性的支持主要依赖于四个函数,zoo_create_op_init,zoo_delete_op_init,
zoo_set_op_init以及zoo_check_op_init。
每一个函数都会在客户端初始化一个operation,客户端程序有义务保留这些operations。当准备好一个事务中的所有操作后,可以使用zoo_multi来提交所有的操作,由zookeeper服务来保证这一系列操作的原子性。也就是说只要其中有一个操作失败了,相当于此次提交的任何一个操作都没有对服务端的数据造成影响。Zoo_multi的返回值是第一个失败操作的状态信号。

如何理解RPC

远程过程调用
RPC要求在调用方中放置被调用的方法的接口。调用方只要调用了这些接口,就相当于调用了被调用方的实际方法,十分易用。于是,调用方可以像调用内部接口一样调用远程的方法,而不用封装参数名和参数值等操作。包含
1.动态代理,封装调用细节
2.序列化与反序列化,数据传输与接收
3.通信,可以选择七层的http,四层的tcp/udp
4.异常处理等
首先,调用方调用的是接口,必须得为接口构造一个假的实现。显然,要使用动态代理。这样,调用方的调用就被
动态代理接收到了。
第二,动态代理接收到调用后,应该想办法调用远程的实际实现。这包括下面几步:
·识别具体要调用的远程方法的IP、端口
。将调用方法的入参进行序列化
·通过通信将请求发送到远程的方法中
这样,远程的服务就接收到了调用方的请求。它应该:
·反序列化各个调用参数
。定位到实际要调用的方法,然后输入参数,执行方法
按照调用的路径返回调用的结果

如何设计一个分布式锁?如何对锁性能进行优化?

分布式锁的本质:就是在所有进程都能访问到的一个地方,设置一个锁资源,让这些进程都来竞争锁资源。数据库,
z0okeeper Redis。。通常对于分布式锁,会要求响应快、性能高、与业务无关。
Redis实现分布式锁:SETNX key value:当key不存在时,就将key设置为value,并返回1。如果key存在,就返回0。EXPIRE key locktime:设置key的有效时长。DEL key: 删除。 GETSEI key value:先GET,再SET,先返回key对应的值,如果没有就返回空。然后再将key设置成value。
1、最简单的分布式锁:SETNX加锁,DEL解锁。
2、给锁设置过期时长:
就挂了,这时锁还是会被锁死。
问题:SETNX和EXPIRE并不是原子性的,所以获取到锁的进程有可能还没有执行EXPIRE指令,
3、将锁的内容设置为过期时间(客户端时间+过期时长),SETNX获取锁失败时,拿这个时间跟当前时间比对,如果是过期的
锁,就先删除锁,再重新上锁。
4、setNX失败后,获取锁上的时间戳,然后用getset,将自己的过期时间更新上去,并获取旧值。如果这个旧值,跟之前获
得的时间戳是不一致的,就表示这个锁赢

如何实现接口的幂等性

。唯—id。每次操作,都根据操作和内容生成唯一的id,在执行之前先判断id是否存在,如果不存在则执行后续
操作,并且保存到数据库或者redis等。
服务端提供发送token的接口,业务调用接口前先获取token,然后调用业务接口请求时,把token携带过去,务器判断token是否存在redis中,存在表示第一次请求,可以继续执行业务,执行业务完成后,最后需要把redis中的token删除
建去重表。将业务中有唯一标识的字段保存到去重表,如果表中存在,则表示已经处理过了
。版本控制。增加版本号,当版本号符合时,才能更新数据
·状态控制。例如订单有状态已支付 未支付 支付中支付失败,当处于未支付的时候才允许修改为支付中等

什么是BASE理论

由于不能同时满足CAP,所以出现了BASE理论:
1.BA:Basically Available,表示基本可用,表示可以允许一定程度的不可用,比如由于系统故障,请求时间变长,或者由于系统故障导致部分非核
心功能不可用,都是允许的
2.S:Soft state:表示分布式系统可以处于一种中间状态,比如数据正在同步
3.E:Eventually consistent,表示最终一致性,不要求分布式系统数据实时达到一致,允许在经过一段时间后再达到一致,在达到一致过程中,系
统也是可用的

什么是RPC

RPC,表示远程过程调用,对于Java这种面试对象语言,也可以理解为远程方法调用,RPC调用和HTTP调用是有区别的,RPC表示的是一种调用远程方法的方式,可以使用HTTP协议、或直接基于TCP协议来实现RPC,在Java中,我们可以通过直接使用某个服务接口的代理对象来执行方法,而底层则通过构造HTTP请求来调用远端的方法,所以,有一种说法是RPC协议是HTTP协议之上的一种协议,也是可以理解的。
分布式ID是什么?有哪些解决方案?
在开发中,我们通常会需要一个唯一ID来标识数据,如果是单体架构,我们可以通过数据库的主键,或直接在内存中维护一个自增数字来作为ID都是
可以的,但对于一个分布式系统,就会有可能会出现I冲突,此时有一下解决方案:
1.uuid,这种方案复杂度最低,但是会影响存储空间和性能
2.利用单机数据库的自增主键,作为分布式ID的生成器,复杂度适中,ID长度较之uuid更短,但是受到单机数据库性能的限制,并发量大的时候,
此方案也不是最优方案

什么是RPC

RPC,表示远程过程调用,对于Java这种面试对象语言,也可以理解为远程方法调用,RP@调用和HTTP调用是有区别的,RPC表示的是一种调用远程方法的方式,可以使用HTTP协议、或直接基于TCP协议来实现RPC,在Java中,我们可以通过直接使用某个服务接口的代理对象来执行方法,而底层则通过构造HTTP请求来调用远端的方法,所以,有一种说法是RPC协议是HTTP协议之上的一种协议,也是可以理解的。
分布式ID是什么?有哪些解决方案?
在开发中,我们通常会需要一个唯一ID来标识数据,如果是单体架构,我们可以通过数据库的主键,或直接在内存中维护一个自增数字来作为ID都是
可以的,但对于一个分布式系统,就会有可能会出现ID冲突,此时有一下解决方案:
1.uuid,这种方案复杂度最低,但是会影响存储空间和性能
2.利用单机数据库的自增主键,作为分布式ID的生成器,复杂度适中,ID长度较之uuid更短,但是受到单机数据库性能的限制,并发量大的时候,
此方案也不是最优方案
3.利用redis

为什么Zookeeper可以用来作为注册中心

可以利用Zookeeper的临时节点和watch机制来实现注册中心的自动注册和发现,另外Zookeeper中的数据都是存在内存中的,并且Zookeeper底层采用了nio,多线程模型,所以Zookeeper的性能也是比较高的,所以可以用来作为注册中心,但是如果考虑到注册中心应该是注册可用性的话,那么Zookeeper则不太合适,因为Zookeeper是CP的,它注重的是一致性,所以集群数据不一致时,集群将不可用,所以用Redis、Eureka、Nacos来作为注册中心将更合适。
Zookeeper中的领导者选举的流程是怎样的?
对于Zookeeper集群,整个集群需要从集群节点中选出一个节点作为Leader,大体流程如下:
1.集群中各个节点首先都是观望状态,一开始都会投票给自己,认为自己比较适合作为leader

什么是分布式事务?有哪些实现方案?

在分布式系统中,一次业务处理可能需要多个应用来实现,比如用户发送一次下单请求,就涉及到订单系统创建订单、库存系统减库存,而对于一次下单,订单创建与减库存应该是要同时成功或同时失败的,但在分布式系统中,如果不做处理,就很有可能出现订单创建成功,但是减库存失败,那么解决这类问题,就需要用到分布式事务。常用解决方案有:
1.本地消息表:创建订单时,将减库存消息加入在本地事务中,一起提交到数据库存入本地消息表,然后调用库存系统,如果调用成功则修改本地
消息状态为成功,如果调用库存系统失败,则由后台定时任务从本地消息表中取出未成功的消息,重试调用库存系统
2.消息队列:目前RocketMQ中支持事务消息,它的工作原理是:
a.生产者订单系统先发送一条half消息到Broker,half消息对消费者而言是不可见的
b.再创建订单,根据创建订单成功与否,向Broker发送commit或rollback
c.并且生产者订单系统还可以提供Broker回调接口,当Broker发现一段时间half消息没有收到任何操作命令,则会主动调此接口来查询订单是
否创建成功
d.一旦half消息commit了,消费者库存系统就会来消费,如果消费成功,则消息销毁,分布式事务成功结束
e.如果消费失败,则根据重试策略进行重试,最后还失败则进入死信队列,等待进一步处理
3.Seata:阿里开源的分布式事务框架,支持AT、TCC等多种模式,底层都是基于两阶段提交理论来实现的

数据库实现分布式锁的问题及解决方案

利用唯一约束键存储key,insert成功则代表获取锁成功,失败则获取失败,操作完成需要删除锁
问题:
·非阻塞,锁获取失败后没有排队机制,需要自己编码实现阻塞,可以使用自旋,直到获取锁·不可重入,如果加锁的方法需要递归,则第二次插入会失败,可以使用记录线程标识解决重入问题·死锁,删除锁失败、则其他线程没办法获取锁,可以设置超时时间、使用定时任务检查
数据库单点故障,数据库高可用

数据一致性模型有哪些

强一致性:当更新操作完成之后,任何多个后续进程的访问都会返回最新的更新过的值,这种是对用户最友好的,
就是用户上一次写什么,下一次就保证能读到什么。根据CAP理论,这种实现需要牺牲可用性。
弱一致性:系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。
用户读到某一操作对系统数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。
最终一致性:最终一致性是弱一致性的特例,强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。到达最终一致性的时间,就是不一致窗口时间,在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。
最终一致性模型根据其提供的不同保证可以划分为更多的模型,包括因果一致性和会话一致性等。
因果一致性:要求有因果关系的操作顺序得到保证,非因果关系的操作顺序则无所谓。
进程A在更新完某个数据项后通知了进程B,那么进程 B之后对该数据项的访问都应该能够获取到进程 A更新后
的最新值,并且如果进程B要对该数据项进行更新操作的话,务必基于进程A更新后的最新值。
在微博或者微信进行评论的时候,比如你在朋友圈发了一张照片,朋友给你评论了,而你对朋友的评论进行了回复,这条朋友圈的显示中,你的回复必须在朋友之后,这是一个因果关系,而其他没有因果关系的数据,可以允许不一致。
会话一致性:将对系统数据的访问过程框定在了一个会话当中,约定了系统能保证在同一个有效的会话中实现“读己之所写”的一致性,就是在你的一次访问中,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。实际开发中有分布式的Session一致性问题,可以认为是会话一致性的一个应用。

为什么Dubbo不用JDK的SPI,而是要自己实现?

java spi缺点:
1、需要遍历所有实现并实例化,假设一个实现类初始化过程比较消耗资源且耗时,但是你的代码里面又用不上
它,这就产生了资源的浪费。也无法准确引用
2、没有使用缓存每次load都需要重新加载
Dubbo SPI:
1、给每个实现类配了个名字,通过名字去文件里面找到对应的实现类全限定名然后加载实例化,按需加载。
2、增加了缓存存储实例,提高读取性能。
3、提供了对IOC和AOP等高级功能的支持,以实现更多类型的扩展。

为什么Zookeeper可以用来作为注册中心

可以利用Zookeeper的临时节点和watch机制来实现注册中心的自动注册和发现,另外Zookeeper中的数据都是存在内存中的,并且Zookeeper底层采用了nio,多线程模型,所以Zookeeper的性能也是比较高的,所以可以用来作为注册中心,但是如果考虑到注册中心应该是注册可用性的话,那么Zookeeper则不太合适,因为Zookeeper是CP的,它注重的是一致性,所以集群数据不一致时,集群将不可用,所以用Redis、Eureka、Nacos来作为注册中心将更合适。
Zookeeper中的领导者选举的流程是怎样的?
付了ZOOKeeper茱群,整个茱群需要从集群节点中选出一个节点作为Leader,大体流程如下:
1.集群中各个节点首先都是观望状态,一开始都会投票给自己,认为自己比较适合作为leader
2.然后相互交互投票,每个节点会收到其他节点发过来的选票,然后pk,先比较zxid,zxid大者获胜,zxid如果相等则比较myid,myid大者获胜3.一个节点收到其他节点发过来的选票,经过PK后,如果PK输了,则改票,此节点就会投给zxid或myid更大的节点,并将选票放入自己的投票箱中,并将新的选票发送给其他节点
4.如果pk是平局则将接收到的选票放入自己的投票箱中
5.如果pk赢了,则忽略所接收到的选票
6.当然一个节点将一张选票放入到自己的投票箱之后,就会从投票箱中统计票数,看是否超过一半的节点都和自己所投的节点是一样的,如果超过
半数,那么则认为当前自己所投的节点是leader
7.集群中每个节点都会经过同样的流程,pk的规则也是一样的,一旦改票就会告诉给其他服务器,所以最终各个节点中的投票箱中的选票也将是一
样的,所以各个节点最终选出来的leader也是一样的,这样集群的leader就选举出来了

【临渊羡鱼不如退而结网】

你可能感兴趣的:(dubbo,java)