尽快进入正题。
0.一点题外话
Kafka名字的由来,是Kafka之父Jay Krept很喜欢作家Franz Kafka。Kafka和很多消息中间件一样,支持两种消息模型:
0.1.点对点模型
包含消息队列(queue)、发送者(sender)和接受者(receiver)。流程就是发送者将消息发送到队列的指定位置,接收者从指定位置获取消息。一旦消息被消费,就从消息列表中删除。
0.2发布-订阅模型
主要包含主题(topic)、生产者(producer)和消费者(consumer)等,也是线上生产常用的模型。本文及后文都基于此模式展开讨论,本文先从生产者讲起。
1.生产者流程图
由图我们可以首先得知,kafka消息至少包含主题topic、分区partition、消息key、消息value和时间戳timestamp五个元素。主要疑问点会在主题topic和分区partition的含义。
topic是储存一类消息的逻辑集合,物理上并不会存储到磁盘。而一个topic会包含多个partition,可在创建topic时指定数量。partition是真实物理存储的,一个partition对应kafka broker上一个文件夹,用于存储topic的一部分消息。同一个topic的多个partition,可以分散保存到多个broker上。这部分内容目前知识初步了解,详细讲述我们放到下文讲broker中。
那么作为生产者生产的同一topic的消息,我们怎么知道它会路由到哪个partition上呢?我们在生产消息时可以直接指定partition,如果没有指定,那么就用到了图中的partitioner分区器,它会根据消息key的hash值路由到不同的partition上(Math.abs(key.hashcode())%partitionNumbers)。如果消息没有消息key,则采用轮询算法。我们也可以自定义分区器,实现Partitioner接口重新实现parition方法即可。
2.消息发送方式
共3种:
2.1发送后忘记(fire and forget)
没什么好说的,字面意思。
2.2同步发送
返回future对象调用get()方法等待。
producer.sendRecord().get(),注意处理异常。
2.3异步发送
send()后注册回调函数。
producer.send(record, new Callback() { public void onCompletion(RecordMetadata metadata, Exception e) {} });
broker返回的参数有metadata和e,哪个不为null,则说明消息发送结果是哪种情况。
如果消息发送失败了,返回的异常也分两种情况,一种是可重试异常,另一种是不可重试异常。
常见可重试异常:
LeaderNotAvailableException:在分区lead选举期间返回(此概念会在后文ISR一节中讲)
NotControllerException:controller选举期间返回(此概念会在后文controller一节中讲)
NetWorkException:网络异常
3.生产者参数
acks
0:发送消息不等待结果;
all或-1:发送消息后broker将消息写入本地日志,同时ISR中所有副本都写入本地日志才返回成功;
(默认)1:发送消息broker将消息写入本地日志即返回。
buffer.memory
producer缓存消息缓存池大小,默认33554432。producer先将消息发送到缓存池,由另一个线程读取消息再真正发送
compression.type
是否压缩消息,默认none。其他枚举:GZIP、Snappy、LZ4
retries
消息发送瞬时故障重试次数,默认0。主要可通过retry.backoff.ms设置重试间隔。
batch.size
producer将发送同一partition的消息放入一个batch中,理论上batch满即发送(如配置了linger.ms则每linger.ms发送一次)。默认大小16384(16KB)。
max.request.size
producer最大发送消息大小,默认1048576。
request.timeout.ms
发送超时时间,默认30s。
下文讲述broker: