Apache kafka KafKa分区器类,使用键将消息分配给主题内的分区

Apache kafka KafKa分区器类,使用键将消息分配给主题内的分区,apache-kafka,Apache Kafka,我是卡夫卡的新手,所以道歉,如果我听起来很愚蠢的话,但到目前为止我所理解的是什么 是消息流可以定义为主题,类似于类别。每一个话题都是分开的 进入一个或多个分区(每个分区可以有多个副本)。所以它们是并行的 他们说卡夫卡 生产者可以选择将哪个消息分配给主题中的哪个分区。 这可以简单地以循环方式来平衡负载,也可以根据某种语义划分函数(比如基于消息中的某个键)来完成 这是否意味着在消费时,我将能够选择来自特定分区的消息偏移量? 在运行多个分区时,是否可以从一个特定分区(即分区0)中进行选择 在卡夫卡0.

我是卡夫卡的新手,所以道歉,如果我听起来很愚蠢的话,但到目前为止我所理解的是什么 是消息流可以定义为主题,类似于类别。每一个话题都是分开的 进入一个或多个分区(每个分区可以有多个副本)。所以它们是并行的

他们说卡夫卡

生产者可以选择将哪个消息分配给主题中的哪个分区。 这可以简单地以循环方式来平衡负载,也可以根据某种语义划分函数(比如基于消息中的某个键)来完成

这是否意味着在消费时,我将能够选择来自特定分区的消息偏移量? 在运行多个分区时,是否可以从一个特定分区(即分区0)中进行选择

在卡夫卡0.7中,他们说

使用分区密钥发送消息。具有相同密钥的消息被发送到同一分区

创建制作人时可以提供密钥,如下所示

    ProducerData<String, String> data = new ProducerData<String, String>("test-topic", "test-key", "test-message");
    producer.send(data);
ProducerData data=新的ProducerData(“测试主题”、“测试密钥”、“测试消息”);
生产者。发送(数据);
现在,如何使用基于此密钥的消息?在卡夫卡制作时使用此键的实际影响是什么

在0.8beta中创建producer时,我们可以通过配置文件提供partitioner类属性。 可以通过实现kafka分区器接口创建自定义分区器类。
但我有点困惑它到底是如何工作的。0.8doc也没有太多解释。有什么建议或者我遗漏了什么吗?

这是我目前发现的

通过实现kafka分区器接口定义我们自己的自定义分区器类。实现的方法将有两个参数,第一个是我们从生产者提供的密钥,第二个是可用分区的数量。所以我们可以定义自己的逻辑来设置消息的哪个键去哪个分区

现在,在创建producer时,我们可以使用“partitioner.class”属性指定我们自己的partitioner类

    props.put("partitioner.class", "path.to.custom.partitioner.class");
如果我们不提及它,那么Kafka将使用其默认类,并尝试在可用分区之间均匀地分布消息

同时通知卡夫卡如何序列化密钥

    props.put("key.serializer.class", "kafka.serializer.StringEncoder");
现在,如果我们在producer中使用一个键发送一些消息,那么消息将被传递到一个特定的分区(基于我们在自定义partitioner类上编写的逻辑),并且在consumer(SimpleConsumer)级别,我们可以指定用于检索特定消息的分区

如果我们需要将字符串作为键传递,那么同样的内容应该在自定义分区器类中处理(获取键的哈希值,然后获取前两位数字等)

这是否意味着在使用时,我可以选择来自特定分区的消息偏移量?在运行多个分区时,是否可以从一个特定分区(即分区0)中进行选择? 是的,您可以从使用者的一个特定分区中选择消息,但如果您希望动态标识该分区,则它取决于您在生产者中实现分区器类的逻辑

现在,如何使用基于此密钥的消息?在卡夫卡制作时使用此键的实际影响是什么? 有两种方式使用消息。一个是使用Zookeeper主机,另一个是静态主机。Zookeper主机使用来自所有分区的消息。然而,若您使用的是静态主机,那个么您可以向代理提供需要使用的分区号

请查看下面的卡夫卡0.8示例

制作人

KeyedMessage<String, String> data = new KeyedMessage<String, String>(<<topicName>>, <<KeyForPartition>>, <<Message>>);
KeyedMessage数据=新的KeyedMessage(,);
分区类

   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);
    }
public int分区(对象arg0,int arg1){
//arg0是生成时给定的键,arg1是
//代理拥有的分区
long organizationId=long.parseLong((字符串)arg0);
//如果给定的密钥小于可用分区数,则发送
//它根据给定的密钥将其发送到最后一个分区
如果(arg1<组织ID){
返回(arg1-1);
}
//返回(int)(组织ID%arg1);
返回整数.parseInt((字符串)arg0);
}
因此PartitionOner类根据您的逻辑决定将消息发送到哪里

消费者(请注意:我使用了Storm Kafka 0.8集成)

HostPort hosts=新的主机端口(“10.*.*.**”,9092);
GlobalPartitionInformation gpi=新的GlobalPartitionInformation();
gpi.addPartition(0,主机);
添加分区(2个,主机);
StaticHosts statHost=新的StaticHosts(gpi);
喷动配置喷动配置=新喷动配置(statHost,“/Kafkastrom”);

卡夫卡中的每个主题都分为许多分区。分区允许并行消耗,从而提高吞吐量

Producer使用Kafka Producer客户端库将消息发布到主题,该库使用分区器跨可用分区平衡消息。生产者连接到的代理负责使用zookeeper中的分区所有者信息将消息发送给作为该分区的领导者的代理。消费者使用Kafka的高级消费者库(处理代理负责人的更改、管理zookeeper中的偏移量信息以及隐式计算分区所有者信息等)来消费流中分区的消息;根据使用者选择如何创建消息流,每个流可以映射到几个分区

例如,如果一个主题有10个分区,3个使用者实例(C1、C2、C3按该顺序开始)都属于同一使用者组,那么我们可以有不同的使用者模型,允许如下所示的读取并行性

每个消费者使用一个流。
        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>>);