当前位置:   article > 正文

校招后端面经——分布式_分布式系统面经

分布式系统面经

1. 分布式系统保证事务的一致性
0.cap定理

consistency: 一致性,所有数据节点上的数据一致性和正确性

availability:可用性,每个操作总能在一定的时间内返回结果

partition tolerance:分区容错,是否可以对数据进行分区

强一致性:一修改,马上更新,用户拿到永远是最新的消息

弱一致性:不保证用户会马上拿到最新的消息

最终一致性:弱一致性的一种特例,系统保证在没有后续更新的前提下,返回上一次更新的结果。

1.主从复制

一台机器负责数据的更新,其他机器负责从主机器上同步数据。

2.两阶段提交
过程

(1)协调者向所有参与者发送事务执行的请求,并等待所有参与者反馈事务的执行结果。事务参与者收到请求后,执行事务,并记录到事务日志里面,但不真正提交。参与者将自己事务的执行情况反馈给协调者,同时阻塞等待协调者的后续指令

(2)当所有参与者都能够正常执行事务后,协调者向各个参与者发送commit通知,请求提交事务。参与者收到事务提交通知之后,执行commit的操作,然后释放占有的资源。参与者向协调者返回事务提交的结果。

(3)当一个或者多个参与者回复事务执行失败或者协调者等待超时,协调者向各个参与者发送事务回滚的请求。参与者收到事务回滚通知后,执行回滚操作,并释放占有的资源。参与者向协调者反馈回滚的信息。

缺点

(1)同步阻塞:当参与者占用第三方资源等待协调者的通知时,其他第三方节点不能访问当前的资源

(2)单点故障:一旦协调者发生故障,参与者会一直阻塞下去,尤其是第二阶段,所有的参与者还处在锁定事务资源的状态,无法继续完成事务操作。

(3)数据的不一致性:在第二阶段中,当局部网络异常或者协调者在发送commit请求的时候出现故障,会导致一部分参与者没有收到commit请求,一部分收到,这样会导致数据的部分一致性

3.三阶段提交
过程

将原本两阶段提交的第一阶段一分为二;对参与者引入超时机制

(1)协调者询问参与者是否能正常执行事务,如果协调者接收到所有参与者返回的确定信息,则再向所有参与者发送执行事务的请求

(2)参与者执行事务,并将事务记录在日志中,但不真正提交,并将事务的执行情况返回给协调者,协调者收到所有参与者的确认消息后向所有参与者发送提交通知,若收到一个或者多个异常的消息,则向所有参与者发送事务回滚的请求。

(3)参与者在等待协调者发送commit请求期间,若等待超时,则会自动执行commit请求,从而避免陷入阻塞。

4. paxos协议

在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么最后能得到一个一致的状态。paxos协议就是保证每个节点执行相同的命令序列,提议者把客户端产生的议题发给发给决策者,由决策者决定使用哪个议题

过程

(1)在申请阶段,多个提议者向决策者对一个议案发出请求,在同一时刻,只有一个提议者能够获得一半以上的决策者的同意。之后进入沟通阶段,提议者会根据决策者返回的内容提交自己的议案,最终要么达成一致性,要么重新回到申请阶段

(2)paxos最重要的两个组件时提议者和决策者。提议者采用抢占的方式取获取一半以上的决策者的认同。决策者采用“喜新厌旧”的原则,一旦更大的议案申请访问,马上让旧的议案访问失效,不再接收它们提交的取值。然后给新的提议者发送访问权限,接收新的议案取值。

2. 消息队列
优点
  1. 解耦

    多个应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程都失败

  2. 异步

    生产者生产消息放到消息队列后直接返回继续操作,不用等消费者接收消息

  3. 削峰

    大量的请求可以暂时存放到消息队列中,等待处理

