最近在对照 《Kafka 权威指南》 这本书, 整理kafka 的一些细枝末叶。随着文章发布,也会逐步完善一份思维导图。没有耐心的小伙伴可以直接跳到文章的最后看总结, 或者可以关注我新开的公众号:程序员BenJi, 回复 :kafka即可获取。
首先要创建一个生产者对象, 并设置一些属性. Kafka 生产者有3个必选的属性, **一定要记得, 不然面试官会觉得你很水!**分别为
# broker的地址清单,清单里不需要提供所有broker的地址,
# 生产者会从给定的broker 中查找 其他的broker信息.
bootstraps.servers
key.serializer
value.serializer
关于这些属性, 要知道不同属性会对系统有什么影响
比如 ack (0,1,-1) , retries ,超时时间 等, 详见 思维导图的 备注说明
这边因为篇幅有限, 讲解一下常常面试被问到的 ack属性
生产者发送消息出现异常后, 尝试重试的次数。当这个值设置大于1的时候,可能会引起顺序消费的问题。
我们都知道kafka 保证消息在同一个分区内是有序的,但是如果第一条消息发生重试, 第二条消息写入成功。随后第一条消息重试成功, 这样消息顺序就会发生错误。
要想知道如何解决由重试引发的消息顺序性问题,发送Kafka到公众号,获取思维导图源码,查看max.in.flight.request.per.connection属性设置吧, 哈哈!
这边因为篇幅有限, retries ,超时时间 等, 详见文末的 思维导图的 备注说明
/**
* 发送演示
* 发送消息必传参数:Topic, Value , 可选参数 partition , key
*/
// 最简单的直接发送
private void sendMessage(){
// 构造消息, 必穿参数Topic , Value
ProducerRecord record = new ProducerRecord<>("test-topic", 0, "key", "v");
try {
RecordMetadata recordMetadata = producer.send(record).get();
// 返回的元数据里面包含重要的 offset , partition 数据
recordMetadata.offset();
recordMetadata.partition();
} catch (Exception e) {
e.printStackTrace();
}
}
// 异步发送, 需要提供回调
private void sendMessageAsyn(){
ProducerRecord record = new ProducerRecord<>("test-topic", 0, "key", "v");
producer.send(record,new CallBackDemo());
}
// 实现kafak 的 CallBack 接口
class CallBackDemo implements Callback{
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if(exception != null){
exception.printStackTrace();
}
}
}
kafka 的分区, 具体指的是消息分配到哪一个partition.
/**
* 自定义 Taobao分区器
* 分区器需要实现 Kafka 的 Partitioner 接口
* 重写 partion 方法
*/
public class BananaPartitioner implements Partitioner{
// 演示了 key == Taobao 的消息, 总是分配到最后一个分区,
// 其他消息 散列到除了最后一个分区之外的其他分区
// 需要返回分区 idx
@Override
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List partitionInfos = cluster.partitionsForTopic(topic);
int lastPartitionNumber = partitionInfos.size();
// 如果key == banner , 总是分配到最后一个分区,
if ("Taobao".equalsIgnoreCase((String) key)){
return lastPartitionNumber;
}
// 其他消息 散列到除了最后一个分区之外的其他分区
return (Math.abs(Utils.murmur2(keyBytes))%(lastPartitionNumber - 1));
}
@Override
public void close() {
}
@Override
public void configure(Map configs) {
}
}
下面是我整理的思维导图,源文件请关注我新建的公众号: 程序员BenJi , 回复 kafka 即可获取:
定期分享优质的知识思维导图,帮助大家建立结构化的知识体系,欢迎关注~