当前位置: 首页 > news >正文

面试八股-各种中间件

1.消息队列

1.1.应用场景

  • 异步处理 减少请求的等待时间,将请求放入队列待处理,提高总体性能
  • 应用解耦 将消息存入队列,下游服务订阅并消费
  • 流量削峰 在高峰期应对消息过多导致崩溃的情况,MQ积压请求,系统每次从MQ拉取能力范围内的数据

1.2.示例

  • 电商系统
  • 日志收集系统
  • JMS

1.3.消息模型

  • 队列模型:消费者之间是竞争关系,即每条消息只能被一个消费者消费

  • 发布订阅模型:将消息发送至一个topic中,所有订阅该topic的服务消费(同时也是kafka的原理)

1.4.消费方式

  • 同步 收到消息之前阻塞
  • 异步 消息到达之后,自动调用onMessage方法

1.5.各种消息队列实现的比较

Kafka 1.1.0RabbitMQ 3.6.10RocketMQ 4.2.0
优先队列不支持支持,优先级0-10之间支持,维护不同的优先级队列,根据message的优先级发送到对应的队列中
延迟队列不支持支持支持
死信队列不支持支持支持
重试队列不支持支持支持
消费模式pullpull+pushpull+长轮询
广播消费支持,Kafka对于广播消息的支持更加正统支持支持
批量消息支持,生产者异步发送支持支持,生产者同步发送
消息回溯支持Kafka支持offset和timestamp两种维度进行消息回溯不支持,一旦被确认消费就会被删除支持
消息堆积支持,海量消息堆积,堆积能力和磁盘大小挂钩支持,但是内存达到阈值时,性能会受到影响支持海量消息堆积
持久化方式消息队列,segment方式支持消息队列
消息追踪不支持。消息追踪可以通过外部系统来支持,但是支持粒度没有内置的细腻支持支持
消息过滤客户端级别的支持,可用过kafka stream进行消息过滤不支持,但是二次封装一下也比较简单支持,可通过message tag、属性进行过滤
多租户不支持支持不支持
多协议支持只支持定义协议,目前几个主流版本间存在兼容性问题AMQSJMS,OpenMessaging
跨语言支持当前版本Java编写,支持多种语言客户端采用Erlang编写,支持多种语言客户端Java C++ Go
流量控制支持client和user级别,通过主动设置可将流控作用于生产者或消费者流量控制基于credit-base算法,是内部被动触发的保护机制,用于生产者层面RocketMQ提供了针对不同维度的流量控制
消息顺序性支持普通的顺序消息,即对于单个分区的消息发送和消费是有序的,但是不保证不重复顺序性条件比较苛刻,需要单线程发送,单线程消费并且不采用延迟队列、优先级队列等一些高级功能,某种意义上来说不支持顺序性支持普通的顺序消息和严格的顺序消息
幂等性支持单个producer单个分区的会话幂等性不支持不支持,不解决消息的重复问题
事务性消息支持支持支持
性能最高
高可用和容错使用partition的副本机制和isr选举机制保证高可用普通集群非高可用,可用镜像模式和主备集群通过broker的master和slave实现高可用
定时消息不支持支持支持
负载均衡客户端消费者负载均衡,需要一个broker作为corrdinator默认是轮询客户端负载均衡,支持平均和轮询分配
刷盘策略默认是异步刷盘默认是内存存储默认同步刷盘

1.6.各种问题的解法

1.6.1.防止消息丢失

分类

  • 生产消息:消息发送至broker的时,需要处理broker响应,如果写入失败进行重传。
  • 存储消息:如果消息发送至broker缓存中还未刷盘便挂掉,则会出现信息丢失,此时需要做broker的备份。
  • 消费消息:如果消息发送至消费者缓存就宕机,则会出现信息丢失,正确做法是消费者处理完业务逻辑之后在给broker响应。

