Maxwell Documentation
repository·master·Indexed 26 days ago
https://github.com/zendesk/maxwellMaxwell is a change data capture (CDC) tool that monitors MySQL binlogs and streams row-level changes as JSON to platforms such as Kafka, Kinesis, SQS, SNS, Google Cloud Pub/Sub, BigQuery, RabbitMQ, and Redis. It supports bootstrapping existing datasets, daemon mode execution, and various producer configurations for ETL processes, audit logs, and search indexing.
What's inside Maxwell
- Maxwell's daemon is a change data capture (CDC) application designed to read MySQL binlogs and stream data changes as JSON to various platforms, including Kafka, Kinesis, and other streaming services. It is commonly used for ETL processes, maintaining database audit logs, cache management, search indexing, and inter-service communication.
Understand Maxwell schema storage and history
masterMaxwell tracks database schema changes to interpret raw MySQL binlog bytes as typed data (numbers, strings, etc.). It uses a combination of base tables and a delta-based history system stored in the
maxwelldatabase.Base Schema Tables
When Maxwell first runs, it captures the initial schema in these tables:
tablescolumnsdatabases
Schema Change History
As schema modifications occur in the binlog, Maxwell stores the changes (diffs) in the
schemastable. Each entry inschemascontains:binlog_file,binlog_position(orgtid_set): The exact binlog location of the change.deltas: The internal representation of the schema change.base_schema_id: The ID of the previous schema this delta applies to.last_heartbeat_read: The most recent Maxwell heartbeat seen in the binlog before this change.server_id: The identifier for the database server.
To reconstruct the schema at any specific binlog position, Maxwell finds the most recent schema for the
server_idthat occurred before that position, then follows thebase_schema_idchain back to the initial captured schema.Implement a Custom Producer
masterIf existing producers do not meet your needs, you can add a custom producer at runtime:
- Implement Interfaces: Implement the
ProducerFactoryinterface (to create yourAbstractProducer) and theAbstractProduceritself. - Register Factory: Set
custom_producer.factoryin your configuration to the fully qualified class name of yourProducerFactory. - Deploy JAR: Add the custom
ProducerFactoryJAR and all its dependencies to the$MAXWELL_HOME/libdirectory. - Configure: Use the
custom_producer.*(orCUSTOM_PRODUCER_*env var) namespace for your producer's specific settings. These are accessible viaMaxwellConfig.customProducerProperties.
- Implement Interfaces: Implement the
Implement custom logic with Javascript Filters
masterFor complex filtering or data munging requirements, you can provide a Javascript file via the
--javascript FILEflag.Your script must contain a function named
process_row(row, state).Arguments:
row: AWrappedRowMapobject representing the current row. It provides methods likerow.suppress()to drop the row androw.data.get(key)/row.data.put(key, value)to access/modify row data.state: ALinkedHashMap<String, Object>representing a global state that persists across rows. You can usestate.put(key, value)andstate.get(key)to maintain state for filtering decisions (e.g., tracking a flag across multiple rows).
Capabilities:
- Suppressing rows: Call
row.suppress()to prevent the row from being emitted. - Data Munging: Modify the row data directly using
row.data.put()before it is emitted.
function process_row(row, state) { // Example: Updating global state based on row values if ( row.database == "test" && row.table == "lock") { var haslock = row.data.get("haslock"); if ( haslock == "false" ) { state.put("haslock", "false"); } else if( haslock == "true" ) { state.put("haslock", "true"); } } // Example: Suppressing rows based on the global state if(state.get("haslock") == "true") { row.suppress(); } // Example: Filtering and modifying data based on actual values if ( row.database == "test" && row.table == "bar" ) { var username = row.data.get("username"); if ( username == "osheroff" ) row.suppress(); row.data.put("username", username.toUpperCase()); } }Configure JMX for remote access
masterTo expose JMX metrics with remote access, you must use the
JAVA_OPTSenvironment variable before starting Maxwell.Below is an example configuration that allows remote access without authentication or SSL (insecure). Replace
SERVER_IP_ADDRESSwith your actual server IP.export JAVA_OPTS="-Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=9010 \ -Dcom.sun.management.jmxremote.local.only=false \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Djava.rmi.server.hostname=SERVER_IP_ADDRESS"Configure stream partitioning
masterMaxwell supports partitioning for Kafka, AWS Kinesis, and SNS/SQS. You can control how data is distributed using the
producer_partition_byoption.Available partitioning strategies:
databasetableprimary_keytransaction_idcolumn_datarandom
Partitioning by Column Data: If you choose
column_data, you must provide:producer_partition_columns: A comma-separated list of column names.producer_partiton_by_fallback: A fallback strategy (_database_,_table_, or_primary_key_) to use if the specified column does not exist in a row.
Kafka Specifics: Kafka partitions are determined by
HASH_FUNCTION(producer_partion_value) % TOPIC.NUMBER_OF_PARTITIONS.- The default
HASH_FUNCTIONishashCode. - You can set
kafka_partition_hashtomurmurhash3(seed is hardcoded to25342). - Important: You should pre-create your Kafka topics with the desired number of partitions before starting Maxwell.
Enable GTID-based replication
masterMaxwell supports GTID-based replication. To enable it, use the
--gtid_modeconfiguration parameter.To support this, your MySQL server must be configured with
gtid-mode=ONandenforce-gtid-consistency=true. When in GTID mode, Maxwell will transparently pick up a new replication position after a master change, though you must still re-point Maxwell to the new master (or use a floating VIP).[mysqld] server_id=1 log-bin=master binlog_format=row gtid-mode=ON log-slave-updates=ON enforce-gtid-consistency=trueEnable Row-Based Binlogs at Runtime
masterIf binlogs are already enabled and you want to avoid a MySQL restart to configure Maxwell, you can attempt to set the binlog format and row image globally.
Note:
binlog_formatis a session-based property. You must shut down all active connections for the change to row-based replication to take full effect.set global binlog_format=ROW; set global binlog_row_image=FULL;Maxwell system requirements
masterTo run Maxwell, ensure your environment meets the following minimum requirements:
- Java: JRE 11 or above
- MySQL: versions 5.1, 5.5, 5.6, 5.7, or 8
- Kafka: version 0.8.2 or greater (only if using the Kafka producer)
Filter tables using Basic Filters
masterYou can configure Maxwell to include or exclude updates from specific tables using the
--filtercommand line flag. Filters are evaluated in the order they are specified. You can use wildcards (*) and regular expressions (enclosed in/.../) to match database and table names.Common patterns include:
exclude: <pattern>: Suppress updates matching the pattern.include: <pattern>: Only include updates matching the pattern.
Note that if you use
exclude: *.*followed by aninclude, the order matters to ensure the inclusion takes precedence.Run multiple Maxwell instances against one master
masterTo run multiple Maxwell instances against a single master (e.g., to produce different table groups to different topics), ensure each instance has unique identifiers:
client_id: Each instance must have a uniqueclient_idto store its own unique binlog position.replica_server_id: Each instance must have a unique 32-bit integer forreplica_server_id. This value must be unique across all Maxwell instances and must not conflict with any existing MySQLserver_idvalues.
Install Maxwell
masterYou can install Maxwell using several methods: downloading the binary distribution, using Docker, or using Homebrew.