1.0.1 主要功能与应用场景
Kafka 作为一个分布式流式处理平台,提供了三个关键的功能:
其主要的应用场景:
1.0.2 相比于其他 MQ 的优缺点
Kafka的设计目标是高吞吐量,所以他的一些特性都和这个目标相关,如
Kafka 使用的是顺序 I/O,为保证顺序,Kafka强制点对点的按顺序传递消息,这意味着,一个 consumer 在分区中只有一个位置。
Kafka 不保存每个消息的状态,不提供以随机访问的形式更新消息的状态,而是使用 offset 划分使用和未使用的消息。
Kafka支持点对点的批量消息传递。
Kafka的消息存储使用了 OS pagecache(页缓存,page cache的大小为一页,通常为4K,用于缓存文件的逻辑内容),提高读写文件时的操作效率。
和其他消息队列的对比:
消息队列 / 特性 | MsgBroker | Kafka | RabbitMQ | ActiveMQ | RocketMq |
---|---|---|---|---|---|
消息推送模式 | push | pull | 多协议,均支持 | 多协议,均支持 | 多协议,均支持 |
持久化能力 | DB | 磁盘(文件系统page cache) | 磁盘 | 磁盘 | 磁盘 |
事务型消息 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
消息是否有序 | 无序 | 有序,采用追加写、offset读 | 有序 | 有序 | 有序 |
数据可靠性 | 可靠 | replica机制,容错容灾.(依赖ZK中维护的元数据来实现的 ) | 保证数据不丢,slave备份 | 可靠,master/slave | 可靠,同步刷盘,同/异步复制 |
应用场景 | 金融及支付高可靠性,重点强调事务型 | 高吞吐量,分布式规模流式数据处理 | 高可用 | 高可用 | 高吞吐,高可靠 |
1. Partition(分区) :
属于 Topic 的一部分。一个 Topic 可以有多个 Partition(即多副本机制) ,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上。
kafka 中 ,Producer 在发布消息时可以选择指定要发送的 Partition,或者使用默认的分区策略让 Kafka 自动选择 Partition。
多副本机制是什么?
Kafka 为 Partition 引入了多副本(Replica)机制。Partition 中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。
生产者和消费者只与 leader 副本交互。
follower 保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。
多分区 以及多副本机制有什么好处呢?
2. Consumer Group
ConsumerGroup 是用来维护一组相同消费者的实例。一个 Consumer Group 可以订阅多个 Topic。
每个 Partition ,在同一个 Consumer Group 中,一定 会有对应的消费者
一个topic下有多个Partition时,如何保证Consumer消费的顺序性?
Broker 中有如下一些概念:
Kafka 通过ISR的同步机制及优化策略,用 HW & LEO 的方式很好地确保了数据不丢失以及吞吐率。而ISR的管理最终都会反馈到 ZK 上。
发布-订阅模型:
发布订阅模型(Pub-Sub) 使用主题(Topic) 作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息 通过 Topic 传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的。
在发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样(即 Producer和Consumer 一对一消费)。
JMS 和 AMQP 属于消息服务领域权威组织所做的相关的标准。
1. 顺序写入
磁盘的读写分为两种方式,顺序IO和随机IO,顺序IO速度和内存基本一致。
kafka 采用顺序IO记录 Producer 发送的消息到磁盘,Consumer 通过和 ZK 共同维护的 offset 来记录读取到的位置。
2. Memory Mapped Files
和Java NIO 对文件的操作相同,使用 虚拟内存完成文件到磁盘的映射,需要对文件进行IO操作时,直接操作内存即可,避免了文件在用户空间到内核空间的来回拷贝。
3. 使用 Sendfile 完成“零拷贝”
零拷贝操作方式下,使用硬件(DMA)的方式完成文件拷贝,不需要拷贝文件到用户空间,所以不消耗 CPU 资源,IO效率提高。关于 操作系统中零拷贝 的更多介绍。
4. 数据压缩与批量发送
在 Producer 端指定压缩算法(CompressionType)进行压缩,然后发送到 Broker(Broker为了校验数据正确性会解压核对数据),Consumer 读取数据后进行解压。
数据批量发送,主要通过 buffer.memory、batch.size、linger.ms 参数来控制批量发送数据的大小,充分利用网络传输效率。
kafka中,不同版本提供的用户认证有如下四种:
SASL/GSSAPI(kerberos):kafka0.9版本推出,即借助kerberos实现用户认证,如果公司恰好有kerberos环境,那么用这个是比较合适的。
SASL/PLAIN:kafka0.10推出,用户名 / 密码明文传输,不能动态添加用户,不建议生产环境使用。
SASL/SCRAM:kafka0.10推出,全名Salted Challenge Response Authentication Mechanism。认证通过sha256等哈希算法,提高了安全性;可以动态添加用户;缺点是某些语言的客户端不支持该方式认证。
SASL/OAUTHBEARER:kafka2.0推出。
一条消息的流转,会经过 Producer / Broker / Consumer ,所以消息的丢失,可能出现在这三个位置,我们分情况讨论。具体的实现,可参考:消息可靠性方案的实现
1. Producer 是否等待 TopicLeader 的消息回执(ack:默认为1)
acks = 1: Leader 写入消息到本地日志,则请求被认为成功。如果此时 Leader 应答请求后挂掉了,消息会丢失。
acks = 0: Producer 执行发送请求后立即返回,不等待 Leader 的确认,消息会丢失。
acks = -1:分区 Leader 必须等待消息被成功写入到所有的ISR副本(In-Sync Replace)中才认为请求成功。该种情况下配合 Producer 的消息重试机制 来保证消息可靠性。
2. Producer 进程意外停止导致的消息丢失
为了提升发送效率,减少IO次数,Producer 在发送数据时,可以将多个消息缓存在本地 buffer 中进行合并后发送(主要通过在 KafkaProducer 对象中配置 buffer.memory 、batch.size 、linger.ms 参数来控制)。
可以看到存在本地 Buffer 的消息,在 Producer 进程突然结束后,会出现消息丢失的情况。如果有必要,可以适当调小上面提及的参数,使发送频率变高,减少丢失数据。
3. Producer 网络问题导致的消息丢失
由于 Producer 的网络问题,在经过 retries 和 retry.backoff.ms 后,依然发送失败,那么将使用其他的方案进行重试发送。
1. Leader 切换
Broker 的消息丢失,最容易出现在 Partition Leader 切换时,我们可以通过如下的一些参数来保证 Broker 消息的可靠性:
1. Consumer 按时间间隔自动提交 offset
使用 enable.auto.commit 和 auto.commit.interval.ms 控制异步 offset 提交,可能会出现消息丢失或者重复消费。
2. Consumer 手动提交 offset
手动提交 offset 并不能 100% 保证消息一定不丢失,(比如,消费某几条消息失败后,导致 offset 没有提交,那么默认情况下,消费者会进行重试,如果重试还是失败,消费者将继续消费下一批消息,如果后续的消费成功提交 offset ,那么消费失败的消息将会丢失),需要配合异常重试、死信队列、死信队列消息处理机制,才能保证 Consumer 100% 不丢失消息。
消息不唯一,可能会出现在 Producer 端多次发送,在 Consumer 端多次消费,下面分情况讨论:
1. Producer 客户端通过 Producer ID(PID)和 Sequence Number 保证消息唯一
0.11.0 后的版本,引入了 Producer ID(PID)和 Sequence Number 实现 Producer 的幂等,保证一个消息只被投递一次。
2. Consumer 添加持久化的去重判断
Consumer 消息的消费和业务紧密相关,所以需建立持久化的唯一标识,来避免消息重复消费。
Kafka 只能为我们保证每个 Partition(分区) 中的消息有序, 同一个 Topic 下的多个 Partition 内的消息在消费时,不保证有序性.
为了保证消息的顺序消费, 有如下几种方案: