模拟业务场景:
一个大型的电商网站,每天都需要分析当天的成交量。如果使用mysql去分析,会非常慢 ,甚至会导致mysql宕机。要进行海量数据分析,需要将mysql中的数据同步到其他的海量数据存储介质(HDFS、hbase)中。那如何来导出呢?
sqoop 解决方案一:
- 使用sqoop定期导出mysql的数据到hbase或hdfs
- sqoop导出mysql的数据,需要通过sql语句来查询数据,再执行导出
存在的问题
mysql本来压力就比较大,sqoop再执行查询时,还需要执行sql查询,到加大mysql的压力,导致mysql速度更慢
logstash 解决方案二
- 通过logstash将mysql的数据抽取到kafka
- 在 logstatsh编写sql语句,从mysql中查询数据
存在的问题
logstash也需要在mysql中执行sql语句,也会加大mysql的压力,拖慢mysql
canal 解决方案三
- 通过 canal 来解析mysql中的binlog日志来获取数据
- 不需要使用sql查询mysql,不会增加mysql的压力
实际操作步骤:
推荐使用sqlyog来创建数据库、创建表
- 创建数据库
- 创建数据库表
- mysql开启binlog
binlog 日志介绍
- 用来记录mysql中的 增加 、删除 、修改操作
- select操作不会保存到binlog中
- 必须要 打开 mysql中的binlog功能,才会生成binlog日志
- binlog日志就是一系列的二进制文件
开启 binlog
步骤
- 修改mysql配置文件,添加binlog支持
- 重启mysql,查看binlog是否配置成功
实现
- 使用vi打开 /etc/my.cnf
- 添加以下配置
[mysqld]
log-bin=/var/lib/mysql/mysql-bin
binlog-format=ROW
server_id=1
配置说明
#配置binlog日志的存放路径为/var/lib/mysql目录,文件以mysql-bin开头
log-bin=/var/lib/mysql/mysql-bin
配置mysql中每一行记录的变化都会详细记录下来
binlog-format=ROW
配置当前机器器的服务ID(如果是mysql集群,不能重复)
server_id=1
6. 重启mysql
service mysql restart
7. mysql -u root -p 登录到mysql,执行以下命令
show variables like ‘%log_bin%’;
8. mysql输出以下内容,表示binlog已经成功开启
9. 进入到 /var/lib/mysql 可以查看到mysql-bin.000001文件已经生成
Canal原理
10. Canal模拟mysql slave的交互协议,伪装自己为mysql slave
11. 向mysql master发送dump协议
12. mysql master收到dump协议,发送binary log给slave(canal)
13. canal解析binary log字节流对象
Canal采集程序搭建
使用java语言将canal中的binlog日志解析,并写入到Kafka中
编写配置文件加载代码
- 创建 GlobalConfigUtil 工具类,读取 application.properties 中的 canal 和 kafka 配置
- 添加main方法,测试是否能正确读取配置
实现
创建GlobalConfigUtil,用来读取application.properties中的配置。使用以下代码来读取application.properties 中的配置
ResourceBundle bundle = ResourceBundle.getBundle("配置文件名", Locale.ENGLISH);
String host = bundle.getString("属性key");
将 application.properties中的canal 和kafka配置读取出来
编写main方法测试是否能够正确读取配置
参考代码
public class GlobalConfigUtil {
public static ResourceBundle bundle = ResourceBundle.getBundle("application", Locale.ENGLISH);
public static String canalHost = bundle.getString("canal.host");
public static String canalPort = bundle.getString("canal.port");
public static String canalInstance = bundle.getString("canal.instance");
public static String mysqlUsername = bundle.getString("mysql.username");
public static String mysqlPassword = bundle.getString("mysql.password");
public static String kafkaBootstrapServers = bundle.getString("kafka.bootstrap.servers");
public static String kafkaZookeeperConnect = bundle.getString("kafka.zookeeper.connect");
public static String kafkaInputTopic = bundle.getString("kafka.input.topic");
public static void main(String[] args) {
System.out.println(canalHost);
System.out.println(canalPort);
System.out.println(canalInstance);
System.out.println(mysqlUsername);
System.out.println(mysqlPassword);
System.out.println(kafkaBootstrapServers);
System.out.println(kafkaZookeeperConnect);
System.out.println(kafkaInputTopic);
}
}
注意:
使用ResourceBundle.getBundle(“application”, Locale.ENGLISH); 读取 application.properties 读取配置文件, 不需要写后缀名
编写Kafka工具类代码KafkaSender.java
/**
* Kafka生产消息工具类
*/