Kafka学习笔记一(消息队列)
众所周知,敲代码写需求的时候,最常见的就是给你加需求,或者给你改需求这种令人头疼的事。
当系统B要接入你的系统A获取数据时,要改代码,系统C要获取数据时,也要改代码;如果后面还有其他系统要来获取数据,这样一直改吗?
当然不,消息队列就可以解决这个问题。
相比起传统模式那样系统间耦合度强的情况,MQ模式可以直接将你的消息写入消息队列,让需要获取消息的系统自己从消息队列中订阅,系统A不需要再做任何修改就可以实现业务了,轻松降低模块之间的耦合。
另外,传统模式里一些非必要的业务逻辑用同步方式运行太过麻烦,使用MQ直接将消息写入消息队列中,非必要逻辑就可以以异步方式运行,大大加快了响应速度,提高用户体验。
在此之外,MQ还有削峰填谷的功能,相较起传统模式并发量激增的时候,所有请求会直接怼到存储服务造成服务异常,MQ会将请求先写入消息队列,然后按照数据库等存储服务能处理的并发量从消息队列中慢慢拉取消息,在高峰期可以避免系统瘫痪。
但可惜的是,MQ同样存在缺点,MQ作为一个中间件,增加它之后会增加依赖服务,需要考虑MQ瘫痪的情况,导致系统可用性降低;另外系统的复杂性也提高了,需要考虑消息丢失、消息重复消费、消息传递的顺序性等;最后还要将主业务和从属业务做一致性的处理。
消息系统原理
一个消息系统负责将数据从一个应用传递到另外一个应用,应用只需关注于数据,无需关注数据在两个或多个应用间是如何传递的。
数据单元
-
关联到业务对象
-
数据单元必须关联到某种业务对象
-
如果是爬虫,数据单元是一个网页;如果是一个日志,那么就可能是用户的一次访问
-
-
完整性
- 在数据传输过程中,要保证该数据单元的完整(要不传输完成,要不传输失败)
-
独立性
-
各个数据单元之间没有互相依赖(前一条数据与后一条数据没有关联)
-
某个数据单元传输失败不该影响已经完成传输的单元,也不应影响尚未传输的单元
-
-
颗粒度
-
数据单元需要关联到某种业务对象。那么数据单元和业务对象应该处于的关系(一对一?一对多)如果颗粒度过小会增加数据传输的次数
-
如果颗粒度过大会增加单个数据传输的时间,影响后期消费
-
点对点消息传递
-
在点对点消息系统中,消息持久化到一个队列中。此时,将有一个或多个消费者消费队列中的数据。但是一条消息只能被消费一次。
-
当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。
-
该模式即使有多个消费者同时消费数据,也能保证数据处理的顺序。
发布订阅消息传递
-
在发布-订阅消息系统中,消息被持久化到一个topic中。
-
消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除。
-
在发布-订阅消息系统中,消息的生产者称为发布者,消费者称为订阅者。
-
Kafka 采取拉取模型(Poll),由自己控制消费速度,消费者可以按照任意的偏移量进行消费。
-
当发布者消息量很大时,显然单个订阅者的处理能力是不足的。实际上现实场景中是多个订阅者节点组成一个订阅组负载均衡消费 Topic 消息即分组订阅,这样订阅者很容易实现消费能力线性扩展。
消息传递对比
序号 | 特点 | 点对点消息传递 | 发布订阅消息传递 |
---|---|---|---|
1 | 基本的 | 一对一消息传递。 发送到队列中的消息只能有一个接收者接收 | 一对多消息传递。 发送给该主题的消息可以被多个使用者接收 |
2 | push推 pull拉 | 一般使用拉取机制,客户端每次都需要轮询消息 | 一般采用基于推送的模型,消息可以广播给所有消费者 |
3 | offset | 确认是强制性的 | 确认是可选的 |
4 | 时间依赖性 | 发送方和接收方之间没有时序依赖性。 | 发布者和订阅者之间存在时间依赖性。 |
5 | 负载均衡 | 可靠的负载均衡消息传递模型 | 当发布一个消息,所有订阅者都能得到一个消息的拷贝;需要消息中间件自己去实现负载均衡 |