分布式面试

烟雨 4年前 (2021-12-27) 阅读数 561 #面试
文章标签 面试

一、分布式服务接口如何保证幂等性

所谓的幂等性,一个接口,同一个请求,发送多次,保证接口结果是确定的。
如何保证呢?
例如接口请求必须带一个唯一标识,订单支付请求,肯定包含订单ID,一个订单ID最多支付一次。每次处理完请求后,必须有一个记录,标记这个请求处理过了。
比如在MySQL中记录一条支付流水表,支付前记录一条订单的支付流水,且支付流水唯一(唯一键约束),只有成功插入了这张表,才能进行实际的扣款支付。

二、说说你们的分布式session方案是啥?

tomcat+redis

通过tomcat RedisSessionManager让session数据存储到Redis中。

Spring Session + redis

使用Spring Session配置基于Redis来存储session。这样就可以通过代码直接获取到redis中的session了。

三、分布式事务

常见的分布式事务方案:
两阶段提交/XA
TCC方案
本地消息表
RocketMQ事务消息
最大努力通知
可靠消息最终一致性方案

四、讲一讲ZAB协议

ZAB协议是分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议。
ZAB协议包括两种基本协议:崩溃恢复和消息广播
崩溃恢复:当整个集群刚刚启动或者Leader服务器宕机、重启、网络故障导致不存在过半服务器与Leader服务器保持正常通讯是,所有服务器进入崩溃恢复模式,首先选举产生新的Leader,然后集群中的Follower始与新的Leader进行数据同步。
消息广播:当集群超过一般的服务器完成数据同步后,退出崩溃恢复模式,进入消息广播模式,Leader开始接收客户端的消息。

五、zookeeper节点宕机后如何处理?

zookeeper集群至少有3个服务器。
如果有一个Follower宕机,还有2台提供服务。数据并不会丢失。
如果Leader宕机,zookeeper会重新选举Leader,zookeeper有一个过半机制,只要过半的机器没有宕机,zookeeper还是可以提供服务。

六、zookeeper中的四种数据节点

1、持久节点
2、持久顺序节点
3、临时节点
3、临时顺序节点

七、非公平锁

image.png

如上实现方式在并发问题比较严重的情况下,性能会下降的比较厉害。
主要原因是,所有的连接都在对同一个节点进行监听,当服务器检测到删除事件时,要通知所有的连接,所有的连接同时收到事件,再次并发竞争,这就是羊群效应
这种加锁方式是非公平锁的具体实现。

八、公平锁

image.png

  1. 一个请求就来,直接在/lock节点下创建一个临时顺序节点。

  2. 判断自己是不是/lock节点下最小的节点。

    1. 否:对前面一个节点进行监听。

    2. 是:获取锁,处理完毕,释放锁,删除自己创建的临时时顺节点。然后/lock的第一个临时时顺节点会收到通知,重复第二步骤。

如上借助于Zookeeper临时顺序节点,可以避免同时多个节点的并发竞争锁,缓解了服务端压力。
这种实现方式所有加锁请求都进行排队加锁,是公平锁的具体实现。

九、共享锁

前面这两种加锁方式有一个共同的特质,就是都是互斥锁,同一时间只能有一个请求占用,如果是大量的并发上来,性能是会急剧下降的,所有的请求都得加锁!
其实有的请求只是读取数据,不需要加锁!但是如果读数据的请求还没读完,这个时候来了一个写请求,怎么办呢?
有人已经在读数据了,这个时候是不能写数据的,不然数据就不正确了。直到前面读锁全部释放掉以后,写请求才能执行,所以需要给这个读请求加一个标识(读锁),让写请求知道,这个时候是不能修改数据的。
如果已经有人在写数据了,再来一个请求写数据,也是不允许的,这样也会导致数据的不一致,所以所有的写请求,都需要加一个写锁,是为了避免同时对共享数据进行写操作。

image.png

十、Dubbo和Spring Clound有哪些区别

Dubbo底层使用的是Netty这样的NIO框架,基于TCP协议传输,配合Hession序列化完成RPC通信。
Spring Clound基于Http协议Rest接口远程调用过程的同喜,相对于Http请求会有更大的报文,占用带宽更多。但是REST相比RPC更灵活,服务提供方和调用方只依靠一之纸契约,不存在代码级别的强依赖,这样强调快速演化的微服务环境下,显得更适合。

十一、Dubbo支持哪些协议

dubbo
rmi
http
webservice
hessian
redis

十二、Dubbo集群提供哪些负载均衡策略

随机负载均衡(Random LoadBalance)

随机负载均衡策略就是从多个Provider中随机选择一个。可通过权重对负载均衡产生影响。可以在Dubbo Admin中对Provider进行权重的设置。

轮询负载均衡(RoundRobin LoadBalance)

轮询负载均衡,就是依次的调用所有的Provider。和随机负载均衡策略一样,轮询负载均衡策略也有权重的概念。
轮询负载均衡算法可以让Dubbo调用严格按照我们设置的比例来分配。不管是少量的调用还是大量的调用。
但是轮询负载均衡算法也有不足的地方,存在慢的Provider累积请求的问题。
比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上,导致整个系统变慢。

最少活跃调用数负载均衡(LeastActive LoadBalance)

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差,使慢的机器收到更少。目的是让更慢的机器收到更少的请求。
最少活跃数的统计是放在消费者这边的。大致流程如下:
  1. 消费者会缓存所调⽤服务的所有提供者,⽐如记为p1、p2、p3三个服务提供者,每个提供者内都个属性记为active,默认位0。

  2. 消费者在调⽤次服务时,如果负载均衡策略是leastactive。

  3. 消费者端会判断缓存的所有服务提供者的active,选择最⼩的,如果都相同,则随机。

  4. 选出某⼀个服务提供者后,假设位p2,Dubbo就会对p2.active+1。

  5. 然后真正发出请求调⽤该服务,消费端收到响应结果后,对p2.active-1。

  6. 这样就完成了对某个服务提供者当前活跃调⽤数进⾏了统计并且并不影响服务调⽤的。

一致性Hash算法(ConsistentHash LoadBalance)

使用一致性Hash算法,让相同参数的请求总是发到同一Provider。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
致性Hash负载均衡涉及到两个主要的配置:
hash.arguments : 当进行调用时候,根据调用方法的哪几个参数生成key,并根据key来通过一致性hash算法来选择调用结点。例如调用方法invoke(String s1,String s2); 若hash.arguments为1(默认值),则仅取invoke的参数1(s1)来生成hashCode。
hash.nodes: 为结点的副本数。
<dubbo:parameter key="hash.arguments" value="0,1" />
<dubbo:parameter key="hash.nodes" value="320" />


版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门