RabbitMQ&Kafka总结

  1. 为什么使用消息队列?

    1. 解耦、异步通信、削峰、冗余、异常处理,分布式事务的最终一致性。

    2. 消息不丢

    3. 微秒级,这是 RabbitMQ 的一大特点,延迟最低

  2. 消息队列有什么优点和缺点?

    1. 系统可用性降低,过度依赖mq

    2. 系统复杂度提高:

      1. 顺序:在消费者中解决顺序问题

      2. 重复:消息幂等。

      3. 丢失:系统保证,本地发消息,消息到消息中心,再到交换机,队列。均采用日志的形式。

    3. 一致性问题:mq是异步,弱一致性,强最终一致性的工具。 非必要消息,和可延迟的用mq。

  3. Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?

  4. 消息丢失怎么办?

    1. RabbitMQ&Kafka总结_第1张图片

       

    2. 生产者丢消息:

      1. 同步:用事务控制,影响性能。

      2. 异步:confirm模式:每个消息一个id ,发送方ack确认。

    3. RabbitMQ丢消息:

      1. 开启持久化:

        1. 队列持久化,

        2. 消息持久化,deliverMode = 2

      2. 如果还没有持久化mq挂了,ack 机制发送者能感知到。

    4. 消费端丢消息: 还没消费,进程挂了。

      1. 关闭自动ACK,处理后,进行手动ack

  5. RabbitMQ的高可用

    1. 实现:主从(非分布式)

    2. 模式:

      1. 单机、

      2. 普通集群:队列只在一台机器,一个挂了就挂了。

      3. 镜像集群:主从,但是一个机器会包含所有数据。没有扩展性。

  6. 如何保证消息顺序性:

    1. 场景:一个queue多个消费者,

    2. 解决方式:一个消费者,内存自己排序后,调用worker处理。

  7. 如何解决消息队列的延时以及过期失效问题:

    1. 队列积压:

      1. 先解决消费卡脖子问题。

      2. 考虑是否扩容。

      3. 增加消费速率。

    2. 失效大量ttl::

      1. 写脚本,拉出来,塞进队列

      2. 开发mq后台,进行持久化后,

  8. 设计一个消息队列。

    1. 发送者:

      1. 建立channel Tcp连接

      2. 信道的原理是一条线程一条信道,多条线程多条信道共同使用一条TCP连接。一条TCP连接可以容纳无限的信道,及时每秒造成成千上万的请求也不会造成性能瓶颈

      3. 发送消息 + 处久化 + ack回应

    2. 服务器 broker 代理:

      1. 交换机:(binding key) xxx_direct xxx_topic

        1. RabbitMQ&Kafka总结_第2张图片

           

        2. 直接(Direct):直接交换机通过消息上的路由键直接对消息进行分发。

        3. 扇出(Fanout):一个扇出交换机会将消息发送到所有和它进行绑定的队列上。

        4. 主题(Topic):这个交换机会将路由键和绑定上的模式进行通配符匹配。

      2. 持久化消息:必须和队列一起被持久化

      3. ack应答

      4. 消息分发到queue:

    3. 消费者:

      1. 轮询拉取队列里的消息

      2. Ack 应答

      3. 消费中挂掉了,broker 收不到ack怎么办? broker 会判断是否断开连接,重新

    4. HA:

      1. 普通模式:同步节点所以信息,不包含message

      2. 镜像模式: 副本

  9. KafKa:

    1. 设计:

      • 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能。

      • 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输。

      • 支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输。

      • 同时支持离线数据处理和实时数据处理。

      • Scale out:支持在线水平扩展

      • RabbitMQ&Kafka总结_第3张图片

         

    2. producer 流程:

      1. producer 根据 broker 拿到对应存储的paritition地址。

        1. broker会根据paritition机制选择一个存储。

        2. broker通过ZooKeeper找到该Partition的Leader返回

      2. producer向Partition发消息

        1. Leader  写到本地 log

        2. follower 从 leader pull数据,pull到 发ack给leader ,然后写到本地log

      3. Partition leader发ack给producer

    3. consumer 流程:

      1. consumer注册到zookeeper上

      2. Consumer 去pull partition 数据 

        1. 服务器会记录每个consumer的在每个topic的每个partition下的消费的offset,然后每次去消费去拉取数据时,都会从上次记录的位置开始拉取数据

        2. offset() + 全局消息id

        3. 通过offset  二分法找到 segment

        4. 通过offset  二分法 index 中 大概位置

        5. 通过全局消息id 二分法 找到log中 消息位置。

      3. 一个group的consumer 和 partition 数量最好一致。

      4. consumer 消费后会发commit 给zookeeper 更新偏移量

    4. 存储:

      1. 每一个partition 都是一个文件,包含2部分,稀疏索引,log查找根据2分发

        1. .index文件:offset, 物理偏移量

        2. .log文件:全局消息id + 数据 

        3. Segment:partition物理上由多个segment组成。

    5. Kafka性能为什么快:

      1. 分区

        1. 为什么要有paritition:负载均衡,消除机器io的性能瓶颈。

        2. consumer group 设定

      2. 网络传输上减少开销

        1. 批量发送:先缓存到内存中,超过一定大小或时间发送

        2. 端到端压缩:数据从发送到服务器上 都是压缩,不解压,频繁压缩和解压会降低性能。到消费者手上也是压缩的。

      3. 顺序读写:

        1. 顺序 和随机  差6000倍

      4. 零拷贝技术:

        1. 传统 文件到socket 中需要 

          1. 从磁盘co 到 内核缓冲区

          2. 切换内核到用户 co 到 用户缓冲区

          3. 应用程序讲数据写到内核的socket缓冲区

          4. 操作系统, co到 网卡接口缓冲区 发出去

        2. 调用linux sendfile系统实现0拷贝,java调用FileChannel.transferTo

        3. 从磁盘通过DMA引擎复制到内核缓冲区直接放到网卡接口

      5. 优秀的文件存储机制

        1. 稀疏索引、文件采用偏移量,利用二分法查找。

    6. 主从复制机制:

      1. Broker 的 主从,读写和备份分离,leader选举

      2. 完全同步:follower 都复制了才算commit

      3. 完全异步:leader 写入log 才算

      4. kafka:有一个复制到内存就算commit

      5. leader的ISR列表:从落后太多会剔除,默认10000

你可能感兴趣的:(框架,面试,rabbitmq,kafka)