Tags

  • 技术

22|消息队列:消息队列可以用来解决什么问题?

  1. 你用过消息队列吗?主要用来解决什么问题?异步、削峰和解耦你能各举一个例子吗?
    异步: 发送邮件
    削峰: 高并发场景
    解耦: 生产者消费者模型
    综合案例: 秒杀场景.服务分为轻重之分.轻量级的部分比如合法性校验、库存内存预扣减差(或者分布式锁扣减).库存扣减成功, 之后再把请求丢到消息队列, 建立订单、进行付款.
    
  2. 你用的是哪个消息队列?为什么使用它而不用别的消息队列?
    kafka, 具有高吞吐量和分布式扩展能力
    
  3. 为什么你一定要用消息队列?不用行不行?不用有什么缺点?
    同步调用方案相比引入消息队列,
    性能差: 需要停下等全部调用完成才可以返回响应
    可扩展性差: 新的下游要接入比较麻烦, 使用消息队列直接订阅消息即可, 不需要对接接口.
    可用性差: 要确保下游同步调用全部成功,容错比较麻烦, 远不如确保自己发送消息成功到消息队列简单.
    
  4. 在对接多个下游的时候,直接用 RPC 调用行不行?为什么?
    不理想, 不结偶, 性能问题:同步调用,下游响应慢会影响整体服务. 扩展性问题: 对接多个下游需要对接服务接口,较消息队列比较重, 不够灵活, 维护成本高. 可靠性问题: 下游一旦不可用,影响自己服务可用性.而使用消息队列, 消息可以存储起来, 等下游服务恢复后再处理.
    
  5. 为什么说使用消息队列可以提高性能?
    不需要像同步调用那样,要服务停下等待全部调用返回响应才能完成请求.
    
  6. 为什么说使用消息队列可以提高扩展性?
    订阅消息远比 对接接口http或者rpc 容易维护.
    
  7. 为什么说使用消息队列可以提高可用性?
    下游的同步调用一旦不可用就会影响上游服务, 而使用消息队列只要确保自己消息成功发送就算请求成功
    
  8. 为什么秒杀场景中经常用消息队列?怎么用的?
    可以异步、解耦、削峰,  请求划为轻重之分.  请求一开始先进行校验、预减库存等内存操作, 然后发送消息再进行订单生成、用户支付等无法高并发的服务
    
  9. 订单超时取消可以怎么实现?
    延时消息、定时任务
    
  10. 你了解事件驱动吗?
    发生事件后发送消息
    
  11. 什么是 SAGA 事务?怎么利用事件驱动来设计一个 SAGA 事务框架?
    一个事件一个消息, 下游消费消息, 失败也发消息进行反向补偿.
    

24|消息积压:业务突然增长,导致消息消费不过来怎么办?

  1. 一个分区可以有多个消费者吗?一个消费者可以消费多个分区吗?
    一个分区对于一个消费者组同一时间只能有一个消费者. 一个消费者可以消费多个分区.
    
  2. 你业务里面的消息有多少个分区?你怎么计算出来的?它能撑住多大的读写压力?
    分区数 = 生产者平均速率/单一消费者速率 * 1.2
    
  3. 你遇到过消息积压吗?怎么发现的?为什么会积压?最后怎么解决的?
    topic 消息累计上万, 消费者消费速率不及生产速度. 异步处理, 批量消费.
    
  4. 为什么会出现消息积压?只要我容量规划好,肯定不会有消息积压,对不对?
    生产速率大于消费速率. 不一定, 流量激增就会引发.
    
  5. 消息积压可以考虑怎么解决?
    临时消息积压可以等待;
    需要迫切解决的:
    1是否能增加分区或者建立新的 topic, 拥有更多分区
    2优化消费者性能: 换更好实例; 优化消费者逻辑
    3消费者批量处理
    4异步消费
    
  6. 增加消费者数量能不能解决消息积压问题?
    一个分区最多一个消费者, 如果n个分区已经有了n个消费者则增加消费者数量不能解决问题.
    
  7. 能不能通过限制发送者,让他们少发一点来解决消息积压问题?
    可能会影响业务体验
    
  8. 现在我发现分区数量不够了,但是运维又不准我增加新的分区,该怎么办?
    建立新topic 拥有更多分区; 优化消费者逻辑、异步消费批量消费
    
  9. 异步消费有什么缺陷?
    重复消费
    

