总结消息中间(redis、kafka、RabbitMQ、RocketMQ)
公共部分
1. RabbitMQ、RocketMQ、Kafka 消息中间键的作用、优点
(1) 作用及优点:解藕、异步、削峰。
(2) 缺点:提高复杂度。例如:消息重复;消息丢失;消息顺序。一致性问题。A和B系统写成功了,C系统没有成功。事务、redis Lua脚本来做原子性。
2. 比对一下,RabbitMQ、Kafka、RocketMQ
(1) 性能角度(单台):RabbitMQ 1.2W、RocketMQ 10W、Kafka 100w
(2) 集群拓展支持:Rabbit 集群很弱(确保高可用 不能拓展性能)、Kafka 和 Rocket 天生分布式
(3) 功能:Rabbitmq 比较丰富(死信消息、延迟消息) ;RocketMQ 比较丰富(死信、延迟、消息回溯、消息的过滤);Kafka 功能没有那么丰富
3. 为啥性能这么高?
RobbitMQ、Kafka用了零拷贝技术
4. 怎么解决消费重复
(1) 消费端的幂等性。例如,业务幂等性。加消息唯一ID,将消费成功的ID存入数据库,再次消费时,查看该消费是否在数据库,如果在则为重复消费。
(2) 版本号控制法,修改数据的时候,判断版本号,是一种乐观锁法则。缺点,生产者加版本号,改动大。
(3) 去重表(并发不大就用mysql、并发大就用redis)的方式。构建唯一性索引。更新数据的时候,如果重复,sql 会报错。redis 用setnx key value ,key 不存在就执行,存在就不能更新数据。
RabbitMQ部分
5. RabbitMQ 怎么确保消息不被重复消费
生产者幂等性;生产者、消费者、MQ之间的ack机制。+上面的
6. 消息丢失场景?如何解决?
场景
(1) 生产者丢失:没生产成功;生产成功了,服务端没接收到。
(2) broker:数据没有持久化,宕机,重启数据丢失;未能及时同步消息
(3) 消费者:网络异常波动,未能从服务端拉取成功消息;消费者宕机,消费者未能正常消费
如何解决
(4) 生产的时候丢失:没生产成功,进行生产者重试机制;事务回滚机制,确保提交成功。但是是同步阻塞,效率性能低。RabbitMQ 的异步confirm机制,如果RabbitMQ接受到这个消 息,写入磁盘,给生产者返回ack。
(5) 宕机的时候,RabbitMQ数据丢失:开启数据持久化(配置消息持久化、交换机持久化、队列持久化)。
(6) 消费者数据丢失:消费者确认机制。消费者消费成功,给rabbitMQ发消息,rabbitMQ进行删除,消费失败,发送失败消息,rabbitMQ会再次发送消息。
(7) 消费者失败处理。消费失败,rabbitMQ会重新发送,会陷入循环,配置重试机制,重试后还是失败要么重新入列、要么删除、要么放入新的队列,交由人工处理。
7. RabbitMQ 如何解决消息堆积
(1) 出现的原因:生产的速度远大于消费的速度;消费者出现异常或者业务复杂,导致消费时间过长;队列容量太小。
(2) 解决:控制生产与消费的速度;负载均衡,提高消费能力;优化消费者代码;控制消费者一次性取的数据;将无法处理的消息放在死信队列,防止阻塞;大消息分割片段处理。
8. RabbitMQ 的设计架构
生产者生产消息,建立长链接,链接到broker 服务,交换机将消息路由给队列,消费者拉取数据进行消费,消费成功后将数据删除。
9. rabbitMQ 交换机的类型
定向、广播、话题(类似于定向,区别可以支持通配符)
10. 延迟消息的实现
(1) 死信交换机。绑定一个正常交换机,不绑定消费,设置时间,达到一定时间没人消费,进入死信交换机,给死信交换机绑定消费者。实现延迟消费。
(2) 延迟消息插件。是对交换机做的改造,消息投递给交换机,交换机设置时间,时间到了,再将消息投递给队列。适合时间短的延迟场景,不适合并发+延迟长的场景,cpu占用高。
redis部分
11. 缓存更新策略
先更新数据库,再删除缓存。对失效的缓存会出现短暂的数据不一致的情况。单体系统,把缓存和更新数据放在一个事务中,保持其原子性。分布式系统,用分布式事务。
12. 缓存穿透
访问一个不存在的数据,缓存没有,数据库也没有,加大对数据库的压力,导致数据库奔溃。
解决方案
(1) 缓存空对象
缺点:大量空对象,可以设置过期时间减少大量空数据的缓存。数据不一致,访问为空,实际有数据,设置过期时间解决。
(2) 布隆过滤器,将所有数据库ID,进行哈希算法以二进制的形式存储在数组里。并不是百分百的准确,有误判情况。优点空间占用少。
13. 缓存雪崩
大量缓存同时失效或者redis服务宕机,导致大量请求到达数据库,给数据库造成压力。
解决方案
(1) 大量缓存同时失效。对数据设置随机过期时间。
(2) redis服务宕机。部署redis集群。
(3) 给缓存业务,降级限流。
(4) 给业务增加多级缓存。例如“浏览器缓存、Nginx服务缓存、redis缓存。
14. 缓存击穿
高并发的热点key失效,构建业务sql复杂,重建数据的时间较长,导致在这段时间内,获取数据的请求全跑到了数据库里。
解决方案
(1) 互斥锁
① 当请求获取数据,正在重建数据中,另外一个请求又来了,也去重建数据,导致大量资源全在重建同样的数据。
② 解决方案,第一次重建数据的过程中,开辟一个新线程,加锁,建完后,释放锁。原来的线程直接返回旧的数据,缺点暂时性的数据不一致。另外一个请求来了获取互斥锁,加睡眠时间,过一段时间再来获取互斥锁。
③ 缺点,所有请求都在等待数据重建完成。
④ 互斥锁用的是setnx, key 设置后,是不可被覆盖的。防止死锁要加过期时间释放锁;设置key-value、过期时间,要保持其原子性,写法:set key value nx ex 10
15. redis 支持事务吗?
支持事务,但是有局限性。如果执行某个命令失败,会继续往下执行,不会回滚。可以用lua 脚本来解决这个局限性。
16. redis 的过期策略、内存淘汰机制
(1) 有定期过期、惰性过期。定期过期,每隔一段时间,清理过期的数据。惰性过期,只有访问的时候才判断是否过期,不访问即使过期也不删除。
(2) 如果定期和惰性过期,都没有删除过期的数据,大量数据堆积,导致内存溢出。
(3) 内存淘汰机制,内存不足时,主动删除一些数据,释放空间。
(4) 淘汰机制的策略:选不常使用的;选快要过期的;从过期数据中,随机删除。
17. 什么是redis 的哨兵机制
(1) 搭建了redis的主从集群,master 挂了,需要从slever 中选一个当master。redis 哨兵的作用 就是自动恢复主从故障。
(2) 原理是,心跳机制,检测集群ping ,是否挂了
18. redis 的数据持久化方案
(1) RDB(redis data base)内存快照,全量备份。性能高,但是宕机,会丢失最近一次修改的的数据。触发方式:手动触发、自动触发。手动触发save, 阻塞redis进程,直到持久化数据完成;手动触发bgsave 主进程创建子进程,由子进程完成数据数据持久化,阻塞时间短。自动触发,shutdown 命令将redis 服务关闭,会触发自动备份。
(2) redis默认开启的是RDB持久化
(3) AOF(append only file)增量日志。存的是命令,数据更加完整可靠,缺点文件大,redis重启,数据恢复慢。
(4) 混合持久化:RDB+AOF
kafka部分
19. kafka 架构
(1) 可以设置多个topic,每个topic 下可以有多个分区, 每个分区是一个有序队列,数据进到队列,会分配一个有序的 offset。一台kafka服务就是一个broker,一个broker 可以容纳多个topic,
(2) broker 接收到生产者的发送消息,并向生产者发送确认消息,消费者消费成功后,给broker发送确认消息,broker更新偏移量,以便下次从正确的位置进行消费。
(3) ZooKeeper 协调kafka 组件之间的协作,例如主从晋升。后来引入Controller,承担ZooKeeper的部分功能,简化Kafka 集群的部署和管理。
20. kafka的工作流程
(1) producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader
(2) producer 将消息发送给该 leader
(3) leader 将消息写入本地 log
(4) followers 从 leader pull 消息
(5) 写入本地 log 后向 leader 发送 ACK
(6) leader 收到所有 ISR 中的 replication 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset)并向 producer 发送 ACK
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!