繁体   English   中英

使用不同 Avro 类型向 Kafka 发送消息的性能——SpecificRecordBase vs. GenericRecord with Schema Registry

[英]Performance of using different Avro types for sending messages to Kafka – SpecificRecordBase vs. GenericRecord with Schema Registry

我正在尝试查找有关使用两种不同的 Avro 类型发送 Kafka 消息的性能和(缺点)优势的一些信息。 根据我的研究,可以创建一个基于 avro 的 Kafka 消息的有效负载:

要么

GenericRecord其实例可以通过调用new GenericData.Record并将从 Schema Registry 读取的模式作为参数传递:

大致:

private CachedSchemaRegistryClient schemaRegistryClient;
private Schema valueSchema;
// Read a schema
//…
this.valueSchema = schemaRegistryClient.getBySubjectAndID("TestTopic-value",1);
// Define a generic record according to the loaded schema

GenericData.Record record = new GenericData.Record(valueSchema);
// Send to kafka

ListenableFuture<SendResult<String, GenericRecord>> res;
res = avroKafkaTemplate
        .send(MessageBuilder
                .withPayload(record)
                .setHeader(KafkaHeaders.TOPIC, TOPIC)
                .setHeader(KafkaHeaders.MESSAGE_KEY, record.get("id"))
                .build());

一个 class 扩展了SpecificRecordBase并在 Maven 的帮助下生成(来自包含 Avro 模式的文件)

/..
public class MyClass extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord

/..
MyClass myAvroClass = new MyClass();

ListenableFuture<SendResult<String, MyClass>> res;
res = avroKafkaTemplate
        .send(MessageBuilder
                .withPayload(myAvroClass)
                .setHeader(KafkaHeaders.TOPIC, TOPIC)
                .setHeader(KafkaHeaders.MESSAGE_KEY, myAvroClass.getId())
                .build());

调试一段包含扩展GenericRecord的 class 实例的代码时,可以看到其中包含一个模式。

鉴于此,我有几个问题:

  1. 如果我向 Kafka 发送GenericRecord实例,是否也发送了底层架构?
    如果没有,什么时候下架? 哪个 class / 方法负责从GenericRecord中提取字节并删除底层模式,以便它不与有效负载一起发送? 如果是,那么模式注册表的意义何在?

  2. 如果是扩展SpecificRecord的 class ,也会发送底层架构,不是吗? 这意味着,如果我使用 function 接收 Kafka 消息并计算其字节数,我应该期望特定记录消息中的字节比通用记录消息中的字节多,对吧?

  3. SpecificRecord实例给了我更多的控制权,而且使用起来更不容易出错。 如果模式不是与GenericRecord一起发送的,而是与SpecificRecord一起发送的,那么我们需要进行权衡。 一方面(SpecificRecord),使用简单,因为清晰的 API 可用(不必记住所有字段,并编写 get("X")、get("Y") 等) ,另一方面,有效负载的大小会增加,因为模式必须与它一起发送。 如果我有一个相对较大的模式(50 个字段),我应该选择在模式注册表的帮助下发送 GenericRecords,否则性能会受到负面影响,因为模式必须随每条消息一起发送,对吗?

在通用或特定的两种情况下,模式都由生产者发送和缓存

性能方面,虽然我没有对其进行基准测试,但我估计两者的序列化时间大致相同,而反序列化对于 Generic 会更快,因为字段访问和类型转换将推迟到您自己的代码,而不是针对每个字段进行验证

注意:还有 ReflectData 记录,由于使用反射,可能会变慢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM