22|消息队列:消息队列可以用来解决什么问题?
- 你用过消息队列吗?主要用来解决什么问题?异步、削峰和解耦你能各举一个例子吗?
异步: 发送邮件 削峰: 高并发场景 解耦: 生产者消费者模型 综合案例: 秒杀场景.服务分为轻重之分.轻量级的部分比如合法性校验、库存内存预扣减差(或者分布式锁扣减).库存扣减成功, 之后再把请求丢到消息队列, 建立订单、进行付款. - 你用的是哪个消息队列?为什么使用它而不用别的消息队列?
kafka, 具有高吞吐量和分布式扩展能力 - 为什么你一定要用消息队列?不用行不行?不用有什么缺点?
同步调用方案相比引入消息队列, 性能差: 需要停下等全部调用完成才可以返回响应 可扩展性差: 新的下游要接入比较麻烦, 使用消息队列直接订阅消息即可, 不需要对接接口. 可用性差: 要确保下游同步调用全部成功,容错比较麻烦, 远不如确保自己发送消息成功到消息队列简单. - 在对接多个下游的时候,直接用 RPC 调用行不行?为什么?
不理想, 不结偶, 性能问题:同步调用,下游响应慢会影响整体服务. 扩展性问题: 对接多个下游需要对接服务接口,较消息队列比较重, 不够灵活, 维护成本高. 可靠性问题: 下游一旦不可用,影响自己服务可用性.而使用消息队列, 消息可以存储起来, 等下游服务恢复后再处理. - 为什么说使用消息队列可以提高性能?
不需要像同步调用那样,要服务停下等待全部调用返回响应才能完成请求. - 为什么说使用消息队列可以提高扩展性?
订阅消息远比 对接接口http或者rpc 容易维护. - 为什么说使用消息队列可以提高可用性?
下游的同步调用一旦不可用就会影响上游服务, 而使用消息队列只要确保自己消息成功发送就算请求成功 - 为什么秒杀场景中经常用消息队列?怎么用的?
可以异步、解耦、削峰, 请求划为轻重之分. 请求一开始先进行校验、预减库存等内存操作, 然后发送消息再进行订单生成、用户支付等无法高并发的服务 - 订单超时取消可以怎么实现?
延时消息、定时任务 - 你了解事件驱动吗?
发生事件后发送消息 - 什么是 SAGA 事务?怎么利用事件驱动来设计一个 SAGA 事务框架?
一个事件一个消息, 下游消费消息, 失败也发消息进行反向补偿.
24|消息积压:业务突然增长,导致消息消费不过来怎么办?
- 一个分区可以有多个消费者吗?一个消费者可以消费多个分区吗?
一个分区对于一个消费者组同一时间只能有一个消费者. 一个消费者可以消费多个分区. - 你业务里面的消息有多少个分区?你怎么计算出来的?它能撑住多大的读写压力?
分区数 = 生产者平均速率/单一消费者速率 * 1.2 - 你遇到过消息积压吗?怎么发现的?为什么会积压?最后怎么解决的?
topic 消息累计上万, 消费者消费速率不及生产速度. 异步处理, 批量消费. - 为什么会出现消息积压?只要我容量规划好,肯定不会有消息积压,对不对?
生产速率大于消费速率. 不一定, 流量激增就会引发. - 消息积压可以考虑怎么解决?
临时消息积压可以等待; 需要迫切解决的: 1是否能增加分区或者建立新的 topic, 拥有更多分区 2优化消费者性能: 换更好实例; 优化消费者逻辑 3消费者批量处理 4异步消费 - 增加消费者数量能不能解决消息积压问题?
一个分区最多一个消费者, 如果n个分区已经有了n个消费者则增加消费者数量不能解决问题. - 能不能通过限制发送者,让他们少发一点来解决消息积压问题?
可能会影响业务体验 - 现在我发现分区数量不够了,但是运维又不准我增加新的分区,该怎么办?
建立新topic 拥有更多分区; 优化消费者逻辑、异步消费批量消费 - 异步消费有什么缺陷?
重复消费
25|消息顺序:保证消息有序,一个 topic 只能有一个 partition 吗?
- 消息在Kafka 分区上是怎么存储的?
wal 日志, 追加写入 - 什么是有序消息?用于解决什么问题?
消费者消费topic 顺序和 生产者生产topic 顺序一样, 按生产顺序消费消息处理业务的场景. - Kafka 上的消息是有序的吗?为什么?
kafka 不同分区上的消息是无序的 - 要想在 Kafka 上保证消息有序,应该怎么做?
将相关消息发送到同一个分区上 - 什么是全局有序?要保证全局有序,在 Kafka 上可以怎么做?
消息只能发送到一个分区上 - 要保证消息有序,一个 topic 只能有一个 partition 吗?
如果是全局有序就只能有一个, 如果是业务有序就再根据业务特征分区 - 异步消费的时候怎么保证消息有序?
把同一个业务特征的消息转发到同一个分区里 - 在你使用的多分区方案中,有没有可能出现分区间负载不均衡的问题?怎么解决?
采用一致性哈希算法分配消息到分区,减少热点分区出现概率。监控分区负载,发现不均衡时,动态调整分区分配策略或重新分配分区。 - 增加分区有可能让你的消息失序吗?怎么解决?
增减分区可能会失序, 一致性哈希分配调整 - 你还知道哪些消息队列是支持有序消息的?
rabbitmq - 要做到跨 topic 的消息也有序,难点在哪里?
难点在于这类问题不依赖于消息队列, 需要引入一个协调者, 确保跨topic 消息有序, 或者引入事件驱动的架构.
26|消息不丢失:生产者收到写入成功响应后消息一定不会丢失吗?
- 什么是 ISR?什么是 OSR?
跟上了主分区的从分区. osr 不在 isr 里的分区. - 一个分区什么情况下会被挪进去 ISR,什么时候又会被挪出 ISR?
一个分区会被挪进 ISR(In-Sync Replicas): - 当该分区的副本能够及时同步主分区的数据,且与主分区的日志进度差距在允许范围内(如 `replica.lag.time.max.ms` 配置的时间内),就会被加入 ISR。 一个分区会被挪出 ISR: - 当该分区副本长时间无法跟上主分区的数据同步(落后主分区太多),或者副本宕机、网络异常,超过配置的最大允许滞后时间,就会被移出 ISR。 **总结**: 能及时同步主分区数据就进 ISR,滞后或异常 - 生产者的 acks 参数有什么含义?你用的是多少?
0: 发送无需要分区确认 1: 需要主分区写入 all: 需要isr都写入 根据数据一致性要求选择 - 怎么根据业务选择合适的 acks 参数?
越高数据一致性要求越严格 - 消息丢失的场景有哪些?
生产者发送: ack=0, broker 可能没收到 broker: ack=1, 只是写到了主分区, 主分区崩溃 刷盘:定时刷 定量刷 消费者提交: 提交了, 没消费成功 - 你遇到过消息丢失的问题吗?是什么原因引起的?你怎么排查的?最终怎么解决的?
参考5 - 当生产者收到发送成功的响应之后,消息就肯定不会丢失吗?
不一定 ack=0, ack=1, ack=all, 刷盘时机都有可能异常 - acks 设置为 all,消息就一定不会丢失吗?
不一定, 因为有unclean 选举, 如果主分区和从分区故障,则会从osr里选择分区作为主分区, 必然少消息 - 什么是事务消息?Kafka 支持事务消息吗?
生产者提交一批消息, 要么全部成功, 要么全部失败. 支持. - 怎么在 Kafka 上支持事务消息?
生产者设置事务id、消费者禁用自动提交、手动提交偏移量 - 什么是本地消息表?拿来做什么的?
发送的消息记录在本地, 可以和异步补偿机制确保消息一定发送出去.[原理是写入本地消息表之前,消息不会直接发出,而是先和业务操作一起落库,保证原子性。只有业务操作和消息记录都成功后,才由异步补偿机制定时扫描消息表,把消息真正发送出去。这样可以确保业务和消息发送的一致性,防止消息丢失或业务未完成就发出消息。] - 你是怎么保证你在执行了业务操作之后,消息一定发出去了?
本地事务里执行业务逻辑+插入一条消息发送记录. 之后依赖异步补偿机制, 确保每发送的消息可以被再次尝试发送, 如果失败过多则告警走人工. - 怎么保证生产者收到发送成功的响应之后,消息一定不会丢失?需要调整哪些参数?
ack=all, 禁用unclean 选举, 调整定量定时刷盘参数.可以极大的减少失败概率. - 什么是 unclean 选举?有什么问题?你用的 Kafka 允许 unclean 选举吗?
当主分区+isr不可用时, 会从osr 里选取从分区作为主分区. 通常会禁用. - 如果你已经把消息发到了业务 topic 上,但是你标记已发送失败了,怎么办?
如果还会重发消息, 那么需要消费者是幂等的.
27|重复消费:高并发场景下怎么保证消息不会重复消费?
- 什么是布隆过滤器?
一种数据结构, 用于检测一个元素是否存在某个集合里. - 什么是 bit array?
位图, 将数字当作位图数组下标存储, 精确检测某数字是否存在集合里. - 为什么说尽量把消费者设计成幂等的?
因为可能会有消息重复消费 - 什么场景会造成重复消费?
消息生产者重复发送; 消费者消费完成后,提交偏移量失败而后再次消费. - 什么是恰好一次语义,Kafka 支持恰好一次语义吗?
恰好一次语义(Exactly Once Semantics)是指消息在传递过程中,确保每条消息被消费者处理且仅处理一次,不会出现重复消费或消息丢失的情况。这是消息队列系统中最严格的消息传递保证。 Kafka 支持恰好一次语义,但需要满足以下条件: 生产者端: 使用事务机制(Transactional API),确保一批消息要么全部成功写入,要么全部失败。 生产者需要设置 transactional.id 来启用事务。 消费者端: 禁用自动提交偏移量(enable.auto.commit=false)。 手动提交偏移量,并确保在处理完消息后提交。 Broker 配置: Kafka 的 Broker 需要支持事务功能,并正确配置相关参数。 通过以上机制,Kafka 可以实现恰好一次语义,确保消息在生产、存储和消费的整个流程中不会丢失或重复处理。 - 利用唯一索引来实现幂等的方案里,你是先插入数据到唯一索引,还是先执行业务?为什么
既然是要幂等, 就要检测执行没执行过, 所以是要在一个事务里先插入数据到唯一索引.再执行业务. - 如果先插入唯一索引成功了,但是业务执行失败了,怎么办?
事务回滚, 重新消费消息 - 如果不能使用本地事务,你怎么利用唯一索引来实现幂等?中间可能会有什么问题?你怎么解决
追求最终一致性,唯一索引写入时要有一个初始状态,同时需要有个异步检测机制,检测唯一索引表里还是初始状态的记录,再去业务表去查记录,如果业务执行成功,则修改索引表;如果业务执行失败,则重试. - 利用唯一索引来解决幂等问题,有什么缺陷?
写入性能取决于数据库, 撑不住高并发 - 高并发场景下,怎么解决幂等问题?
布隆过滤器+redis+唯一性索引 - 在你的高并发幂等方案里面,为什么要引入 Redis?
因为布隆过滤器存在假阳性 - Redis 里面的 Key 过期时间该怎么确定?
根据业务重试的时间间隔来预估 - 布隆过滤器 + Redis + 唯一索引里面,去掉布隆过滤器行不行?去掉 Redis 呢?去掉唯一索引呢?
层层削流, 除了唯一索引其他都可以去掉. - 布隆过滤器 + Redis + 唯一索引方案中能不能使用本地布隆过滤器?怎么用?
那需要一致性哈希确保如果重复消息能发到同一个分区消费 - 布隆过滤器 + Redis + 唯一索引有什么缺陷?
复杂一些,用来撑住高并发的方案.如果不是高并发的服务则可以简化.
28|架构设计:如果让你设计一个消息队列,你会怎么设计架构
- Kafka 为什么要引入分区?只有 topic 行不行
分区用来持久化消息, 解耦生产者和消费者 - Kafka 为什么要强调把 topic 的分区分散在不同的 broker 上?
为了高可用 - Kafka 为什么要引入消费者组概念?只有消费者行不行?
同一个消息可能有不同业务方来订阅, 一个消费者组对应一个业务方 - Kafka 为什么要引入 topic?
数据传递,降低耦合性 - 如果让你来设计一个消息队列,你会怎么设计架构?
生产者客户端、分区、broker、消费者组/消费者
29|高性能:Kafka 为什么性能那么好
- 为什么 Kafka 性能那么好?
使用了很多优化技术:零拷贝、顺序写、分页(减少并发) - 为什么零拷贝性能那么好?
减少内核态数据向用户缓冲区拷贝,直接拷贝至目标缓冲区 - 写磁盘一定很慢吗?顺序写为什么很快
写磁盘默认都会开启page cahce, 顺序写可以连续更改脏页数据, 较随机写减少寻址时间, 从而减少脏页的刷盘次数. - 批量操作为什么快?节省了什么资源?
网络io - 什么是上下文切换?为什么上下文切换慢?
- 分区过多有什么问题?topic 过多有什么问题?
写性能下降, 一个topic 至少一个分区, 一个分区就是一个文件 - 分区有什么好处?
缩小并发力度, 提升性能 - 实际中使用批量发送之类的技术,可能出现什么问题?怎么解决?
要是凑不够一批就要等, 所以需要设置等待时间兜底 - 什么是 page cache ?为什么要引入 page cache?
页缓存,基本属于内存操作, 刷盘控制由操作系统控制,
30|Kafka 综合运用:怎么在实践中保证 Kafka 高性能?
- 什么是交换区
swap 分区, 用于当可用的内存不足时, 将内存中的部分页淘汰出来存放到磁盘上 - 如果来不及发送,那么性能瓶颈可能在哪里?
发送缓冲区满了, 消息丢失 - 怎么优化发送者的发送性能?
增大缓冲区大小(buffer.memory 参数)。 优化批量发送(batch.size 和 linger.ms 参数)。 - 批次发送的时候,多大的批次才是最合适的?
压力测试 - 使用压缩有什么优缺点?怎么选择合适的压缩算法?
可以提高kafka的吞吐量, 性能测试 - 怎么优化 broker?
优化swap;调大读写缓冲区;优化磁盘io(文件系统xfs);优化主从分区同步参数(都调大);优化jvm(调大堆,启用G1) - 怎么优化 broker 所在的操作系统?
优选xfs - 什么是 TCP 读写缓冲区?怎么调优?
通过网络io 发送读取数据都会暂存到读写缓冲区 - 哪些参数可以影响 Kafka 的主从同步?你优化过吗?
同步线程数量;同步批次字节数量;同步等待时间-> 都调大增加吞吐量 - 你有优化过 Kafka 的 JVM 吗?怎么优化的?
增大堆, 启用 G1 垃圾回收器