实现

  • RabbitMQ
    • 生产者丢消息:生产者发送之前丢失。生产者发送数据前开启事务发送消息,失败则回滚,成功则提交,这种同步方式可能会造成吞吐量下降。开启confirm模式,每条消息都会有唯一id,写入成功后有对应的消息回复,如果超时也可以重发,这种异步机制是一般会采用的。
    • RabbitMQ自己丢消息:RabbitMQ没有持久化,重启数据丢失。需要设置消息持久化到磁盘,首先创建queue的时候将其设置为持久化,可以保证RabbitMQ持久化queue的元数据。发送消息时将消息的deliveryMode设置为2,这样消息就会被设为持久化方式,必须同时开启这两个才行。和生产者confirm机制配合使用。
    • 消息端丢消息:消费者刚读到数据就挂掉。关闭RabbitMQ的自动ACK,让消费者手动ack。
  • Kafka
    • 生产者丢消息:发送过程中丢失数据。关闭自动提交offset,生产者处理完毕之后手动提交offset。
    • Kfaka自己丢消息:
      • 给topic 设置replication.factor 参数大于1,要求每个partition至少有两个副本
      • 在kafka服务端设置min.isync.replicas参数大于1,要求一个leader感知到至少有一个follower在跟自己保持正常联系同步数据
      • 在生产端设置acks=all,要求每条数据必须写入所有replica副本之后,才能认为是成功了
      • 在生产端设置retries=MAX,表示一旦写入失败,就不停重试
    • 消费端丢消息:自己自动提交了offset还没来的急处理消息。设置ack=all后就不会丢失数据。

1.6.2.消息幂等处理(不重复消费)

  • 天然幂等的操作
    • 查询操作
    • 删除操作
  • 机制
    • 唯一索引
    • token机制
    • 悲观锁和乐观锁
    • 分布式锁
  • select+insert+并发不高的后台系统

1.6.3.消息按序处理

分类

  • 全局有序:只能由一个生产者往一个队列中发消息,并且消费者单线程消费。

  • 部分有序:大部分需求是部分有序。即将Topic内部划分为所需队列数,把消息用过特定策略发往固定队列中,每个队列对应一个单线程处理的消费者。即完成了部分有序的需求,又通过增加队列数量来提高并发性和处理效率。

实现

  • RabbitMQ:
    • 原因:集群部署MQ,不同消费者执行速度不同导致顺序错乱
    • 解决:每个消费者消费固定的queue,同一个订单号的消息发送到同一个queue中
  • Kafka:
    • 原因:一个topic下同一个partition中消息肯定有序,生产者写时指定key,同一个key肯定发到同一个partition中。但是最终消费者使用多线程,每个线程速度不一致
    • 解决:处理线程前面增加一个内存队列,单个线程只负责其中一个队列的消息
  • RocketMQ:
    • 原因:一个Topic可以指定多个MessageQueue,同一个订单号的binlog进入了不同的MessageQueue,进而导致一个订单的binlog被不同机器的消费者处理
    • 解决:想办法让同一个订单的binlog进入同一个MessageQueue中

1.6.4.处理堆积消息

  • 消费者消费慢,优化消费逻辑

  • 扩容,增加队列数和消费者数。一定要增加队列数,因为一个Topic中一个队列只会分配给一个消费者

1.6.5.MQ失败消息的处理

  • 核心业务队列
  • 死信队列 失败消息存储,由一个专门程序负责检测目标消费者是否正常,正常的话从该队列中取出消息进行消费

1.7.Kafka速度快的原因

  • 顺序写入 每个partition其实都是一个文件,受到消息后Kafka把数据插入到文件末尾,消费者有offset用于保存读到了第几条数据。
  • Memory Mapped Files 使用内存映射文件,直接利用操作系统的Page来实现文件到物理内存的直接映射。操作系统会在适时进行同步硬盘操作,分为同步和异步两种模式,前者等待flush之后再返回,后者写入mmap之后直接返回。

2.搜索引擎

2.1.搜索方式

  • 顺序搜索法
  • 索引搜索法 全文搜索使用的

2.2.特点

  • 相关度排序
  • 文本关键字高亮显示
  • 摘要截取
  • 只关注文本,不考虑语义
  • 搜索效果更加精确

2.3.使用场景

  • 替换数据库模糊查询,数据库左模糊会让索引失效
  • 全文检索式搜索引擎寄出
  • 只对指定领域的网站进行索引和搜索,即垂直搜索
  • 可以在word、pdf等各种各样的数据格式中检索内容
  • 输入法等

