-
本文主要目的是實現Canal+disruptor+springboot,訂閱mysql binlog日誌,實現數據同步,比如緩存,ES等。
DEMO項目Github地址 -
組件簡介:
Canal-阿里巴巴mysql數據庫binlog的增量訂閱&消費組件
Disruptor-開源的併發框架,能夠在無鎖的情況下實現網絡的Queue併發操作 -
使用方式:
Canal的服務端搭建參考
Disruptor+Canal異步操作參考,業務集成時在DisruptorServiceImpl服務中實現自己的業務邏輯即可,代碼片段:
public void execute(TableData tableData)
{
if (log.isDebugEnabled())
{
log.debug("接受數據更新請求,更新表名:{},更新的主鍵爲:{}", tableData.getTableName(), tableData.getId());
}
if (null != tableData)
{
//業務處理 TODO
}
}
在CanalClientService中定製自己需要的binlog事件處理,代碼片段:
private void processData(List<CanalEntry.Entry> entrys)
{
if (log.isDebugEnabled())
{
log.debug("接收到需要處理數據,總數量:{}", entrys.size());
}
List<TableData> tableDataList = new ArrayList<>(entrys.size());
// 表名
String tableName;
TableData tableData;
CanalEntry.RowChange rowChange;
for (CanalEntry.Entry entry : entrys)
{
// 事物數據不處理
if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN
|| entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND)
{
continue;
}
if (entry.getEntryType() != CanalEntry.EntryType.ROWDATA)
{
continue;
}
//獲取表名
tableName = entry.getHeader().getTableName();
//僅處理部分表接口數據
if (tableNames.contains(tableName))
{
try
{
rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
// RowData --具體insert/update/delete的變更數據,可爲多條,1個binlog event事件可對應多條變更,比如批處理
for (CanalEntry.RowData rowData : rowChange.getRowDatasList())
{
switch (rowChange.getEventType())
{
//當前僅處理Insert和更新數據
case INSERT:
case UPDATE:
tableData = new TableData();
tableData.setTableName(tableName);
tableData.setId(parseKey(rowData.getAfterColumnsList()));
tableDataList.add(tableData);
break;
default:
break;
}
}
}
catch (Exception e)
{
log.error("當前行數據解析錯誤:", e);
}
}
}
if (CollectionUtil.isNotEmpty(tableDataList))
{
//發送數據到異步隊列框架
disruptorProducer.send(tableDataList);
}
if (log.isDebugEnabled())
{
log.debug("接收到Mysql更新數據,總數量:{}", tableDataList.size());
}
}