使用 阿里巴巴 Canal 增量訂閱&消費組件 同步 MySQL 數據到 Redis

使用 阿里巴巴 Canal 增量訂閱&消費組件 同步 MySQL 數據到 Redis

背景

《阿里巴巴的增量訂閱&消費組件》 https://github.com/alibaba/canal java

早期,阿里巴巴B2B公司由於存在杭州和美國雙機房部署,存在跨機房同步的業務需求。不過早期的數據庫同步業務,主要是基於trigger的方式獲取增量變動,不過從2010年開始,阿里系公司開始逐步的嘗試基於數據庫的日誌解析,獲取增量變動進行同步,由此衍生出了增量訂閱&消費的業務,今後開啓了一段新紀元。mysql

項目介紹

名稱:運河[kə'næl]git

譯意:水道/管道/溝渠github

語言:純java開發redis

定位:基於數據庫增量日誌解析,提供增量數據訂閱&消費,目前主要支持了mysqlsql

關鍵詞:mysql binlog解析器/實時/隊列和主題數據庫

基於日誌增量訂閱&消費支持的業務:apache

1.數據庫鏡像
2.數據庫實時備份
3.多級索引 (賣家和買家各自分庫索引)
4.search build
5.業務cache刷新
6.價格變化等重要業務消息segmentfault

工做原理

mysql主備複製實現

圖片描述
從上層來看,複製分紅三步:less

master將改變記錄到二進制日誌(binary log)中(這些記錄叫作二進制日誌事件,binary log events,能夠經過show binlog events進行查看);
slave將master的binary log events拷貝到它的中繼日誌(relay log);
slave重作中繼日誌中的事件,將改變反映它本身的數據。

CentOs7.3 搭建 MySQL 5.7.19 主從複製,以及複製實現細節分析

canal的工做原理

圖片描述

原理相對比較簡單:

1.運河模擬mysql slave的交互協議,假裝本身爲mysql slave,向mysql master發送dump協議
2.mysql master收到dump請求,開始推送二進制日誌給slave(也就是運河)
3.運河解析二進制對象(原始爲字節流)

canal的原理是基於mysql binlog技術,因此這裏必定須要開啓mysql的binlog寫入功能,建議配置binlog模式爲row.

針對阿里雲RDS帳號默認已經有binlog dump權限,不須要任何權限或者binlog設置,能夠直接跳過這一步

修改 etc/my.cnf

$ cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin     #添加這一行就ok
binlog-format=ROW     #選擇row模式
server_id=1           #配置mysql replaction須要定義,不能和canal的slaveId重複

一.配置步驟

MySQL 安裝

《CentOs7.3 安裝 MySQL 5.7.19 二進制版本》

1.下載canal

直接下載 訪問:https://github.com/alibaba/canal/releases,會列出全部歷史的發佈版本包 下載方式,好比以1.0.24版本爲例子:

$ ca /opt
$ wget https://github.com/alibaba/canal/releases/download/canal-1.0.24/canal.deployer-1.0.24.tar.gz

or 本身編譯

$ git clone git@github.com:alibaba/canal.git
$ cd canal; 
$ mvn clean install -Dmaven.test.skip -Denv=release

編譯完成後,會在根目錄下產生target/canal.deployer-$version.tar.gz

2.解壓縮

$ mkdir /opt/canal
$ tar zxvf canal.deployer-$version.tar.gz  -C /opt/canal

3.配置修改

應用參數:

$ vi conf/example/instance.properties
#################################################
## mysql serverId
canal.instance.mysql.slaveId = 1234

canal.instance.master.address 須要改爲本身的數據庫信息

canal.instance.master.address = 127.0.0.1:3306 
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =

#canal.instance.standby.address =
#canal.instance.standby.journal.name =
#canal.instance.standby.position =
#canal.instance.standby.timestamp =

username/password,須要改爲本身的數據庫信息

canal.instance.dbUsername = canal

canal.instance.dbPassword = canal

canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8

4.啓動

$ sh bin/startup.sh

5.查看日誌

$ less logs/canal/canal.log
$ less logs/example/example.log

6.中止

$ sh bin/stop.sh

二.安裝 Redis

本測試項目,選擇的是Redis 單機服務。集羣也支持

Redis 單機

CentOs7.3 搭建 Redis-4.0.1 單機服務

Redis 集羣

CentOs7.3 搭建 Redis-4.0.1 Cluster 集羣服務

三.同步Redis

alibaba / canal wiki

Canal提供的 ClientExample

1.建立庫表

CREATE DATABASE `test`;

use `test`;

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(1000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO `test` VALUES ('1', '同步MySQL數據到 Redis');

2.導入源碼

克隆,同步MySQL數據到 Redis項目https://github.com/souyunku/YmqExample

$ git clone https://github.com/souyunku/YmqExample.git

3.運行測試類

打開 ymq-alibaba-otter-canal 項目,運行 SimpleCanalTest 測試類

創建canal客戶端,從canal中獲取數據,並將數據更新至Redis

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import io.ymq.example.util.AbstractCanalClientTest;
import org.apache.commons.lang.exception.ExceptionUtils;

import java.net.InetSocketAddress;

/**
 * 單機模式的測試例子
 *
 * @author jianghang 2013-4-15 下午04:19:20
 * @version 1.0.4
 */
public class SimpleCanalClientTest extends AbstractCanalClientTest {

    public SimpleCanalClientTest(String destination) {
        super(destination);
    }

    public static void main(String args[]) {
        // 根據ip,直接建立連接,無HA的功能
        String destination = "example";
        // String ip = AddressUtils.getHostIp();

        CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("192.168.252.125", 11111),
                destination,
                "",
                "");

        final SimpleCanalClientTest clientTest = new SimpleCanalClientTest(destination);
        clientTest.setConnector(connector);
        clientTest.start();

        Runtime.getRuntime().addShutdownHook(new Thread() {

            public void run() {
                try {
                    logger.info("## stop the canal client");
                    clientTest.stop();
                } catch (Throwable e) {
                    logger.warn("##something goes wrong when stopping canal:\n{}", ExceptionUtils.getFullStackTrace(e));
                } finally {
                    logger.info("## canal client is down.");
                }
            }

        });
    }

4.更新數據

UPDATE `penglei`.`test` SET `id`='1', `name`='使用 Alibaba Canal 增量訂閱&消費組件,同步MySQL數據到 Redis' WHERE (`id`='1');

5.查看響應

****************************************************
* Batch Id: [27] ,count : [3] , memsize : [325] , Time : 2017-08-29 13:57:33
* Start : [mysql-bin.000005:13948:1503986259000(2017-08-29 13:57:39)] 
* End : [mysql-bin.000005:14295:1503986259000(2017-08-29 13:57:39)] 
****************************************************

================> binlog[mysql-bin.000005:13948] , executeTime : 1503986259000 , delay : -5057ms
 BEGIN ----> Thread id: 27
----------------> binlog[mysql-bin.000005:14076] , name[penglei,test] , eventType : UPDATE , executeTime : 1503986259000 , delay : -5057ms
id : 1    type=int(11)
name : 使用 阿里巴巴 Canal 增量訂閱&消費 binlog 同步 MySQL 數據到 Redis 集羣    type=varchar(1000)    update=true
-------> before
id : 1    type=int(11)
name : 使用 阿里巴巴 Canal 增量訂閱&消費 binlog 同步 MySQL 數據到 Redis    type=varchar(1000)
-------> after
----------------
 END ----> transaction id: 307
================> binlog[mysql-bin.000005:14295] , executeTime : 1503986259000 , delay : -5056ms

6.查看Redis

查看Redis 是否已經同步

$ /opt/redis-4.0.1/src/redis-cli -h 192.168.252.101 -c -p 6379
192.168.252.104:6379> get ymq-group:1

{
    "name": "使用 Alibaba Canal 增量訂閱&消費組件,同步MySQL數據到 Redis",
    "id": "1"
}

Contact

  • 做者:鵬磊
  • 出處:http://www.ymq.io
  • Email:admin@souyunku.com
  • 版權歸做者全部,轉載請註明出處
  • Wechat:關注公衆號,搜雲庫,專一於開發技術的研究與知識分享

關注公衆號-搜雲庫

相關文章
相關標籤/搜索