连接数据库的时候需要给予连接数据库权限:在my.ini配置文件里加上 log-bin=mysql-bin 这个就行了
连接数据库的账号需要授权
CREATE USER cqlpz IDENTIFIED BY 'cqlpz';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'cqlpz'@'%';
FLUSH PRIVILEGES; 创建一个账号并给予权限
解压出来有4个目录
2.conf 里面
canal.properties 配置canal自己的 比如多个服务连接,canal缓存名称
这是example里面的内容;
两个properties就是配置自己的数据库连接,meta.dat相当于启动canal服务过后的额缓存信息
3.lib 就是canal需要的jar
4.logs 日志文件
maven引入jar
1
2 com.alibaba.otter
3 canal.client
4 1.0.25
5
6
7 redis.clients
8 jedis
9 2.9.0
10
java代码
1.连接canal服务
// 创建链接
CanalConnector connector =CanalConnectors.newSingleConnector(
newInetSocketAddress(AddressUtils.getHostIp(), 端口),
"canal名称(虚拟数据名)",
"数据库账号",
"数据库密码");
2.连接某个数据库
connector.connect();
connector.subscribe("监控的数据库\\..*");
connector.rollback();
3.获取操作的事件
Message message = connector.getWithoutAck(数量); // 获取指定数量的数据
List entrys=message.getEntries();
for(Entry entry : entrys) {
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN ||entry.getEntryType() ==EntryType.TRANSACTIONEND) {
continue;
}
RowChange rowChage = null;
try{
rowChage =RowChange.parseFrom(entry.getStoreValue());
} catch(InvalidProtocolBufferException e) {
System.out.println("获取数据失败:"+e.getMessage());
}
EventType eventType =rowChage.getEventType();
for(RowData rowData : rowChage.getRowDatasList()) {
if(eventType.equals(EventType.DELETE)) {
rowData.getBeforeColumnsList();//删除的所有数据
} else if(eventType.equals(EventType.INSERT)) {
rowData.getAfterColumnsList();//添加的所有数据
}else if(eventType.equals(EventType.UPDATE)) {
rowData.getAfterColumnsList();//修改的所有数据
}}
完整的java类
public classClientSample {private static Logger logger = LoggerFactory.getLogger(ClientSample.class);public voidstartCanalThread(){
Thread thread= newStartCanalThread();
thread.start();
}/*** canal 线程*/
public class StartCanalThread extendsThread {
@Overridepublic voidrun() {//创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("localhost", 11111),"longpizi","longpizi","cqlongpizi");
connector.connect();
connector.subscribe("test\\..*");
connector.rollback();try{while (true) {//获取指定数量的数据
Message message = connector.getWithoutAck(1000);long batchId =message.getId();if (batchId != -1 && message.getEntries().size() > 0) {
printEntry(message.getEntries());
}
connector.ack(batchId);//提交确认
Thread.sleep(2000);
}
}catch(Exception e){
logger.error("Canal线程异常,已终止:"+e.getMessage());
}finally{//中断Canal连接
connector.disconnect();
}
}
}/*** 数据库执行的操作
*@paramentrys*/
private static void printEntry( Listentrys) {for(Entry entry : entrys) {//操作事物 忽略
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) { continue; }
RowChange rowChage= null;//执行事件信息
String database=null;//执行的数据库
String table=null;//执行的表
try{
database=entry.getHeader().getSchemaName();
table=entry.getHeader().getTableName();
rowChage=RowChange.parseFrom(entry.getStoreValue());
}catch(InvalidProtocolBufferException e) {
logger.error("获取数据失败:"+e.getMessage());
}//获取执行的事件
EventType eventType =rowChage.getEventType();for(RowData rowData : rowChage.getRowDatasList()) {//删除操作
if(eventType.equals(EventType.DELETE)) {
redisDelete(rowData.getBeforeColumnsList(),database,table);
}//添加操作
else if(eventType.equals(EventType.INSERT)) {
redisInsert(rowData.getAfterColumnsList(),database,table);
}//修改操作
else if(eventType.equals(EventType.UPDATE)) {
redisUpdate(rowData.getAfterColumnsList(),database,table);
}//修改表结构
else if(eventType.equals(EventType.ALTER)){
logger.info("修改表结构");
}
}
}
}/*** 数据库执行了添加操作
*@paramcolumns
*@paramdatabase
*@paramtable*/
private static void redisInsert( Listcolumns,String database,String table){
JSONObject json=newJSONObject();for(Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>添加数据:"+JSON.toJSONString(json));
}/*** 数据库执行了修改操作
*@paramcolumns
*@paramdatabase
*@paramtable*/
private static void redisUpdate( Listcolumns,String database,String table){
JSONObject json=newJSONObject();for(Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>修改数据:"+JSON.toJSONString(json));
}/*** 数据库执行了删除操作
*@paramcolumns
*@paramdatabase
*@paramtable*/
private static void redisDelete( Listcolumns,String database,String table){
JSONObject json=newJSONObject();for(Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>删除数据:"+JSON.toJSONString(json));
}
}
这样就可把操作的数据更新到redis里面了