25|消息顺序:保证消息有序,一个 topic 只能有一个 partition 吗?

  1. 消息在Kafka 分区上是怎么存储的?
    wal 日志, 追加写入
    
  2. 什么是有序消息?用于解决什么问题?
    消费者消费topic 顺序和 生产者生产topic 顺序一样,  按生产顺序消费消息处理业务的场景.
    
  3. Kafka 上的消息是有序的吗?为什么?
    kafka 不同分区上的消息是无序的
    
  4. 要想在 Kafka 上保证消息有序,应该怎么做?
    将相关消息发送到同一个分区上
    
  5. 什么是全局有序?要保证全局有序,在 Kafka 上可以怎么做?
    消息只能发送到一个分区上
    
  6. 要保证消息有序,一个 topic 只能有一个 partition 吗?
    如果是全局有序就只能有一个, 如果是业务有序就再根据业务特征分区
    
  7. 异步消费的时候怎么保证消息有序?
    把同一个业务特征的消息转发到同一个分区里
    
  8. 在你使用的多分区方案中,有没有可能出现分区间负载不均衡的问题?怎么解决?
    采用一致性哈希算法分配消息到分区,减少热点分区出现概率。监控分区负载,发现不均衡时,动态调整分区分配策略或重新分配分区。
    
  9. 增加分区有可能让你的消息失序吗?怎么解决?
    增减分区可能会失序, 一致性哈希分配调整
    
  10. 你还知道哪些消息队列是支持有序消息的?
    rabbitmq
    
  11. 要做到跨 topic 的消息也有序,难点在哪里?
    难点在于这类问题不依赖于消息队列, 需要引入一个协调者, 确保跨topic 消息有序, 或者引入事件驱动的架构.
    

26|消息不丢失:生产者收到写入成功响应后消息一定不会丢失吗?

  1. 什么是 ISR?什么是 OSR?
    跟上了主分区的从分区. osr 不在 isr 里的分区.
    
  2. 一个分区什么情况下会被挪进去 ISR,什么时候又会被挪出 ISR?
    一个分区会被挪进 ISR(In-Sync Replicas):
    - 当该分区的副本能够及时同步主分区的数据,且与主分区的日志进度差距在允许范围内(如 `replica.lag.time.max.ms` 配置的时间内),就会被加入 ISR。
    一个分区会被挪出 ISR:
    - 当该分区副本长时间无法跟上主分区的数据同步(落后主分区太多),或者副本宕机、网络异常,超过配置的最大允许滞后时间,就会被移出 ISR。
    **总结**:
    能及时同步主分区数据就进 ISR,滞后或异常
    
  3. 生产者的 acks 参数有什么含义?你用的是多少?
    0: 发送无需要分区确认
    1: 需要主分区写入
    all: 需要isr都写入
    根据数据一致性要求选择
    
  4. 怎么根据业务选择合适的 acks 参数?
    越高数据一致性要求越严格
    
  5. 消息丢失的场景有哪些?
    生产者发送: ack=0, broker 可能没收到
    broker: ack=1, 只是写到了主分区, 主分区崩溃
    刷盘:定时刷 定量刷
    消费者提交:  提交了, 没消费成功
    
  6. 你遇到过消息丢失的问题吗?是什么原因引起的?你怎么排查的?最终怎么解决的?
    参考5
    
  7. 当生产者收到发送成功的响应之后,消息就肯定不会丢失吗?
    不一定 ack=0, ack=1, ack=all, 刷盘时机都有可能异常
    
  8. acks 设置为 all,消息就一定不会丢失吗?
    不一定, 因为有unclean 选举, 如果主分区和从分区故障,则会从osr里选择分区作为主分区, 必然少消息
    
  9. 什么是事务消息?Kafka 支持事务消息吗?
    生产者提交一批消息, 要么全部成功, 要么全部失败. 支持.
    
  10. 怎么在 Kafka 上支持事务消息?
    生产者设置事务id、消费者禁用自动提交、手动提交偏移量
    
  11. 什么是本地消息表?拿来做什么的?
    发送的消息记录在本地, 可以和异步补偿机制确保消息一定发送出去.[原理是写入本地消息表之前,消息不会直接发出,而是先和业务操作一起落库,保证原子性。只有业务操作和消息记录都成功后,才由异步补偿机制定时扫描消息表,把消息真正发送出去。这样可以确保业务和消息发送的一致性,防止消息丢失或业务未完成就发出消息。]
    
  12. 你是怎么保证你在执行了业务操作之后,消息一定发出去了?
    本地事务里执行业务逻辑+插入一条消息发送记录. 之后依赖异步补偿机制, 确保每发送的消息可以被再次尝试发送, 如果失败过多则告警走人工.
    
  13. 怎么保证生产者收到发送成功的响应之后,消息一定不会丢失?需要调整哪些参数?
    ack=all, 禁用unclean 选举, 调整定量定时刷盘参数.可以极大的减少失败概率.
    
  14. 什么是 unclean 选举?有什么问题?你用的 Kafka 允许 unclean 选举吗?
    当主分区+isr不可用时, 会从osr 里选取从分区作为主分区. 通常会禁用.
    
  15. 如果你已经把消息发到了业务 topic 上,但是你标记已发送失败了,怎么办?
    如果还会重发消息, 那么需要消费者是幂等的.
    