2.4.倒排索引

2.4.1.创建索引

  1. 分词
  2. 语言处理(单词缩减为词根等)
    1. stemming 词干提取,用缩减方式
    2. lemmatization 词形还原,用转换方式
  3. 索引组件创建字典
  4. 文档倒排链表

2.4.2.使用索引

  1. 词法分析识别单词和关键字
  2. 语法分析生成语法树
  3. 语言处理(和索引一致)
  4. 根据文档和查询语句相关性排序

2.4.3.计算工具

权重计算公式 余弦相似度

Lucene 全文搜索工具包 依赖于Java 不适合集群环境

ES:全文搜索服务器 基于Lucene Rest HTTP调用,对集群支持

分词器 找几个常用分词器

  • standard(过滤标点符号

  • simple (过滤数字和标点符号)

  • whitespace (不过滤,按照空格分隔)

  • stop (过滤停顿单词及标点符号,例如is are等等)

  • keyword (视为一个整体不进行任何处理)

  • path hierarchy tokenizer (路径层次分词器)

  • 中文分词 analysis-ik

3.Kafka

3.1.特点

  • 一个分布式流式处理平台,也可以当作消息队列使用。

  • 性能强,且非常可靠,在大数据领域生态兼容性好。

  • 采用的是 发布-订阅模型,当一个生产者生产消息后,其他订阅该消息的消费者都可以消费完整的消息。

3.2.架构

  • Kafka-cluster:一个Kafka集群中包含多个broker
  • Broker:可以看作是一个独立的Kafka服务器,每个broker上有多个topic
  • Topic:主题,生产者将消息发送到特定的主题,消费者从订阅的主题消息,每个topic有多个分区,来提高负载
  • Partition:分区,每个topic有多个分区,并且这些分区有多个副本,可以分布在不同的broker上,防止数据丢失

3.3.多副本机制

每个分区都有多个副本,发送的消息先存入leader,然后同步到其他副本。

  • 多副本保证了数据安全性,防止一个broker宕机造成的数据丢失
  • 多分区的目的是提高并发能力,即负载均衡,分区分布在不同的broker上

3.4.和RocketMQ

RocketMQ的出现是因为kafka不支持在交易、订单、充值等场景下许多特性,于是阿里编写了RocketMQ,定位于非日志的可靠消息传输;而kafka诞生的时候定位是日志传输。

3.5.zookeeper管理Kafka

  • broker注册:每个broker在启动时,都会到zookeeper上注册
  • topic注册:kafka中topic会被分为几个分区并分布在broker上,这些分区信息和与broker的对应关系也都会由zookeeper维护
  • 负载均衡:zookeeper根据分区数量和消费者来负载均衡

3.6.消息相关问题解法

3.6.1.消息有序性

一个topic中可以有多个分区,消费者发送消息时在每个分区中使用的是先入先出的方法。能保证每个分区中消息的有序性。但没办法保证各分区之间的有序性。

  • 一个topic只对应一个分区
  • 发送消息时指定分区

3.6.2.保证消息不丢失

1)生产者:发送时要有返回,即使用callback得知消息是否发送成功

2)消费者:当提交了偏移量后还没有消费,挂掉,那就会造成丢失。因此必须在真正消费后提交偏移量。这时候可能会出现重复消费,比如消费后偏移量还没提交就挂掉。

3)Kafka:当分区副本中的leader挂掉后,如果消息还没有同步到其他副本上,会造成消息丢失,因此要设置一定有几个副本更新完消息后才算发送成功。

3.6.3保证不重复消费-幂等处理

通过业务来保证

4.Zookeeper

是一个分布式服务管理服务,用来管理分布式服务中的一些问题,是很多分布式技术和框架的重要组件,比如hadoop,dubbo。

4.1.用途

  • 集群管理:分布式系统中会有节点的加入和退出,其他机器需要感知变化,并作出相应的调整和决策。
  • 命名服务:通过命名服务,分布式系统可以根据特定的名字来获取资源或服务器。
  • 负载均衡
  • 分布式锁:对于分布式系统,多个进程直线的活动之间会需要进行协调,zookeeper来处理。

4.2.运行模式

  • 单机模式
  • 集群模式
  • 伪集群模式 (各机器在同一台机器上)

