為什麼需要schema registry?
首先我們知道:
- Kafka將位元組作為輸入併發布
- 沒有資料驗證
但是:
- 如果Producer傳送了bad data怎麼辦?
- 如果欄位被重新命名怎麼辦?
- 如果資料型別改變了怎麼辦?
這些情況都會導致consumer break
所以:
- 我們需要資料能夠自我描述
- 我們需要能夠在不破壞下游消費者的情況下演化資料
- 能夠拒絕壞資料
為什麼不在kafka broker收到訊息時驗證訊息,而是使用schema registry?
由下面兩幅圖可以看到,schema registry是獨立於kafka的一個元件。
Kafka Core:
Confluent Components -Schema Registry:
為什麼schema registry不整合在kafka broker,因為這樣會打破kafka一些優秀的特性:
- Kafka不解析或讀取你的資料(沒有使用CPU)
- Kafka將位元組作為輸入,而不需要事件將它們載入到記憶體中(稱為零拷貝) 。什麼是零拷貝,移步至https://www.cnblogs.com/fangjb/p/13271886.html
- 就Kafka而言,它甚至不知道你的資料是否是整數或是字串。
所以:
- Schema Registry需要是獨立的元件
- 生產者和消費者需要能夠與之對話
- 必須商定通用的資料格式
- 它需要支援schema
- 它需要支援進化
- 它需要是輕量級的
Solution:
Confluent Schema Registry
Apache Avro as the data format
Apache Avro& Avro Schema介紹
- Apache Avro是一個資料序列化系統。
- 可以將Avro看作是JSON附帶一個schema
- Avro schema使用Json來定義
- Avro依賴於schema
Avro優點:
1.豐富的資料結構
2.使用快速的壓縮二進位制資料格式
3.schema隨資料一起出現
4.schema可以以安全的方式隨時間進化(schema evolution)
5. Document嵌入到schema中
Avro缺點:
1.某些語言對Avro的支援可能缺乏
2.不使用avro工具就不能“列印”資料(因為壓縮了和序列化)
資料型別
Schema 定義了基本資料型別和複雜資料型別,其中複雜資料型別包含不同屬性。通過各種資料型別使用者可以自定義豐富的資料結構
基本型別:
型別 |
含義 |
null |
沒有值 |
boolean |
布林值 |
int |
32位有符號整數 |
long |
64位有符號整數 |
float |
單精度(32位)的IEEE 754浮點數 |
double |
雙精度(64位)的IEEE 754浮點數 |
bytes |
8位無符號位元組序列 |
string |
字串 |
複雜型別
Avro提供了6種複雜型別。分別是Record,Enum,Array,Map,Union和Fixed。
Record型別:
Record型別使用的型別名字是 “record”,還支援其它屬性的設定:
- name(必填):record型別的名字
- namespace:名稱空間(可選),相當於java中的包名
- doc:這個型別的文件說明(可選)
- aliases:record型別的別名,是個字串陣列(可選)
- fields(必填):record型別中的欄位,是個物件陣列。每個欄位需要以下屬性:
- name(必填):欄位名字
- doc:欄位說明文件(可選)
- type(必填):一個schema的json物件或者一個型別名字
- default:預設值(可選)
- order:排序(可選),只有3個值ascending(預設),descending或ignore
- aliases:別名,字串陣列(可選)
一個record例子:
{ "type": "record", "namespace": "com.aaa", "name": "Employee", "fields": [ { "name": "id", "type": "string"}, { "name": "first_name", "type": "string", "default": ""}, { "name": "last_name", "type": "string", "default":""} ] }
Enum
列舉型別的型別名字是”enum”,還支援其它屬性的設定:
- name:列舉型別的名字(必填)
- namespace:名稱空間(可選)
- aliases:字串陣列,別名(可選)
- doc:說明文件(可選)
- symbols:字串陣列,所有的列舉值(必填),不允許重複資料。
一個列舉例子:
{ "type": "enum", "name": "customer_status", "symbols": [ "BRONZE", "SILVER", "GOLD" ] }
Array
陣列型別的型別名字是”array”並且只支援一個屬性:
items:陣列元素的schema
一個陣列例子:
{ "name": "email", "type": "array", "items": "string" }
Map
Map是一種定義keys和values列表的方法,其中keys是字串.
Example: secrets questions
- “What’s your favourite color?”: “green”
- “Where were you born?”: “Tapei”
- “Who you love most?”: “My wife”
Map型別的型別名字是”map”並且只支援一個屬性:
values:map值的schema
Map的key必須是字串。
一個Map例子:
{ "name": "secrets", "type": "map", "values": "long" }
Union
組合型別,表示各種型別的組合,使用陣列進行組合。比如[“null”, “string”]表示型別可以為null或者string。
組合型別的預設值是組合型別的第一個元素,因此如果一個組合型別包括null型別,那麼null型別一般都會放在第一個位置,這樣子的話這個組合型別的預設值就是null。
組合型別中不允許同一種型別的元素的個數不會超過1個,除了record,fixed和enum。比如組合類中有2個array型別或者2個map型別,這是不允許的。
組合型別不允許巢狀組合型別