27|重复消费:高并发场景下怎么保证消息不会重复消费?

  1. 什么是布隆过滤器?
    一种数据结构, 用于检测一个元素是否存在某个集合里.
    
  2. 什么是 bit array?
    位图, 将数字当作位图数组下标存储, 精确检测某数字是否存在集合里.
    
  3. 为什么说尽量把消费者设计成幂等的?
    因为可能会有消息重复消费
    
  4. 什么场景会造成重复消费?
    消息生产者重复发送; 消费者消费完成后,提交偏移量失败而后再次消费.
    
  5. 什么是恰好一次语义,Kafka 支持恰好一次语义吗?
    恰好一次语义(Exactly Once Semantics)是指消息在传递过程中,确保每条消息被消费者处理且仅处理一次,不会出现重复消费或消息丢失的情况。这是消息队列系统中最严格的消息传递保证。
    Kafka 支持恰好一次语义,但需要满足以下条件:
    生产者端:
    使用事务机制(Transactional API),确保一批消息要么全部成功写入,要么全部失败。
    生产者需要设置 transactional.id 来启用事务。
    消费者端:
    禁用自动提交偏移量(enable.auto.commit=false)。
    手动提交偏移量,并确保在处理完消息后提交。
    Broker 配置:
    Kafka 的 Broker 需要支持事务功能,并正确配置相关参数。
    通过以上机制,Kafka 可以实现恰好一次语义,确保消息在生产、存储和消费的整个流程中不会丢失或重复处理。
    
  6. 利用唯一索引来实现幂等的方案里,你是先插入数据到唯一索引,还是先执行业务?为什么
    既然是要幂等, 就要检测执行没执行过, 所以是要在一个事务里先插入数据到唯一索引.再执行业务.
    
  7. 如果先插入唯一索引成功了,但是业务执行失败了,怎么办?
    事务回滚, 重新消费消息
    
  8. 如果不能使用本地事务,你怎么利用唯一索引来实现幂等?中间可能会有什么问题?你怎么解决
    追求最终一致性,唯一索引写入时要有一个初始状态,同时需要有个异步检测机制,检测唯一索引表里还是初始状态的记录,再去业务表去查记录,如果业务执行成功,则修改索引表;如果业务执行失败,则重试.
    
  9. 利用唯一索引来解决幂等问题,有什么缺陷?
    写入性能取决于数据库, 撑不住高并发
    
  10. 高并发场景下,怎么解决幂等问题?
    布隆过滤器+redis+唯一性索引
    
  11. 在你的高并发幂等方案里面,为什么要引入 Redis?
    因为布隆过滤器存在假阳性
    
  12. Redis 里面的 Key 过期时间该怎么确定?
    根据业务重试的时间间隔来预估
    
  13. 布隆过滤器 + Redis + 唯一索引里面,去掉布隆过滤器行不行?去掉 Redis 呢?去掉唯一索引呢?
    层层削流, 除了唯一索引其他都可以去掉.
    
  14. 布隆过滤器 + Redis + 唯一索引方案中能不能使用本地布隆过滤器?怎么用?
    那需要一致性哈希确保如果重复消息能发到同一个分区消费
    
  15. 布隆过滤器 + Redis + 唯一索引有什么缺陷?
    复杂一些,用来撑住高并发的方案.如果不是高并发的服务则可以简化.
    