4.3.角色

  • Leader 进行投票的发起和决议,更新系统状态
  • Follower 接受客户端请求,并给客户端返回结果,参与投票。(写操作只有leader可以做,follower得到要转发给leader,读操作谁都可以做)
  • Observer 不参与投票,可以提高可伸缩性(增加节点提高负载能力)。等于增加数个不参与投票的节点

4.4.节点的四种状态

  • leading
  • following
  • observing
  • looking 没有leader时,寻找leader的状态

4.5.Zab协议(原子广播协议)

4.5.1.限制

其定义了事务请求的方式

  • 所有事务请求必须由一个全局唯一的服务器来协调处理,即leader
  • leader负责将一个客户端请求,转化为一个proposal,并广播到其他节点
  • leader要保证超过半数节点得到正确响应后,leader才会向所有follower服务器发送commit消息进行proposal提交

4.5.2.消息广播

正常接收事务的状态。消息广播流程如下

  • 客户端发起一个写请求,leader将请求转化成一个proposal,并分配一个全局zxid
  • leader为每个follower服务器分配一个单独的队列,然后将广播的proposal放在队列中,并根据先入先出的规则进行消息发送(使用队列保证异步级耦合)
  • follower收到proposal后,首先将其以事务的方式写入本地磁盘,写入成功后返回ack
  • leader收到超半数ack后,即认为消息发送成功,可以发送commit消息
  • leader和follower将事务提交

4.5.3.崩溃恢复

条件:

  • leader崩溃
  • 服务器启动
  • 不存在半数节点和leader通信

主要阶段:

  • 选举阶段
  • 发现阶段
  • 同步阶段

选举阶段

选举机制必须满足两个条件

  • 新选择的leader不能包含未提交的proposal
  • 新选择的leader必须包含最大的事务id(避免leader事务回退)

具体流程

每个服务器有两个id,myid(自己id)和zxid(事务id)

  1. 初始投票,每个服务器都给自己投一票
  2. 同步投票结果,每个服务器将各自投票结果同步给其他服务器
  3. 检查投票有效性
  4. 处理投票,先检查zxid,较大的服务器优先作为leader,zxid相同时,myid较大的作为leader
  5. 统计投票结果,超半数节点得到相同的结果时才算成功
  6. 更改服务器状态

发现阶段 发现leader

  • 从所有节点发现最新的zxid,防止因为出现意外生成两个leader

  • zxid前32位为epch,epoch最大的是leader

  • leader接受所有follower发来的epoch,并选择最新的,发送给follower,并在上面加1作为自己的epoch值

同步阶段 同步数据

leader接收所有follower发送的zxid,并选择最大的更新到自己的事务日志,并将事务日志同步给所有follower,超半数同步完成则结束崩溃恢复

4.6.处理丢弃的事务 - 依靠zxid

每个新事务都有一个递增的唯一zxid

如果一个节点数据同步时发现自身最大zxid要大于leader上的最大zxid,则进行回退。

4.7.zookeeper的事件通知-watcher

客户端可以像节点注册watcher,节点发生变化时,通知客户端作出相应的处理

相关文章:

  • 电子商务网站建设与全程实例/网站建设平台有哪些
  • 潍坊做公司网站/seo培训讲师招聘
  • flash网站建设/站长工具的网址
  • 租网站服务器/我国网络营销现状分析
  • 旅游便宜网站建设/公司快速建站
  • 网站如何做流量赚钱吗/优秀的营销策划案例
  • AbstractProcessor相关的API记录
  • 【案例实践】长时间序列遥感数据分析与代码实现技术应用
  • 实验室天平台制作要求
  • PyTorch | 学习笔记4
  • 后台执行linux命令
  • Web前端:广州蓝景实训
  • 【TypeScript】TS入门(一)
  • 以技术创新践行社会责任,欧科云链斩获界面新闻年度双项大奖
  • 通过API远程调用Hue之一——登录和登出
  • JavaSE第6篇:面向对象上
  • 【运维有小邓】AD域权限报表
  • hutool工具并发使用 Sftp sftp = new Sftp(sshHost, sshPort, sshUser, sshPass) 的坑