Introduction
Applications inevitably change over time:- New features are added
- Requirements change
- Bug fixes are deployed
- Performance improvements are made
- Backward compatibility: New code can read data written by old code
- Forward compatibility: Old code can read data written by new code
1. Formats for encoding data
When you want to send data over the network or write it to a file, you need to encode it as a sequence of bytes.Language-specific formats
Many programming languages have built-in encoding (Python’s pickle, Java’s Serializable, Ruby’s Marshal). Problems:- Tied to one language
- Security issues (arbitrary code execution)
- Poor versioning support
- Inefficient
JSON, XML, and CSV
Text-based formats that are human-readable and language-independent. Advantages:- Human readable
- Language independent
- Widely supported
- Ambiguity with numbers
- No binary string support
- Verbose, larger size
- Schema support varies
Binary encoding
Text formats are verbose. Binary formats are more compact and faster to parse. Size comparison:2. Thrift and Protocol Buffers
Binary encoding formats that require a schema. Benefits:- Compact binary encoding
- Type safety
- Schema evolution support
- Code generation
Thrift
Schema definition (Thrift IDL):Key insight: Fields are identified by tag numbers (1, 2, 3), not field names. This enables schema evolution.
Protocol Buffers
Similar to Thrift, developed by Google. Schema definition (Protocol Buffers):3. Schema evolution
The key to maintaining compatibility during schema changes.Adding fields
Rule: New fields must be optional or have default values for backward compatibility.
Removing fields
Rules for removing fields:- Can only remove optional fields (never required!)
- Cannot reuse tag number (forward compatibility!)
Changing field types
Example of safe type change:4. Avro
A different approach to schema evolution, developed for Hadoop. Avro difference: No tag numbers in schema! Avro schema (JSON):Writer’s schema vs reader’s schema
Avro’s key insight: Need both schemas to decode data! How Avro resolves schemas: The reader compares the writer’s schema with its own schema and maps fields by name. Schema resolution rules:- Writer field present, reader field present: Match by name, convert if types compatible
- Writer field present, reader field absent: Ignore field
- Writer field absent, reader field present: Use default value or null
Schema evolution in Avro
Adding a field:Where does writer’s schema come from?
Different contexts:- Large file with many records: Include writer schema once at file start
- Database with schema registry: Store schema version in each record, schema registry maps ID to schema
- Network service: Negotiate schema at connection setup
Avro vs Thrift/Protocol Buffers
Thrift/Protocol Buffers:- Tag numbers enable field renaming
- Schema embedded in code
- Can’t reuse tag numbers
- Manual tag management
- No tag numbers to manage
- Can rename fields with aliases
- Better for dynamic schemas
- Need writer’s schema to decode
5. Modes of dataflow
How does data flow between processes? Three main modes:- Via databases: Process writes, another reads later
- Via services: Client sends request, server responds
- Via message passing: Async message queue
Dataflow through databases
Dataflow through services (REST and RPC)
Two main approaches: REST and RPC REST example:RPC hides the differences between network calls and local calls, which can make debugging harder. Network calls are unpredictable, may fail, may timeout, and idempotency matters.
Dataflow through message passing
Benefits of message queues:- Decoupling: Sender doesn’t need to know about receiver
- Buffering: Queue absorbs bursts
- Reliability: Retry on failure
- Flexibility: Multiple consumers
Actor model
Each actor:- Has a mailbox for incoming messages
- Processes messages sequentially
- Can send messages to other actors
- No shared state (concurrency-safe)
Summary
Key takeaways:-
Encoding formats trade-offs:
- JSON/XML: Human-readable, widely supported, verbose
- Thrift/Protobuf: Compact, fast, requires schema
- Avro: Most compact, dynamic schemas, complex resolution
-
Schema evolution essentials:
- New fields must be optional or have defaults
- Can’t remove required fields
- Can’t reuse field tags/IDs
- Preserve unknown fields when possible
-
Compatibility requirements:
- Backward: New code reads old data (common)
- Forward: Old code reads new data (harder)
- Both needed for rolling deployments
-
Dataflow patterns:
- Databases: Long-lived data, many readers
- Services: Request-response, synchronous
- Messages: Asynchronous, decoupled
-
Best practices:
- Include schema version in data
- Test compatibility between versions
- Use schema registry for centralized management
- Document breaking changes
Quick reference: Encoding format comparison
Quick reference: Encoding format comparison