28|架构设计:如果让你设计一个消息队列,你会怎么设计架构

  1. Kafka 为什么要引入分区?只有 topic 行不行
    分区用来持久化消息, 解耦生产者和消费者
    
  2. Kafka 为什么要强调把 topic 的分区分散在不同的 broker 上?
    为了高可用
    
  3. Kafka 为什么要引入消费者组概念?只有消费者行不行?
    同一个消息可能有不同业务方来订阅, 一个消费者组对应一个业务方
    
  4. Kafka 为什么要引入 topic?
    数据传递,降低耦合性
    
  5. 如果让你来设计一个消息队列,你会怎么设计架构?
    生产者客户端、分区、broker、消费者组/消费者
    

29|高性能:Kafka 为什么性能那么好

  1. 为什么 Kafka 性能那么好?
    使用了很多优化技术:零拷贝、顺序写、分页(减少并发)
    
  2. 为什么零拷贝性能那么好?
    减少内核态数据向用户缓冲区拷贝,直接拷贝至目标缓冲区
    
  3. 写磁盘一定很慢吗?顺序写为什么很快
    写磁盘默认都会开启page cahce, 顺序写可以连续更改脏页数据, 较随机写减少寻址时间, 从而减少脏页的刷盘次数.
    
  4. 批量操作为什么快?节省了什么资源?
    网络io
    
  5. 什么是上下文切换?为什么上下文切换慢?
  6. 分区过多有什么问题?topic 过多有什么问题?
    写性能下降, 一个topic 至少一个分区, 一个分区就是一个文件
    
  7. 分区有什么好处?
    缩小并发力度, 提升性能
    
  8. 实际中使用批量发送之类的技术,可能出现什么问题?怎么解决?
    要是凑不够一批就要等, 所以需要设置等待时间兜底
    
  9. 什么是 page cache ?为什么要引入 page cache?
    页缓存,基本属于内存操作, 刷盘控制由操作系统控制,
    

30|Kafka 综合运用:怎么在实践中保证 Kafka 高性能?

  1. 什么是交换区
    swap 分区, 用于当可用的内存不足时, 将内存中的部分页淘汰出来存放到磁盘上
    
  2. 如果来不及发送,那么性能瓶颈可能在哪里?
    发送缓冲区满了, 消息丢失
    
  3. 怎么优化发送者的发送性能?
    增大缓冲区大小(buffer.memory 参数)。
    优化批量发送(batch.size 和 linger.ms 参数)。
    
  4. 批次发送的时候,多大的批次才是最合适的?
    压力测试
    
  5. 使用压缩有什么优缺点?怎么选择合适的压缩算法?
    可以提高kafka的吞吐量, 性能测试
    
  6. 怎么优化 broker?
    优化swap;调大读写缓冲区;优化磁盘io(文件系统xfs);优化主从分区同步参数(都调大);优化jvm(调大堆,启用G1)
    
  7. 怎么优化 broker 所在的操作系统?
    优选xfs
    
  8. 什么是 TCP 读写缓冲区?怎么调优?
    通过网络io 发送读取数据都会暂存到读写缓冲区
    
  9. 哪些参数可以影响 Kafka 的主从同步?你优化过吗?
    同步线程数量;同步批次字节数量;同步等待时间-> 都调大增加吞吐量
    
  10. 你有优化过 Kafka 的 JVM 吗?怎么优化的?
    增大堆, 启用 G1 垃圾回收器