使用maxwell實時同步mysql數據到消息隊列(rabbitMQ)

maxwell簡介

maxwell是一個由Java編寫的守護進程,可以實時讀取mysql binlog並將行更新以JSON格式寫入Kafka,Kinesis,RabbitMQ,Google Cloud Pub / Sub或Redis(Pub / Sub或LPUSH)。(以上內容摘自maxwell官網)。可以想象,有了mysql增量數據流,使用場景就很多了,比如:實時同步數據到緩存,同步數據到ElasticSearch,數據遷移等等。與canal(ali)相比,更加輕量

maxwell還提供以下功能:

  • 使用SELECT * FROM table 的方式做全量數據初始化
  • 支持主庫發生failover後,自動恢復binlog位置
  • 對數據進行分區,解決數據傾斜的問題
  • 僞裝成mysql從庫,接收binlog

maxwell官網:http://maxwells-daemon.io/

maxwell源碼:https://github.com/zendesk/maxwell

maxwell使用

mysql配置

需要mysql開啓binlog,而binlog默認是關閉的,需要開啓,並且爲了保證同步數據的一致性,使用的日誌格式爲row-based replication(RBR),新建或修改my.conf開啓binlog。

$ vim /etc/my.cnf

添加內容

[mysqld]
log-bin=mysql-bin #添加這一行就ok
binlog-format=ROW #選擇row模式
server_id=1 #隨機指定一個不能和其他集羣中機器重名的字符串,如果只有一臺機器,那就可以隨便指定了

重啓mysql, 查詢是否已開啓bin

show variables like '%log_bin%'

配置jdk環境(略)

maxwell 依賴java sdk,所以需要先配置JDK環境。

下載maxwell:https://github.com/zendesk/maxwell/releases/download/v1.17.1/maxwell-1.17.1.tar.gz

解壓後

修改config.properties.example爲config.properties

到目前爲止,前期準備已完成

實戰項目:配置maxwell發送消息到rabbitMQ, 監聽MQ隊列,處理消息

mysql db如下:

修改maxwell的config.properties

# tl;dr config 生產環境配置爲info級別
log_level=DEBUG

producer=rabbitmq


# mysql login info, mysql用戶必須擁有讀取binlog權限和新建庫表的權限
host=127.0.0.1
user=xiehd
password=xiehd2018

output_nulls=true
# options to pass into the jdbc connection, given as opt=val&opt2=val2
#jdbc_options=opt1=100&opt2=hello
jdbc_options=autoReconnet=true

#需要同步的數據庫,表,及不包含的字段
include_dbs=xhd-sso
#include_tables=SYS_USER,SYS_ROLE
#exclude_columns=password

metrics_type=http
metrics_slf4j_interval=60
http_port=8111
http_diagnostic=true # default false


#rabbitmq
rabbitmq_host=192.168.50.184
rabbitmq_port=5672
rabbitmq_user=maxwell
rabbitmq_pass=maxwell@2018
rabbitmq_virtual_host=/
rabbitmq_exchange=maxwell
rabbitmq_exchange_type=topic
rabbitmq_exchange_durable=false
rabbitmq_exchange_autodelete=false
rabbitmq_routing_key_template=%db%.%table%
rabbitmq_message_persistent=false
rabbitmq_declare_exchange=true

啓動maxwell

./bin/maxwell

啓動成功

此時會自動生成maxwell庫,該庫記錄了maxwell同步的狀態,最後一次同步的id等等信息,在主庫失敗或同步異常後,只要maxwell庫存在,下次同步會根據最後一次同步的id。如果沒有生成maxwell庫或報錯,可能config.properties中配置的mysql用戶權限不夠

此時修改mysql中的SYS_ROLE表數據,maxwell控制檯會打印相應的json格式的日誌

rabbitMQ控制檯中會自動創建名稱爲maxwell的exchange(該exchange爲config.properties中配置的)

新建Queue並綁定exchange,並設置routingkey爲%db%.%table%(該routingkey爲config.properties中配置)

修改表SYS_USER中數據,此時修改的數據會被髮送到rabbitMQ

 一般情況下,一張表對應一個queue, 也可以多張表共用一個queue, 根據實際吞吐量靈活使用。

MQ消費端

新建一個MaxwellData

public class MaxwellData implements Serializable {
    private String type;
    private String database;
    private String table;
    private Map<String, Object> data;
    private Map<String, Object> old;

    public MaxwellData() {
    }

    public String getType() {
        return this.type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getDatabase() {
        return this.database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public String getTable() {
        return this.table;
    }

    public void setTable(String table) {
        this.table = table;
    }

    public Map<String, Object> getData() {
        return this.data;
    }

    public void setData(Map<String, Object> data) {
        this.data = data;
    }

    public Map<String, Object> getOld() {
        return this.old;
    }

    public void setOld(Map<String, Object> old) {
        this.old = old;
    }

解析maxwell數據

    @RabbitHandler
    @RabbitListener(queues = "SYS_USER")
    public void process(byte[] data) {
        String s = new String(data);
        MaxwellData maxwellData = decodeMsg(s);
        logger.info("maxwellData:" + maxwellData);
        //to do
    }
    private MaxwellData decodeMsg(String msg) {
        if (msg == null) {
            return null;
        }
        return JSON.parseObject(msg, MaxwellData.class);
    }

當然也可以同步到Redis, kafka, rocketMQ(rocketmq需要自行實現producer)等

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章