maxwell订阅binlog并生产到Kafka
1.zookeeper伪分布式安装
2.Kafka伪分布式安装
创建一个topic为maxwell
sh $KAFKA_HOME/bin/kafka-topics.sh --create --zookeeper hadoop_zxy:2181 --replication-factor 2 --partitions 1 --topic maxwell
3.MySQL
3.1 binlog文件存储类型
- statement类型
语句级,只记录写操作的SQL语句
-- statement类型是记录写操作的语句,记录什么在从库执行什么
update user set name = 'zxy' where id = '0001';
-- 从id < '0100'可以看出是有很多数据的发生变化的,可以一次性执行
update user set name = 'zxy' where id < '0100';
-- 当使用这些随机,时间,udf函数的时候,因为主库和从库都会执行一次,那么得到的结果可能就会不一样
update user set name = random()/now()/current_date()/udf() where id = '0001';
- row格式
行级,记录每行数据的变化
--row格式,记录每行的数据变化,也就是数据的最终结果
update user set name = 'zxy' where id = '0001';
--这里就跟statement不一样,这里需要将每一条语句都执行一次
update user set name = 'zxy' where id < '0100';
-- 这里也不一样,因为row包留的是执行SQL的最终结果,所以会与主库保持一致
-- 例如:当主库执行update user set value = now() where id = '0001',
-- 那么在SQL的row格式下,binlog文件中记录的就是,
-- update user set value = '2022-06-11 22:03:30'
update user set value = random()/now()/current_date()/udf() where id = '0001';
- mixed格式
statement升级版,正常情况下都是statement,只有SQL中使用了随机、时间、自定义函数等时会变成row
-- mixed混合模式,正常长情况下都是跟statement类型一样保持操作语句
update user set name = 'zxy' where id = '0001';
update user set name = 'zxy' where id < '0100';
-- 但是遇到这种情况的时候,就会自动使用row类型保持操作语句最终结果到binlog
update user set name = random()/now()/current_date()/udf() where id = '0001';
3.2 开启binlog
如果是同步指定的数据库,请添加
binlog_do_db=gmall
> [root@hadoop_zxy software]# vim /etc/my.cnf
> 添加以下内容
log-bin = mysql-bin
binlog_format = row
server-id = 1
innodb_file_per_table = ON
skip_name_resolve = ON
> 注意:binlog_format一定要设置为row
> 修改好后一定要重启数据库
[root@hadoop_zxy scripts]# service mysqld restart
3.3 查看binlog状态
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/mysql-bin |
| log_bin_index | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+--------------------------------+
6 rows in set (0.00 sec)
mysql>
3.4 查看binlog日志
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 220628 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
> 注意:这里的File和Posititon在启动maxwell的使用会用到
3.5 创建maxwell用户并分配权限
CREATE USER 'maxwell'@'%' IDENTIFIED BY '@Zhou147258369';
create database maxwell DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
GRANT ALL ON *.* TO 'maxwell'@'%';
GRANT ALL ON *.* TO 'maxwell'@'localhost' IDENTIFIED BY '@Zhou147258369' ;
GRANT ALL ON *.* TO 'maxwell'@'localhost.localdomain' IDENTIFIED BY '@Zhou147258369';
GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE on *.* to 'maxwell'@'%';
GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE on *.* to 'maxwell'@'localhost';
GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE on *.* to 'maxwell'@'localhost.localdomain';
GRANT USAGE ON *.* TO 'maxwell'@'localhost.localdomain' IDENTIFIED BY '@Zhou147258369' WITH GRANT OPTION;
grant all privileges on *.* to maxwell@localhost.localdomain identified by '@Zhou147258369';
flush privileges;
4.maxwell
Maxwell和Canal的选择,根据自己的场景和需求确定
1.Canal有server+client模式,Maxwell只有一个server把数据发送到消息队列或redis
2.Canal只能抓取最新数据,对已存在的历史数据没有办法处理。Maxwell提供一个bootstrap功能,可以直接引导出完整的历史数据用于初始化
3.Maxwell不支持HA,需要自行开发。但支持断电还原,即错误解决后重启继续上次位置读取数据。
4.Canal在server+client模式下,可以自定义数据格式。Maxwell只支持json格式。
5.Maxwell比canal更轻量级
6.Maxwell需要在数据库中建立Maxwell库
[root@hadoop_zxy software]# tar -zxvf maxwell-1.22.1.tar.gz -C /zxy/apps/
[root@hadoop_zxy maxwell-1.22.1]# vim config.properties.example
>> 加入以下内容:
# tl;dr config
daemon=true
log_level=info
producer=kafka
kafka.bootstrap.servers=hadoop_zxy:9092
kafka_topic=maxwell
# 设置根据表将binlog写入Kafka不同分区,还可指定:[database, table, primary_key, transaction_id, thread_id, column]
producer_partition_by=table
# mysql login info
host=ip地址
user=maxwell
password=@Zhou147258369
port=3306
schema_database=maxwell
# maxwell启动端口
http_port=9002
http_diagnostic=true
http_path_prefix=/
metrics_type=jmx|http|datadog
5.启动
5.1 启动zookeeper
5.2启动Kafka
5.3启动Kafka消费端
5.4启动maxwell
第一次启动 指定binlog
[root@hadoop_zxy maxwell-1.22.1]# bin/maxwell --conf config.properties.example --init_position=/var/lib/mysql/mysql-bin.000002:47565:0 &
binlog的路径可以通过
find / -iname 'mysql-bin.000002'
查找47565为
3.3查看binlog日志处显示
0是maxwell的监听
6.测试
6.1 MySQL插入数据
6.2 maxwell监听状态
6.3 Kafka消费者接收数据
7.Maxwell全量导入数据
7.1 maxwel-bootstrap命令导入
[root@zxy_master maxwell-1.22.1]# bin/maxwell-bootstrap --config config.properties --database database_name --table table_name
7.2 SQL命令
如果需要指定条件导入,需要为字段where_clause插入值
insert into maxwell.bootstrap(database_name,table_name) values('database_name','table_name')
8.如何保证业务执行顺序一致?
通过Maxwell解析MySQL的binlog,当业务系统的表A,先update字段name为zxy,再update字段name为zxyyy,那么如何保证Maxwell将数据发送至Kafka的时候,也是按照这个顺序呢?
首先,可以想到当所有数据发送到Kafka的一个分区内的时候,肯定是有序的,但是这样就会影响效率
那么我们要做的就是保证分区内有序,将同一类数据发送到一个分区内,通过配置Maxwell的配置文件,保证让相同id的数据发送到一个分区内,这样不管做了多少次update,始终是将修改记录发送到一个分区内,且有序
# config.properties文件
# *** partitioning ***
# What part of the data do we partition by?
# producer_partition_by=database # [database, table, primary_key, transaction_id, column]
# 按照字段类型分区
producer_partition_by=column
# specify what fields to partition by when using producer_partition_by=column
# column separated list.
# producer_partition_columns=id,foo,bar
## 按照字段ID分区
producer_partition_columns=id
# when using producer_partition_by=column, partition by this when
# the specified column(s) don't exist.
# producer_partition_by_fallback=database
# 如果没有该字段,则按照表分区
producer_partition_by_fallback=table