Schema Registry为元数据提供服务层。它为存储和检索Avro schema提供了RESTful接口。它存储所有schema的历史版本,提供多个兼容性设置,并允许根据配置的兼容性设置进行schema演化。
Schema Registry是Avro模式的分布式存储层,它使用Kafka作为底层存储机制。下面是一些关键的设计决策:
(1)为每个注册schema分配全局唯一id。分配的id保证是单调递增的,但不一定是连续的。
(2)Kafka提供了持久的后端。
(3)Schema Registry被设计为分布式的,具有单主架构,Zookeeper/Kafka协调主节点的选择(基于配置)。
Avro Background
当通过网络发送数据或将数据存储在文件中时,我们需要一种将数据编码为字节的方法。数据序列化领域有着悠久的历史,但在过去几年中有了很大发展。人们开始时使用特定于编程语言的序列化方法,比如Java序列化,这使得使用其他语言的数据很不方便。然后人们转向不依赖于语言的格式,如JSON。
然而,像JSON这样的格式缺乏严格定义的格式,这有两个明显的缺点:
(1)数据消费者可能不理解数据生产者:8由于缺乏结构,使用这些格式的数据更具挑战性,因为可以任意添加或删除字段,甚至可以损坏数据。跨组织的应用程序或团队开始使用数据源的数量越多,这种缺陷就越严重。如果上游团队可以随意更改数据格式,那么就很难确保所有下游消费者能够解释数据。缺少的是生产者和消费者之间的数据“契约”(schema,见下文),类似于API的契约。
(2)开销和冗余:它们是冗余的,因为字段名和类型信息必须以序列化格式显式表示,尽管所有消息都是相同的。
出现了一些跨语言的序列化库,它们要求数据结构由某种模式定义。这些库包括Avro、Thrift和Protocol buffer。使用模式的优点是它清楚地指定了数据的结构、类型和含义(通过文档)。使用模式,还可以更有效地编码数据。
Avro模式以JSON格式定义数据结构。
下面是一个示例Avro模式,它使用两个字段指定用户记录:类型string的name和favorite_number以及int。
{"namespace": "example.avro",
"type": "record",
"name": "user",
"fields": [
{"name": "name", "type": "string"},
{"name": "favorite_number", "type": "int"}
]
}
例如,您可以使用这个Avro模式将Java对象(POJO)序列化为字节,并将这些字节反序列化回Java对象。
Avro的一个有趣之处在于,它不仅在数据序列化期间需要模式,而且在数据反序列化期间也需要模式。因为模式是在解码时提供的,所以不必在数据中显式编码字段名等元数据。这使得Avro数据的二进制编码非常紧凑。
Schema ID分配
模式ID分配总是发生在主节点中,它们确保模式ID单调地增加。
如果使用Kafka master election,模式ID总是基于写入Kafka store的最后一个ID。
如果您正在使用ZooKeeper主选择,/<schema. registration .zk.namespace>/schema_id_counter path将当前ID批处理的上限存储起来,新的批处理分配将由主选择和当前批处理结束触发。此批处理分配有助于防止潜在的僵尸master现象。
网友评论