티스토리 뷰
Primitive Types
- null : 값이 없음
- boolean : a binary 값
- int : 32-bit signed integer
- long : 64-bit signed integer
- float : single precision (32-bit) IEEE 754 소숫점 숫자
- double : double precision (64-bit) IEEE 소숫점 숫자
- bytes : 8-bit unsigned 바이트 배열
- string : unicode characther 배열
Primitive 타입은 속성을 갖지 않는다.
Primitive 타입 이름은 또한 type name 으로 정의된다. 그래서 예를들어 "string" Schema 는 {"type":"string"} 과 동일하다.
Complex Types
Avro 는 6개 종류의 Complext Type 을 지원한다 : records, enums, arrays, maps, unions, fixed
Records
Records 는 타입 이름으로 "record" 를 사용하며 아래 요소들을 지원한다.
- name : Record 의 이름을 제공하는 JSON string (필수)
- namespace : name 을 보충하는 JSON string
- doc : Schema 사용에게 문서를 제공하는 JSON string (선택)
- aliases : Record 의 또 다른 이름을 제공하는 Json string 배열 (선택)
- fields : field 를 나열한 JSON 배열. 각각의 field 는 JOSN Object 이고 아래 요소들을 포함한다.
- name : field 의 이름을 제공하는 JSON string (필수)
- doc : field 를 사용자에게 설명하는 JSON string (선택)
- type : 위에서 설명한 것과 같은 type
- default : 이 field 의 기본 값. 해당 객체를 읽을때 만들어진 데이터에 field 가 없을때 Schema Evolution 의 목적으로 사용된다. default value 가 있다고 하더라도 field 를 optional 로 만들지는 않는다. 허용되는 값은 아래 표에 따라 field Schema 타입에 따라 다르다. Union 필드의 default 값은 Union 의 첫번째 값을 따른다. Bytes 와 Fixed 필드의 기본 값은 JSON string 이고 Unicode 포인트 0-255는 unsigned 8-bit byte value 0-255 로 맵핑된다. Avro 는 비록 데이터의 값이 default 와 동일하다고 하더라도 인코딩한다.
- order : Field 가 어떻게 정렬될지를 특정한다 (선택). "ascending" (기본값), "descending", "ignore" 가 유효한 값이다.
Enums
Enum 은 "enum" 타입 명으로 사용된다.
- name : Enum 의 이름을 제공하는 JSON string (필수)
- namespace : name 을 보충하는 JSON string
- aliases : Enum 의 대체 이름을 제공하는 JSON string 배열 (선택)
- doc : 사용자에게 schema 를 설명하는 문서를 제공하는 JSON string (선택)
- symbols : symoble 을 나열하는 JSON 배열 (필수). 모든 Enum 의 symbols 은 유일해야한다. 모든 symoble 은 이 정규표현식에 매칭되어야한다. [A-Za-z_][A-Za-z0-9_]
- default : Enum 타입에서 default 는 Writer Schema 로 작성한 데이터를 Reader Schema 가 읽을때 정의되어있지 않은 값을 마주쳤을때 사용한다 (선택). symbol 배열에 속해있는 Enum 이여야하고 JSON string 이다.
{
"type": "enum",
"name": "Suit",
"symbols" : ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
}
Arrays
Arrays 는 "array" 타입 명으로 사용된다.
- items : 배열의 항목
{
"type": "array",
"items" : "string",
"default": []
}
Unions
Uninos 은 JSON 배열로 표현된다. ["null", "string"] 은 null 또는 string 일 수 이는 schema 를 정의한다.
default 값은 union 의 첫번째 타입과 매칭되어 사용된다는 것을 기억하자. 그래서 union 이 "null" 을 포함하고 있다면 "null" 이 리스트에 첫번째 요소가 되어야 null 이라는 값을 가질 수 있는 optional 필드로서 역할을 할 수 있다.
Union 은 동일한 type 을 가질 수 없다. 예를들어 Union 은 2개의 배열 타입과 2개의 Map 타입을 가질 수 없다. 하지만 서로 다른 일므을 가진 두개의 타입은 허용된다.
Union 은 다른 union 을 바로 포함할 수 없다
Fixed
Fixed 는 "fixed" 라는 타입 이름으로 사용된다
- name : fixed 의 이름을 나타내는 string (필수)
- namespace : name 을 보충하는 string
- alias : 대체 이름을 제공하기 위한 JSON 배열 (선택)
- doc : 사용자에게 schema 를 설명하는 문서를 제공하는 JSON string (선택)
- size : 값 별 Bytes 의 수 (필수)
{"type": "fixed", "size": 16, "name": "md5"}
Names
record, enum, fixed 는 Named 타입이다. name 과 namespace 로 나뉘는 두개의 파트를 가진 full name 을 갖는다. 이름의 동등성은 fullname 으로 정의된다.
fullname 의 일부분인 name 은 아래 규칙을 따른다
- [A-Za-z] 으로 시작
- [A-Za-z0-9_] 만 포함
namespace 는 각각의 이름을 . 으로 구분한다. empty string 은 사용하여 null namspace 를 가리킨다. fullname 과 name 의 동등성은 case-sensitive 하다.
null namespace 는 . 으로 구분된 name 배열을 사용하지 않는다. 따라서 namespace 의 문법은 아래와 같다.
<empty> | <name>[(<dot><name>)*]
record, enum, fixed 정의에서 fullname 은 아래의 방법으로 결정된다
- name 과 namespace 는 둘 다 지정된다면. 예를들어 "name": "X", "namespace": "org.foo" 를 사용한다면 fullname 은 org.foo.X 가 된다
- fullname 만 지정된다면. name 에 . 가 포함되어있다면 namespace 는 무시된다. "name": "org.foo.X" 의 fullname 은 "org.foo.X" 가 된다.
- name 만 지정되고 name 에 . 이 포함되어있지 않다면. 이 경우에는 namespace 가 schema 혹은 protocol 로 둘러쌓여진다. 예를들어 "name": "X" 로 지정되고 "org.foo.Y" 에 정의되어있는 record 에서 사용되는 field 라면 fullname 은 "org.foo.X" 가 된다.
name 이 . 을 포함하고 있다면 fullname 으로 사용되고 name 이 . 을 포함하고 있지 않다면 namespace 는 schema 또는 protocol 로 부터 불러와지게 된다.
Primitive 타입은 namespace 가 없고 Primitive 타입의 이름은 어떠한 namespace 에도 정의되어 있지 않다.
Aliases
Named 타입과 Field 는 aliases 를 가질 수 있다. 구현체는 선택적으로 Alias 를 사용하여 Write Schema 를 Read Schema 에 맵핑할 수 있다. 이것은 Schema Evolution 와 Disparate 데이터 처리를 용이하게 한다.
Alias 기능은 Reader Schema 의 Alias 를 사용하여 Write Schema 가 다시 데이터를 쓸 수 있다. 예를들어, Writer Schema 가 "Foo" 라는 이름으로 지었는데 Reader Schema 가 "Bar" 라는 이름으로 지었고 "Foo" 에 해당하는 Alias 가 있다면 구현체는 "Foo" 를 "Bar" 라는 것으로 읽을때 사용한다.
Data Serialization and Deserialization
Binary 로 인코딩된 Avro 데이터는 타입정보나 Field 이름을 포함하고 있지 않다. 그 결과로 직렬화된 데이터의 크기가 작다는 이점을 가질 수 있다. 하지만 Avro 데이터를 정확하게 읽어내기 위해서는 Schema 정보가 항상 사용되어야한다. 이것을 보장하기 위한 최선의 방법을 Read 할때 Schema 와 Write 할때 Schema 가 동일한 것을 사용하는 것이다.
그래서 Avro 데이터를 저장할때는 Schema 정보도 함께 저장해야만 한다. Avro 기반 RPC 호출 시스템도 호출하는 측에서도 Schema 복사본을 사용하는 것이 보장되어야 한다. 새로운 Schema 로 데이터를 역직렬화 하는 것은 Schema Resolutioon 를 사용하면 성공할 수 있다.
일반적으로 직렬화, 역직렬화 모두 깊이 우선 탐색, 좌에서 우로 Schema 탐색하면서 바주치는 primitive 타입을 직렬화/역직렬화 하면서 수행된다. 그래서 Avro 데이터를 Schema 로 읽는것은 데이터가 쓰여질 당시의 같은 Parsing Canonical Form Schema 가 아닐 수 있다. 이것이 동작하도록 하기 위하여 직렬화된 primitive 값이 역직렬화 Schema 와 호환이 가능해야한다. 예를들어, int 와 long 은 항상 같은 방법으로 직렬화된다. 따라서 int 는 long 으로 역직렬화 될 수 있다. 두 Schema 의 호환성은 데이터와 직렬화 포맷에 달려있기 때문에 동일한 Parsing Canonical Form 을 사용하는 것이 더 간단하고 안정적이다.
Encoding
Avro 두개의 인코딩 직렬화를 지원한다. Binary 와 JSON. 대부분의 어플리케이션들은 Binary 인코딩이 더 빠르고 간단하기 때문에 Binary 인코딩을 사용한다. 그러나 Debugging 의 장점과 Web-based 어플리케이션들은 JSON 인코딩을 사용하는게 때때로는 적합할 수도 있다.
Binary Encoding
Binary 인코딩은 field 이름을 포함하지 않고 field, record 의 구분자 또한 저장하지 않는다. 그래서 Reader 는 데이터가 인코딩될때 Schema 에 의존한다.
Json Encodinng
Union 을 제외하고 JSON 인코딩은 field default values 인코딩을 사용하는 것은 동일하다
union 은 JSONT 으로 아래와 같이 인코딩된다.
- 만약 타입이 null 이면 JSON null 로 인코딩된다
- 그외에는 name/value 쌍으로 JSON 객체로 인코딩이 된다. name 은 type 의 name 이고 value 는 인코딩 되는 value 이다. Avro 의 Named type (record, fixed, enum) 은 유저가 특정한 이름이 name 으로 사용되고 다른 타입들은 type 의 name 이 사용된다.
예를 들어, union schema 인 ["null, "string", "Foo"]이 있고 Foo 가 Record 이름일때
- null 은 null
- string "a" 는 {"string":"a"}
- Foo 객체는 {"Foo": {...}}
로 직렬화 된다. 명심해야할 것은 Write 할 당시의 Schema 는 역직렬화를 위해서 필요하다. 한가지예로 JSON 인코딩이 int, long, float, double, record, maps, enum, string 등등을 구분하지 않는다.
Single-object encoding
Avro 로 직렬화된 데이터를 꽤 긴 기간동안 저장해야 하는 경우가 있다. 가장 흔한 예중의 하나는 Apache Kafka 에 몇주 동안 record 를 저장하는 경우이다.
직렬화된 데이터가 저장된 이후에 Schema 가 변경된다면 이 시스템은 Read 할때와 Write 할때 다른 Schema 를 사용하게 된다. 따라서 Schema Evolution 을 정확하게 지원하기위하여 Write 할 당시의 Schema 를 알아야 하는 필요성이 있다. 대부분의 경우의 Schema 는 메시지에 스키마를 포함하기에는 너무 크기 때문에, Binary Wrapper 포맷이 이 유즈케이스를 효과적으로 지원한다.
Single object encoding specification
Single Avro Object 는 아래와 같이 직렬화 된다.
- 2byte 마커 (C3 01) 가 Avro 메시지임을 나타내고 single-record format 을 사용하였음을 나타낸다
- Object schema 를 식별하기 위한 CRC-64-AVRO fingerprint 의 little-edian 8byte
- Avro Binary 인코딩을 사용한 Avro serialized data
구현체는 2-byte 마커를 사용하여 payload 가 Avro 인지를 확인한다. 이것은 데이터가 Avro 로 직렬화되지 않았을 경우에 비싼 lookup 작업을 피할 수 있도록 돕는다.
Schema Resolution
RPC 또는 File 이던지 간에 Avro 데이터의 Reader 는 Write 할 당시의 Schema 가 데이터와 함께 제공되기 때문에 항상 데이터를 파싱할 수 있다. 하지만 Reader 는 다른 Schema 로도 데이터를 읽을 수 있도록 개발되었다. 예를들어 서로 다른 버전의 Software 로 Avro 데이터가 작성되었다면 Field 가 추가되거나 제거될 수 있다. 이 장에서는 이러한 Schema 의 차이를 어떻게 해결할 수 있는지를 설명한다.
데이터를 Write 할때 사용된 Schema 를 writer's schema 라 부르고 Read 할때 사용되는 Schema 를 reader's schema 라 부른다. 이 두 Schema 의 차이는 아래와 같이 해결될 수 있다
- 만약 두 Schema 가 일치하지 않는다면 에러이다. 일치하게 하기 위하여 아래 규칙들이 지켜져야한다
- 두 스키마의 Array item type 은 일치해야한다
- 두 스키마의 Map item type 은 일치해야한다.
- 두 스키마의 Enum name 은 일치해야한다.
- 두 스키마의 Fixed 사이즈와 이름은 일치해야한다.
- 두 스키마의 Record 이름은 일치해야한다.
- 두 스키마는 같은 Primitive Type 을 가져야한다
- Reader Schema 는 Writer Schema 로 부터 아래와 같이 변경될 수 있다
- int는 long, float, double 로 변경될 수 있다
- long 은 float, double 로 변경될 수 있다
- float 은 double 로 변경될 수 있다
- string 은 bytes 로 변경될 수 있다
- bytes 는 string 으로 변경될 수 있다
- 둘 다 record 인 경우
- field 의 순서가 달라야한다. 필드는 이름에 의해서 매칭된다
- 두 Schema 에서 같은 이름을 사용하는 field 는 재귀적으로 해결된다
- Writer record 가 Reader record 에 없는 field 를 가지고 있다면, Writer 의 필드는 무시된다
- Reader record 의 field 가 default value 를 가지고 있고 Writer Schema 가 해당 필드와 같은 이름을 가지고 있지 않다면 Reader 는 default value 를 사용한다
- Reader record 가 default value 를 가지고 있지 않고 Writer Schema 가 동일한 이름의 field 를 가지고 있지 않다면 Error 가 발생한다.
- 둘 다 Enum 인 경우
- Writer symbol 이 Reader symbol 에 존재하지 않고 Reader 가 default value 를 가지고 있으면 default value 가 사용되고 default value 가 없는 경우 에러가 발생한다
- 둘 다 Array 인 경우
- Reader 와 Writer 아이템의 Schema 를 재귀적으로 해결한다
- 둘 다 Map 인 경우
- Reader 와 Writer 아이템의 Schema 를 재귀적으로 해결한다
'Avro' 카테고리의 다른 글
Avro - Serializer/Deserializer 비교 (0) | 2022.02.18 |
---|---|
Avro 시작하기 - Java, Gradle (0) | 2022.02.17 |
Apache Avro 소개 (0) | 2022.02.17 |
- Total
- Today
- Yesterday
- custom config data convertion
- referencedColumnName
- notify()
- RouteDefinition
- ResultSet
- getBoolean
- reative
- Lazy
- mariadb-connector-j
- msyql-connector-java
- N+1
- Seperate Chaining
- circurit breaker
- GlobalFilter
- DyanomoDB
- rate limit
- spring cloud gateway
- dynamodb
- wait()
- MariaDB
- aurora
- ConcurrentHashMap
- Flux
- RoutePredication
- mariada-connector
- reactor
- router
- AbstractMethodError
- notifyAll()
- HashMap
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |