我是kafka的新手,如果我听起来很愚蠢,但我到目前为止所理解的是道歉 是..消息流可以定义为主题,如类别。每个主题都是分开的 进入一个或多个分区(每个分区可以有多个副本)。所以他们并行行动
来自卡夫卡main site他们说
生产者能够选择将哪个消息分配给主题中的哪个分区。 这可以通过循环方式完成,只是为了平衡负载,或者可以根据一些语义分区功能(比如根据消息中的某些键)来完成。
这是否意味着在消费时我将能够从特定分区中选择消息偏移量? 运行多个分区时,是否可以从一个特定分区中选择,即分区0?
在卡夫卡0.7 quick start他们说
发送带分区键的消息。具有相同密钥的消息将发送到同一分区。
创建生产者时可以提供密钥,如下所示
ProducerData<String, String> data = new ProducerData<String, String>("test-topic", "test-key", "test-message");
producer.send(data);
现在如何根据此密钥使用消息?在Kafka制作时使用此键的实际影响是什么?
在0.8beta中创建生产者时,我们可以通过配置文件提供分区器类属性。 可以创建自定义分区器类来实现kafka分区器接口。 但有点混淆它是如何工作的。 0.8 doc也没有解释太多。有什么建议或者我错过了什么?
答案 0 :(得分:16)
这是我到目前为止所发现的......
通过实现kafka Partitioner接口来定义我们自己的自定义分区器类。实现的方法将有两个参数,首先是我们从生产者提供的密钥,然后是可用的分区数。因此,我们可以定义自己的逻辑来设置消息的哪个键进入哪个分区。
现在在创建生成器时,我们可以使用“partitioner.class”属性
指定我们自己的分区器类 props.put("partitioner.class", "path.to.custom.partitioner.class");
如果我们不提及它,那么Kafka将使用其默认类并尝试在可用分区之间均匀分发消息。
另请告知Kafka如何序列化密钥
props.put("key.serializer.class", "kafka.serializer.StringEncoder");
现在,如果我们使用生产者中的密钥发送一些消息,消息将被传递到特定分区(基于我们在自定义分区器类上编写的逻辑),而在消费者(SimpleConsumer)级别,我们可以指定分区检索特定消息。
如果我们需要将String作为键传递,则应该在自定义分区器类中处理相同的内容(获取键的哈希值,然后取前两位数等)
答案 1 :(得分:15)
Kafka中的每个主题都分为许多分区。分区允许并行消耗,从而提高吞吐量。
生产者使用Kafka生产者客户端库将消息发布到主题,该库使用分区程序在可用分区之间平衡消息。生产者连接到的代理负责使用zookeeper中的分区所有者信息将消息发送到作为该分区的领导者的代理。消费者使用Kafka的高级消费者库(处理经纪人领导者变更,管理zookeeper中的偏移信息并隐含地计算分区所有者信息等)来使用来自流中分区的消息;根据消费者选择创建消息流的方式,每个流可以映射到几个分区。
例如,如果一个主题有10个分区,并且3个消费者实例(C1,C2,C3按此顺序启动)都属于同一个消费者组,我们可以使用不同的消费模型,允许读取并行度,如下所示< / p>
每个消费者使用一个流。 在此模型中,当C1启动时,主题的所有10个分区都映射到同一个流,并且C1开始从该流中消耗。当C2启动时,Kafka重新平衡两个流之间的分区。因此,每个流将分配到5个分区(取决于重新平衡算法,它可能也是4对6)并且每个消费者从其流消耗。类似地,当C3启动时,分区再次在3个流之间重新平衡。请注意,在此模型中,当从分配给多个分区的流中消费时,消息的顺序将在分区之间混乱。
每个消费者使用多个流(比如C1使用3,C2使用3,C3使用4)。 在此模型中,当C1启动时,所有10个分区都分配给3个流,C1可以使用多个线程同时从3个流中消耗。当C2启动时,分区在6个流之间重新平衡,类似地,当C3启动时,分区在10个流之间重新平衡。每个消费者可以同时从多个流中消费。请注意,此处的流和分区数相等。如果流的数量超过分区,则某些流将不会获得任何消息,因为它们不会被分配任何分区。
答案 2 :(得分:6)
是的,您可以从消费者的某个特定分区中选择消息,但如果您希望动态识别该消息,那么它取决于您在生产者中实施Partitioner Class的逻辑。
有两种消费方式。一个是使用Zookeeper Host,另一个是静态主机。 Zookeper主机使用来自所有分区的消息。但是,如果您使用的是静态主机,则可以为代理提供需要使用的分区号。
请查看以下Kafka 0.8的例子
<强>生产者强>
KeyedMessage<String, String> data = new KeyedMessage<String, String>(<<topicName>>, <<KeyForPartition>>, <<Message>>);
分区类
public int partition(Object arg0, int arg1) {
// arg0 is the key given while producing, arg1 is the number of
// partition the broker has
long organizationId = Long.parseLong((String) arg0);
// if the given key is less than the no of partition available then send
// it according to the key given Else send it to the last partition
if (arg1 < organizationId) {
return (arg1 - 1);
}
// return (int) (organizationId % arg1);
return Integer.parseInt((String) arg0);
}
因此,partiotioner类根据您的逻辑决定在何处发送消息。
消费者(PN:我使用过Storm Kafka 0.8集成)
HostPort hosts = new HostPort("10.**.**.***",9092);
GlobalPartitionInformation gpi = new GlobalPartitionInformation();
gpi.addPartition(0, hosts);
gpi.addPartition(2, hosts);
StaticHosts statHost = new StaticHosts(gpi);
SpoutConfig spoutConf = new SpoutConfig(statHost, <<topicName>>, "/kafkastorm", <<spoutConfigId>>);