使用mq主要原因:
1,解耦,主要是发布订阅模式,系统间解耦
2,异步,主要是串行改成并行,不需要等待,比如:发送邮件服务
3,削峰,主要是突然涌入大量数据,导致数据库挂掉。可以主动去拉数据。
kafka基本概念
kafka主要用于,日志储存,顺序非常严格
数据持久化,动态扩容,支持事务 ,消息自动平衡
架构基本认识:由多个Broker组成,每个Broker是一个节点,创建一个topic,一个topic分成多个partition,每个partition分布在不同的节点Broker上面
topic是逻辑概念,topic包含一个 或多个partition,不同的partition,采用顺序写入磁盘。这是重要的速度
Broker物理概念,kafka集群每个服务器节点
partition是物理逻辑,一个文件夹
比如我们给topic=test发送3条消息,可能分布在3个broker节点,每个节点一个partition上面
kafka是高可用
有副本,如果主节点挂了,还有副本,只有主节点负责读写操作,如果主节点挂了,会自动选举副节点作为主节点,达到高可用
如何实现高效
1.将写磁盘的过程变为顺序写,可极大提高对磁盘的利用率。
Kafka的整个设计中,Partition相当于一个非常长的数组,而Broker接收到的所有消息顺序写入这个大数组中。同时Consumer通过Offset顺序消费这些数据,并且不删除已经消费的数据,从而避免了随机写磁盘的过程。
由于磁盘有限,不可能保存所有数据,实际上作为消息系统Kafka也没必要保存所有数据,需要删除旧的数据。而这个删除过程,并非通过使用“读-写”模式去修改文件,而是将Partition分为多个Segment,每个Segment对应一个物理文件,通过删除整个文件的方式去删除Partition内的数据。这种方式清除旧数据的方式,也避免了对文件的随机写操作。
2.充分利用Page Cache
activemq
两种模式
首先看一下发布/订阅模式(即观察者模式),观察者模式
还有是,点对点P2P
RabbitMQ
不是分布式的,但是可以做集群达到高可用。
三种模式:单机模式/普通集群模式/镜像集群模式
普通集群模式:每个节点存储索引元数据,但是真实数据只存在一个节点。消费的时候如果没有连接到数据的机器,会真是存储数据的节点拉数据。缺点:可能会存在大量数据传输,不是高可用!!可以提高吞吐量!!
镜像集群模式:高可用,每个节点都有queue的完整镜像,包含数据。消费的时候任何一个节点都有数据,即使挂了一个节点也不丢失数据。缺点:不是分布式
面试题:
重复消费问题?
kafka的消息是有offset类似于唯一标识的,消费也是根据offset来顺序消费,消费后会提交offset,zk会记录消费进度,如果消费者重启了,不需要重头发送,zk是知道进度的。还是会重复的。
如何保证幂等性?
也就是保证数据库不能有重复数据,借助redis或者set来判断
消息丢失如何处理?消息的可靠性传输,就是发出去了,mq没收到,如何处理?
rabbitmq消息丢失三种可能性:1.生产者->mq 2.mq自身,在缓存中丢失 3.消费者 都可能出现
解决方案:
生产者:1.rabbitmq是可以开启事务的,保证生产者-》mq 是一个事务,可以回滚(事务是同步的,导致吞吐量下降,不推荐)
生产者:2. 开启confirm回调机制,发送成功或者失败,mq会回调生产者
mq:3.开启持久化,这样就不会在内存丢失了,重启也不会丢失(内存还没持久化到硬盘的时候,挂了,还是会丢失部分数据)
消费端丢失:4.关闭自动ack ,改成手动的。(mq会消费的时候,自动给发消息说已经完成,实际有可能挂了,改成成功后再手动)
kafka的解决方案:
消费端丢失:消费者自动提交offset,kafka以为消费好了实际上未消费失败了,关闭自动提交offset,改成手动提交,就不会丢失了
生产者丢失: Kafka 的 leader 机器宕机了,将 follower 切换为 leader 之后,就会发现说这个数据就丢了。
所以此时一般是要求起码设置如下 4 个参数:
- 给 topic 设置 replication.factor 参数:这个值必须大于 1,要求每个 partition 必须有至少 2 个副本。
- 在 Kafka 服务端设置 min.insync.replicas 参数:这个值必须大于 1,这个是要求一个 leader 至少感知到有至少一个 follower 还跟自己保持联系,没掉队,这样才能确保 leader 挂了还有一个 follower 吧。
- 在 producer 端设置 acks=all,这个是要求每条数据,必须是写入所有 replica 之后,才能认为是写成功了
- 在 producer 端设置 retries=MAX(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了。
生产环境就是按照上述要求配置的,这样配置之后,至少在 Kafka broker 端就可以保证在 leader 所在 broker 发生故障,进行 leader 切换时,数据不会丢失。
保证消息的顺序消费问题?
rabbitmq :一个queue,多个消费者消费数据会出现顺序不一致,
解决方案:拆分多个queue队列,需要排序的消息都放到一个队列,这样就只给一个消费者,一定是顺序的
kafka:
partition中的数据是顺序的,放数据指定key,就会放到一个partition中
一个消费者只能消费一个partition,所以一定是顺序的
但是,如果一个消费者有多个线程并发处理,结果也会乱,如何处理?
中间在加一层内存队列,同样的key放入内存队列。。
消息积压如何处理?
kafka消费者故障,就会出现消息积压,增加消费者服务器。。
rabbitmq 可以设置过期时间,积压时间长就会丢失,最好不设置。
让你设计一个消息队列,考虑哪些?
1.支持分布式,可扩容
2.考虑持久化,要不要落入磁盘,防止数据丢失
3.高可用,挂了选举新节点,数据迁移等
4.重复消费/顺序消费/丢失数据,都需要考虑