为什么要在Kafka上使用Avro-如何处理POJO

时间:2019-01-15 09:18:00

标签: java apache-kafka avro confluent-schema-registry

我有一个春季应用程序,是我的kafka制作人,我想知道为什么avro是最好的选择。 我读到了它的全部内容,但是为什么我不能序列化我用杰克逊创建的POJO并将其发送给kafka?

之所以这样说,是因为avro产生的POJO并不那么直接。 最重要的是,它需要Maven插件和一个.avsc文件。

例如,我在我的kafka制作人上创建了一个名为用户的POJO:

public class User {

    private long    userId;

    private String  name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

}

我序列化它,并将其发送到我在kafka中的用户主题。然后,我有一个消费者,该消费者本身具有POJO用户并反序列化消息。 这是空间问题吗?以这种方式进行序列化和反序列化还不是更快吗?更不用说维护架构注册表的开销。

3 个答案:

答案 0 :(得分:4)

这是速度和存储的问题。序列化数据时,通常需要传输实际的模式,因此,这会导致有效负载大小增加。

                            Total Payload Size
+-----------------+--------------------------------------------------+
|     Schema      |                 Serialised Data                  |
+-----------------+--------------------------------------------------+

模式注册表提供了用于模式和元数据的集中式存储库,以便所有模式都在中央系统中注册。这种集中式系统使生产者可以仅包括模式的ID,而不是完整的模式本身(以文本格式)。

                      Total Payload Size
+----+--------------------------------------------------+
| ID |                 Serialised Data                  |
+----+--------------------------------------------------+

因此,序列化变得更快。

此外,通过架构注册表版本控制,可以实施数据策略,这可能有助于防止较新的架构破坏与现有版本的兼容性,这可能会导致停机或管道中的其他任何重大问题。


this article by Confluent中详细说明了Schema Registry的其他优点。

答案 1 :(得分:2)

您不需要AVSC you can use an AVDL file,它基本上与仅包含字段的POJO相同

@namespace("com.example.mycode.avro")
protocol ExampleProtocol {
   record User {
     long id;
     string name;
   }
}

其中,当使用Maven插件的idl-protocol目标时,将为您创建此AVSC,而不是您自己编写。

{
  "type" : "record",
  "name" : "User",
  "namespace" : "com.example.mycode.avro",
  "fields" : [ {
    "name" : "id",
    "type" : "long"
  }, {
    "name" : "name",
    "type" : "string"
  } ]
}

它还将在您的类路径中放置一个SpecificData POJO User.java,供您在代码中使用。


如果您已经拥有POJO,则无需使用AVSC或AVDL文件。有一些库可以转换POJO。例如,您的can use Jackson(不仅适用于JSON),仅需要为Kafka创建一个JacksonAvroSerializer,或者查找是否存在。

Avro也有built-in library based on reflection


这个问题-为什么选择Avro(对于Kafka)?

嗯,拥有一个架构是一件好事。考虑一下RDBMS表,您可以解释该表,然后看到所有列。移至NoSQL文档数据库,它们实际上可以包含任何内容,这就是Kafka的JSON世界。

让我们假设您在Kafka集群中有一些消费者,他们不知道主题中的内容,他们必须确切地知道是谁/主题产生了什么。他们可以尝试使用控制台使用者,如果它是JSON之类的纯文本格式,那么他们必须找出他们感兴趣的某些字段,然后一次又一次地执行类似HashMap之类的.get("name")操作,然后才能运行字段不存在时的NPE。使用Avro,您清楚地定义默认值和可为空的字段。

不需要使用,但是它为RDBMS类推提供了explain topic语义类型。这也使您无需将架构与每条消息一起发送,也省去了Kafka主题上额外带宽的开销。该注册表不仅对Kafka有用,因为它可用于Spark,Flink,Hive等,用于围绕流数据提取的所有数据科学分析。


假设您确实要使用JSON,然后try using MsgPack instead,您很可能会发现Kafka吞吐量有所增加,并节省了代理上的磁盘空间


您还可以使用其他格式,例如Protobuf或Thrift,as Uber has compared

答案 2 :(得分:0)

首先-Kafka不知道键/值的内容。它操作字节,由客户(生产者/消费者)负责反序列化。

到目前为止,最常见的选项似乎是JSON,protobuf和Avro。

我个人喜欢Avro的原因,以及为什么我通常使用它并向他人推荐:

1)这是一个足够紧凑的二进制序列化,具有模式和逻辑类型(有助于区分常规的longtimestamp in long millis

2)Avro模式具有很强的描述性和完善的文档记录

3)必须在大多数广泛使用的编程语言中提供广泛的支持!

4)Confluent(及其他)提供架构的存储库,即所谓的“模式注册表”,以为您的架构提供集中存储。在Avro中,该消息仅包含架构版本ID,而不包含架构本身。

5)如果您使用的是Java,则可以从模式中使用POJO基类生成。

当然可以使用其他选项来包含其中的一部分。您应该尝试比较适合您的用例的所有选项。

P.S。我非常个人的建议是:如果不是String,请选择Avro。同时适用于键和值。