两种模式
  1. 点对点模式

    生产者生产消息发送到队列中,消费者读取队列中的数据,然后队列删除该消息,消费者不可能接收到重复的消息

  2. 发布/订阅模式

    生产者生产消息放到队列中,系统将这些消息发送给不同的订阅者

    每个消息可以有多个订阅者

    发布者和订阅者之间有时间上的依赖,针对某个主题的订阅者,必须先创建订阅实例才能订阅该主题消息

    为了消费消息,订阅者需要提前订阅该消息,并保持在线运行

常用的消息队列
RabbitMQ

中小型软件公司,建议选RabbitMQ。

优点

  1. 由于erlang语言的特性,mq 性能较好,高并发;
  2. 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
  3. 有消息确认机制和持久化机制,可靠性高;
  4. 管理界面较丰富;
  5. 社区活跃度高

缺点

  1. 尽管结合erlang语言本身的并发优势,性能较好,但是不利于做二次开发和维护(用erlang做开发的比较少);
  2. 消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;
ActiveMQ

服从JMS规范,运行在Java语言所支持的平台之上 ,它相比RabbitMQ的缺点是社区活跃度低,会出莫名其妙的问题,会丢失消息 ,不适合上千个队列的申请

RocketMQ

阿里开发,使用java实现

优点:

  1. RocketMQ 的所有消息都是持久化的,先写入系统页缓存,然后刷盘,可以保证内存与磁盘都有一份数据,
    访问时,直接从内存读取。
  2. 模型简单,接口易用;
  3. 性能非常好,可以大量堆积消息在队列中;
  4. 支持多种消费,包括集群消费、广播消费等。
  5. 开发度较活跃,版本更新很快(用java实现,易自主扩展)。
Kafka

优点

  1. 提供完全分布式架构, 拥有较高的可用性和可靠性, 理论上支持消息无限堆积;
  2. 支持批量操作;
  3. 快速持久化,可以在O(1)的系统开销下进行消息持久化
  4. 消费者采用Pull方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;
  5. 有优秀的第三方Kafka Web管理界面Kafka-Manager;
  6. 在日志领域比较成熟;
如何保证消息队列是高可用的

跟消息队列模型的集群有关,比如

RocketMQ,集群有多种模式,包括多主多从的异步复制模式,多主多从的同步双写模式

Kafka集群:image

一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。

如何保证消息不被重复消费
  1. 为什么会造成重复消费

    正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念,就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。 因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。

  2. 解决方案

    在客户端或者使用第三方介质开一个redis缓存,给每个消息设置一个唯一的id,并存储到redis中,每次收到消息先到redis中查找,若存在redis中,就丢掉这个消息,不存在则接收这个消息,然后存到redis中

如何保证消费的可靠性传输(以RabbitMQ为例)?
  1. 提供事务和确认模式来确保生产者不丢消息。

    事务机制:发送消息前,开启事务,然后发送消息,如果发送过程中出现什么异常,事物就会回滚,如果发送成功则提交事务(channel.txCommit())。 然而缺点就是吞吐量下降了。

    确认模式:一旦channel进入confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID,一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.如果rabiitMQ没能处理该消息,则会发送一个Nack消息给生产者,生产者可以进行重试操作。

​ 一般用confirm

  1. 消息队列丢数据

    处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发

  2. 消费者丢数据

    消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rahbitMQ会立即将消息删除,这种情况下如果消费者出现异常而没能处理该消息,就会丢失该消息。

如何保证消息的顺序性

通过某种算法,将需要保持先后顺序的消息放到同一个消息队列中(kafka中就是partition,rabbitMq中就是queue)。然后只用一个消费者去消费该队列。

若是多个消费者消费一个队列的话,就重试就好了,只要保证入队有序,出队的顺序由消费者自己负责。

3. 代理
1. 正向代理

客户端配置,通过代理去访问服务器

2.反向代理

不需要配置,对客户端来说代理本身就是服务器,但是代理是从其他服务器拿数据再返回

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/290445
推荐阅读
相关标签
  

闽ICP备14008679号