mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -62,10 +62,10 @@ public class HbaseAdapter implements OuterAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> propertites = configuration.getProperties();
|
Map<String, String> properties = configuration.getProperties();
|
||||||
|
|
||||||
Configuration hbaseConfig = HBaseConfiguration.create();
|
Configuration hbaseConfig = HBaseConfiguration.create();
|
||||||
propertites.forEach(hbaseConfig::set);
|
properties.forEach(hbaseConfig::set);
|
||||||
conn = ConnectionFactory.createConnection(hbaseConfig);
|
conn = ConnectionFactory.createConnection(hbaseConfig);
|
||||||
hbaseTemplate = new HbaseTemplate(conn);
|
hbaseTemplate = new HbaseTemplate(conn);
|
||||||
hbaseSyncService = new HbaseSyncService(hbaseTemplate);
|
hbaseSyncService = new HbaseSyncService(hbaseTemplate);
|
||||||
|
|||||||
@@ -166,6 +166,14 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<excludes>
|
||||||
|
<exclude>application.yml</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
servers: localhost:9876 #for rocketmq: means the nameserver
|
servers: slave1:6667 #for rocketmq: means the nameserver
|
||||||
retries: 0
|
retries: 0
|
||||||
batchSize: 16384
|
batchSize: 16384
|
||||||
lingerMs: 1
|
lingerMs: 1
|
||||||
@@ -13,7 +13,7 @@ flatMessage: true
|
|||||||
canalDestinations:
|
canalDestinations:
|
||||||
- canalDestination: example
|
- canalDestination: example
|
||||||
topic: example
|
topic: example
|
||||||
partition: 1
|
partition:
|
||||||
# #对应topic分区数量
|
# #对应topic分区数量
|
||||||
# partitionsNum: 3
|
# partitionsNum: 3
|
||||||
# partitionHash:
|
# partitionHash:
|
||||||
|
|||||||
@@ -353,7 +353,11 @@ public abstract class AbstractEventParser<EVENT> extends AbstractCanalLifeCycle
|
|||||||
eventSink.interrupt();
|
eventSink.interrupt();
|
||||||
|
|
||||||
if (multiStageCoprocessor != null && multiStageCoprocessor.isStart()) {
|
if (multiStageCoprocessor != null && multiStageCoprocessor.isStart()) {
|
||||||
multiStageCoprocessor.stop();
|
try {
|
||||||
|
multiStageCoprocessor.stop();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
logger.debug("multi processor rejected:", t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -37,21 +37,23 @@ import com.taobao.tddl.dbsync.binlog.LogBuffer;
|
|||||||
import com.taobao.tddl.dbsync.binlog.LogContext;
|
import com.taobao.tddl.dbsync.binlog.LogContext;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.FormatDescriptionLogEvent;
|
||||||
|
|
||||||
public class MysqlConnection implements ErosaConnection {
|
public class MysqlConnection implements ErosaConnection {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MysqlConnection.class);
|
private static final Logger logger = LoggerFactory.getLogger(MysqlConnection.class);
|
||||||
|
|
||||||
private MysqlConnector connector;
|
private MysqlConnector connector;
|
||||||
private long slaveId;
|
private long slaveId;
|
||||||
private Charset charset = Charset.forName("UTF-8");
|
private Charset charset = Charset.forName("UTF-8");
|
||||||
private BinlogFormat binlogFormat;
|
private BinlogFormat binlogFormat;
|
||||||
private BinlogImage binlogImage;
|
private BinlogImage binlogImage;
|
||||||
|
|
||||||
// tsdb releated
|
// tsdb releated
|
||||||
private AuthenticationInfo authInfo;
|
private AuthenticationInfo authInfo;
|
||||||
protected int connTimeout = 5 * 1000; // 5秒
|
protected int connTimeout = 5 * 1000; // 5秒
|
||||||
protected int soTimeout = 60 * 60 * 1000; // 1小时
|
protected int soTimeout = 60 * 60 * 1000; // 1小时
|
||||||
|
private int binlogChecksum = LogEvent.BINLOG_CHECKSUM_ALG_OFF;
|
||||||
// dump binlog bytes, 暂不包括meta与TSDB
|
// dump binlog bytes, 暂不包括meta与TSDB
|
||||||
private AtomicLong receivedBinlogBytes;
|
private AtomicLong receivedBinlogBytes;
|
||||||
|
|
||||||
@@ -118,7 +120,7 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
*/
|
*/
|
||||||
public void seek(String binlogfilename, Long binlogPosition, SinkFunction func) throws IOException {
|
public void seek(String binlogfilename, Long binlogPosition, SinkFunction func) throws IOException {
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
loadBinlogChecksum();
|
||||||
sendBinlogDump(binlogfilename, binlogPosition);
|
sendBinlogDump(binlogfilename, binlogPosition);
|
||||||
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
||||||
fetcher.start(connector.getChannel());
|
fetcher.start(connector.getChannel());
|
||||||
@@ -128,6 +130,7 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
decoder.handle(LogEvent.QUERY_EVENT);
|
decoder.handle(LogEvent.QUERY_EVENT);
|
||||||
decoder.handle(LogEvent.XID_EVENT);
|
decoder.handle(LogEvent.XID_EVENT);
|
||||||
LogContext context = new LogContext();
|
LogContext context = new LogContext();
|
||||||
|
context.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
|
||||||
while (fetcher.fetch()) {
|
while (fetcher.fetch()) {
|
||||||
accumulateReceivedBytes(fetcher.limit());
|
accumulateReceivedBytes(fetcher.limit());
|
||||||
LogEvent event = null;
|
LogEvent event = null;
|
||||||
@@ -145,12 +148,14 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
|
|
||||||
public void dump(String binlogfilename, Long binlogPosition, SinkFunction func) throws IOException {
|
public void dump(String binlogfilename, Long binlogPosition, SinkFunction func) throws IOException {
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
loadBinlogChecksum();
|
||||||
sendRegisterSlave();
|
sendRegisterSlave();
|
||||||
sendBinlogDump(binlogfilename, binlogPosition);
|
sendBinlogDump(binlogfilename, binlogPosition);
|
||||||
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
||||||
fetcher.start(connector.getChannel());
|
fetcher.start(connector.getChannel());
|
||||||
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
||||||
LogContext context = new LogContext();
|
LogContext context = new LogContext();
|
||||||
|
context.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
|
||||||
while (fetcher.fetch()) {
|
while (fetcher.fetch()) {
|
||||||
accumulateReceivedBytes(fetcher.limit());
|
accumulateReceivedBytes(fetcher.limit());
|
||||||
LogEvent event = null;
|
LogEvent event = null;
|
||||||
@@ -173,6 +178,7 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
@Override
|
@Override
|
||||||
public void dump(GTIDSet gtidSet, SinkFunction func) throws IOException {
|
public void dump(GTIDSet gtidSet, SinkFunction func) throws IOException {
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
loadBinlogChecksum();
|
||||||
sendBinlogDumpGTID(gtidSet);
|
sendBinlogDumpGTID(gtidSet);
|
||||||
|
|
||||||
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
||||||
@@ -180,6 +186,7 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
fetcher.start(connector.getChannel());
|
fetcher.start(connector.getChannel());
|
||||||
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
||||||
LogContext context = new LogContext();
|
LogContext context = new LogContext();
|
||||||
|
context.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
|
||||||
// fix bug: #890 将gtid传输至context中,供decode使用
|
// fix bug: #890 将gtid传输至context中,供decode使用
|
||||||
context.setGtidSet(gtidSet);
|
context.setGtidSet(gtidSet);
|
||||||
while (fetcher.fetch()) {
|
while (fetcher.fetch()) {
|
||||||
@@ -207,9 +214,11 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
@Override
|
@Override
|
||||||
public void dump(String binlogfilename, Long binlogPosition, MultiStageCoprocessor coprocessor) throws IOException {
|
public void dump(String binlogfilename, Long binlogPosition, MultiStageCoprocessor coprocessor) throws IOException {
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
loadBinlogChecksum();
|
||||||
sendRegisterSlave();
|
sendRegisterSlave();
|
||||||
sendBinlogDump(binlogfilename, binlogPosition);
|
sendBinlogDump(binlogfilename, binlogPosition);
|
||||||
((MysqlMultiStageCoprocessor) coprocessor).setConnection(this);
|
((MysqlMultiStageCoprocessor) coprocessor).setConnection(this);
|
||||||
|
((MysqlMultiStageCoprocessor) coprocessor).setBinlogChecksum(binlogChecksum);
|
||||||
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
||||||
try {
|
try {
|
||||||
fetcher.start(connector.getChannel());
|
fetcher.start(connector.getChannel());
|
||||||
@@ -234,9 +243,10 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
@Override
|
@Override
|
||||||
public void dump(GTIDSet gtidSet, MultiStageCoprocessor coprocessor) throws IOException {
|
public void dump(GTIDSet gtidSet, MultiStageCoprocessor coprocessor) throws IOException {
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
loadBinlogChecksum();
|
||||||
sendBinlogDumpGTID(gtidSet);
|
sendBinlogDumpGTID(gtidSet);
|
||||||
|
|
||||||
((MysqlMultiStageCoprocessor) coprocessor).setConnection(this);
|
((MysqlMultiStageCoprocessor) coprocessor).setConnection(this);
|
||||||
|
((MysqlMultiStageCoprocessor) coprocessor).setBinlogChecksum(binlogChecksum);
|
||||||
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
|
||||||
try {
|
try {
|
||||||
fetcher.start(connector.getChannel());
|
fetcher.start(connector.getChannel());
|
||||||
@@ -482,6 +492,52 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主库checksum信息
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* mariadb区别于mysql会在binlog的第一个事件Rotate_Event里也会采用checksum逻辑,而mysql是在第二个binlog事件之后才感知是否需要处理checksum
|
||||||
|
* 导致maraidb只要是开启checksum就会出现binlog文件名解析乱码
|
||||||
|
* fixed issue : https://github.com/alibaba/canal/issues/1081
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private void loadBinlogChecksum() {
|
||||||
|
if (checkMariaDB()) {
|
||||||
|
ResultSetPacket rs = null;
|
||||||
|
try {
|
||||||
|
rs = query("select @@global.binlog_checksum");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CanalParseException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> columnValues = rs.getFieldValues();
|
||||||
|
if (columnValues != null && columnValues.size() >= 1 && columnValues.get(0).toUpperCase().equals("CRC32")) {
|
||||||
|
binlogChecksum = LogEvent.BINLOG_CHECKSUM_ALG_CRC32;
|
||||||
|
} else {
|
||||||
|
binlogChecksum = LogEvent.BINLOG_CHECKSUM_ALG_OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取是否为mariadb
|
||||||
|
*/
|
||||||
|
private boolean checkMariaDB() {
|
||||||
|
ResultSetPacket rs = null;
|
||||||
|
try {
|
||||||
|
rs = query("SELECT @@version");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CanalParseException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> columnValues = rs.getFieldValues();
|
||||||
|
if (columnValues != null && columnValues.size() >= 1) {
|
||||||
|
return StringUtils.containsIgnoreCase(columnValues.get(0), "MariaDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void accumulateReceivedBytes(long x) {
|
private void accumulateReceivedBytes(long x) {
|
||||||
if (receivedBinlogBytes != null) {
|
if (receivedBinlogBytes != null) {
|
||||||
receivedBinlogBytes.addAndGet(x);
|
receivedBinlogBytes.addAndGet(x);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
// update by yishun.chen,特殊异常处理参数
|
// update by yishun.chen,特殊异常处理参数
|
||||||
private int dumpErrorCount = 0; // binlogDump失败异常计数
|
private int dumpErrorCount = 0; // binlogDump失败异常计数
|
||||||
private int dumpErrorCountThreshold = 2; // binlogDump失败异常计数阀值
|
private int dumpErrorCountThreshold = 2; // binlogDump失败异常计数阀值
|
||||||
|
private boolean rdsOssMode = false;
|
||||||
|
|
||||||
protected ErosaConnection buildErosaConnection() {
|
protected ErosaConnection buildErosaConnection() {
|
||||||
return buildMysqlConnection(this.runningInfo);
|
return buildMysqlConnection(this.runningInfo);
|
||||||
@@ -352,7 +353,7 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
return logPosition.getPostion();
|
return logPosition.getPostion();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (masterPosition!=null && StringUtils.isNotEmpty(masterPosition.getGtid())) {
|
if (masterPosition != null && StringUtils.isNotEmpty(masterPosition.getGtid())) {
|
||||||
return masterPosition;
|
return masterPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,6 +494,12 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
dumpErrorCount = 0;
|
dumpErrorCount = 0;
|
||||||
return findPosition;
|
return findPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Long timestamp = logPosition.getPostion().getTimestamp();
|
||||||
|
if (isRdsOssMode() && (timestamp != null && timestamp > 0)) {
|
||||||
|
// 如果binlog位点不存在,并且属于timestamp不为空,可以返回null走到oss binlog处理
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 其余情况
|
// 其余情况
|
||||||
logger.warn("prepare to find start position just last position\n {}",
|
logger.warn("prepare to find start position just last position\n {}",
|
||||||
@@ -745,14 +752,13 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
logPosition.setPostion(entryPosition);
|
logPosition.setPostion(entryPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry == null) {
|
// 直接用event的位点来处理,解决一个binlog文件里没有任何事件导致死循环无法退出的问题
|
||||||
return true;
|
String logfilename = event.getHeader().getLogFileName();
|
||||||
}
|
// 记录的是binlog end offest,
|
||||||
|
// 因为与其对比的offest是show master status里的end offest
|
||||||
String logfilename = entry.getHeader().getLogfileName();
|
Long logfileoffset = event.getHeader().getLogPos();
|
||||||
Long logfileoffset = entry.getHeader().getLogfileOffset();
|
Long logposTimestamp = event.getHeader().getWhen() * 1000;
|
||||||
Long logposTimestamp = entry.getHeader().getExecuteTime();
|
Long serverId = event.getHeader().getServerId();
|
||||||
Long serverId = entry.getHeader().getServerId();
|
|
||||||
|
|
||||||
// 如果最小的一条记录都不满足条件,可直接退出
|
// 如果最小的一条记录都不满足条件,可直接退出
|
||||||
if (logposTimestamp >= startTimestamp) {
|
if (logposTimestamp >= startTimestamp) {
|
||||||
@@ -764,6 +770,10 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 记录一下上一个事务结束的位置,即下一个事务的position
|
// 记录一下上一个事务结束的位置,即下一个事务的position
|
||||||
// position = current +
|
// position = current +
|
||||||
// data.length,代表该事务的下一条offest,避免多余的事务重复
|
// data.length,代表该事务的下一条offest,避免多余的事务重复
|
||||||
@@ -905,4 +915,12 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
this.dumpErrorCountThreshold = dumpErrorCountThreshold;
|
this.dumpErrorCountThreshold = dumpErrorCountThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRdsOssMode() {
|
||||||
|
return rdsOssMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRdsOssMode(boolean rdsOssMode) {
|
||||||
|
this.rdsOssMode = rdsOssMode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.taobao.tddl.dbsync.binlog.LogContext;
|
|||||||
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.DeleteRowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.DeleteRowsLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.FormatDescriptionLogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.RowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.RowsLogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.UpdateRowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.UpdateRowsLogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
||||||
@@ -69,6 +70,7 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
private WorkerPool<MessageEvent> workerPool;
|
private WorkerPool<MessageEvent> workerPool;
|
||||||
private BatchEventProcessor<MessageEvent> simpleParserStage;
|
private BatchEventProcessor<MessageEvent> simpleParserStage;
|
||||||
private BatchEventProcessor<MessageEvent> sinkStoreStage;
|
private BatchEventProcessor<MessageEvent> sinkStoreStage;
|
||||||
|
private LogContext logContext;
|
||||||
|
|
||||||
public MysqlMultiStageCoprocessor(int ringBufferSize, int parserThreadCount, LogEventConvert logEventConvert,
|
public MysqlMultiStageCoprocessor(int ringBufferSize, int parserThreadCount, LogEventConvert logEventConvert,
|
||||||
EventTransactionBuffer transactionBuffer, String destination){
|
EventTransactionBuffer transactionBuffer, String destination){
|
||||||
@@ -95,9 +97,10 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
SequenceBarrier sequenceBarrier = disruptorMsgBuffer.newBarrier();
|
SequenceBarrier sequenceBarrier = disruptorMsgBuffer.newBarrier();
|
||||||
ExceptionHandler exceptionHandler = new SimpleFatalExceptionHandler();
|
ExceptionHandler exceptionHandler = new SimpleFatalExceptionHandler();
|
||||||
// stage 2
|
// stage 2
|
||||||
|
this.logContext = new LogContext();
|
||||||
simpleParserStage = new BatchEventProcessor<MessageEvent>(disruptorMsgBuffer,
|
simpleParserStage = new BatchEventProcessor<MessageEvent>(disruptorMsgBuffer,
|
||||||
sequenceBarrier,
|
sequenceBarrier,
|
||||||
new SimpleParserStage());
|
new SimpleParserStage(logContext));
|
||||||
simpleParserStage.setExceptionHandler(exceptionHandler);
|
simpleParserStage.setExceptionHandler(exceptionHandler);
|
||||||
disruptorMsgBuffer.addGatingSequences(simpleParserStage.getSequence());
|
disruptorMsgBuffer.addGatingSequences(simpleParserStage.getSequence());
|
||||||
|
|
||||||
@@ -128,6 +131,12 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
workerPool.start(parserExecutor);
|
workerPool.start(parserExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBinlogChecksum(int binlogChecksum) {
|
||||||
|
if (binlogChecksum != LogEvent.BINLOG_CHECKSUM_ALG_OFF) {
|
||||||
|
logContext.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
// fix bug #968,对于pool与
|
// fix bug #968,对于pool与
|
||||||
@@ -239,9 +248,9 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
private LogDecoder decoder;
|
private LogDecoder decoder;
|
||||||
private LogContext context;
|
private LogContext context;
|
||||||
|
|
||||||
public SimpleParserStage(){
|
public SimpleParserStage(LogContext context){
|
||||||
decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
||||||
context = new LogContext();
|
this.context = context;
|
||||||
if (gtidSet != null) {
|
if (gtidSet != null) {
|
||||||
context.setGtidSet(gtidSet);
|
context.setGtidSet(gtidSet);
|
||||||
}
|
}
|
||||||
@@ -468,4 +477,5 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
public void setGtidSet(GTIDSet gtidSet) {
|
public void setGtidSet(GTIDSet gtidSet) {
|
||||||
this.gtidSet = gtidSet;
|
this.gtidSet = gtidSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -567,8 +567,7 @@ public class LogEventConvert extends AbstractCanalLifeCycle implements BinlogPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private EntryPosition createPosition(LogHeader logHeader) {
|
private EntryPosition createPosition(LogHeader logHeader) {
|
||||||
return new EntryPosition(logHeader.getLogFileName(),
|
return new EntryPosition(logHeader.getLogFileName(), logHeader.getLogPos() - logHeader.getEventLen(), // startPos
|
||||||
logHeader.getLogPos(),
|
|
||||||
logHeader.getWhen() * 1000L,
|
logHeader.getWhen() * 1000L,
|
||||||
logHeader.getServerId()); // 记录到秒
|
logHeader.getServerId()); // 记录到秒
|
||||||
}
|
}
|
||||||
@@ -818,6 +817,7 @@ public class LogEventConvert extends AbstractCanalLifeCycle implements BinlogPar
|
|||||||
Header.Builder headerBuilder = Header.newBuilder();
|
Header.Builder headerBuilder = Header.newBuilder();
|
||||||
headerBuilder.setVersion(version);
|
headerBuilder.setVersion(version);
|
||||||
headerBuilder.setLogfileName(logHeader.getLogFileName());
|
headerBuilder.setLogfileName(logHeader.getLogFileName());
|
||||||
|
// 记录的是该binlog的start offest
|
||||||
headerBuilder.setLogfileOffset(logHeader.getLogPos() - logHeader.getEventLen());
|
headerBuilder.setLogfileOffset(logHeader.getLogPos() - logHeader.getEventLen());
|
||||||
headerBuilder.setServerId(logHeader.getServerId());
|
headerBuilder.setServerId(logHeader.getServerId());
|
||||||
headerBuilder.setServerenCode(UTF_8);// 经过java输出后所有的编码为unicode
|
headerBuilder.setServerenCode(UTF_8);// 经过java输出后所有的编码为unicode
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.apache.http.ssl.TrustStrategy;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.parse.exception.CanalParseException;
|
||||||
import com.alibaba.otter.canal.parse.inbound.mysql.rds.data.BinlogFile;
|
import com.alibaba.otter.canal.parse.inbound.mysql.rds.data.BinlogFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,6 +104,9 @@ public class BinlogDownloadQueue {
|
|||||||
|
|
||||||
public BinlogFile tryOne() throws Throwable {
|
public BinlogFile tryOne() throws Throwable {
|
||||||
BinlogFile binlogFile = binlogList.poll();
|
BinlogFile binlogFile = binlogList.poll();
|
||||||
|
if (binlogFile == null) {
|
||||||
|
throw new CanalParseException("download binlog is null");
|
||||||
|
}
|
||||||
download(binlogFile);
|
download(binlogFile);
|
||||||
hostId = binlogFile.getHostInstanceID();
|
hostId = binlogFile.getHostInstanceID();
|
||||||
this.currentSize++;
|
this.currentSize++;
|
||||||
@@ -131,7 +135,7 @@ public class BinlogDownloadQueue {
|
|||||||
if (StringUtils.isNotEmpty(needCompareName) && StringUtils.endsWith(needCompareName, "tar")) {
|
if (StringUtils.isNotEmpty(needCompareName) && StringUtils.endsWith(needCompareName, "tar")) {
|
||||||
needCompareName = needCompareName.substring(0, needCompareName.indexOf("."));
|
needCompareName = needCompareName.substring(0, needCompareName.indexOf("."));
|
||||||
}
|
}
|
||||||
return fileName.equalsIgnoreCase(needCompareName) && binlogList.isEmpty();
|
return (needCompareName == null || fileName.equalsIgnoreCase(needCompareName)) && binlogList.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepare() throws InterruptedException {
|
public void prepare() throws InterruptedException {
|
||||||
@@ -162,6 +166,14 @@ public class BinlogDownloadQueue {
|
|||||||
this.currentSize = 0;
|
this.currentSize = 0;
|
||||||
binlogList.clear();
|
binlogList.clear();
|
||||||
downloadQueue.clear();
|
downloadQueue.clear();
|
||||||
|
try {
|
||||||
|
downloadThread.interrupt();
|
||||||
|
downloadThread.join();// 等待其结束
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// ignore
|
||||||
|
} finally {
|
||||||
|
downloadThread = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void download(BinlogFile binlogFile) throws Throwable {
|
private void download(BinlogFile binlogFile) throws Throwable {
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import com.alibaba.otter.canal.parse.inbound.mysql.MysqlEventParser;
|
|||||||
*/
|
*/
|
||||||
public class RdsBinlogEventParserProxy extends MysqlEventParser {
|
public class RdsBinlogEventParserProxy extends MysqlEventParser {
|
||||||
|
|
||||||
private String rdsOpenApiUrl = "https://rds.aliyuncs.com/"; // openapi地址
|
private String rdsOpenApiUrl = "https://rds.aliyuncs.com/"; // openapi地址
|
||||||
private String accesskey; // 云账号的ak
|
private String accesskey; // 云账号的ak
|
||||||
private String secretkey; // 云账号sk
|
private String secretkey; // 云账号sk
|
||||||
private String instanceId; // rds实例id
|
private String instanceId; // rds实例id
|
||||||
private String directory; // binlog目录
|
private String directory; // binlog目录
|
||||||
private int batchFileSize = 4; // 最多下载的binlog文件数量
|
private int batchFileSize = 4; // 最多下载的binlog文件数量
|
||||||
|
|
||||||
private RdsLocalBinlogEventParser rdsLocalBinlogEventParser = new RdsLocalBinlogEventParser();
|
private RdsLocalBinlogEventParser rdsLocalBinlogEventParser = null;
|
||||||
private ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
private ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -43,8 +43,11 @@ public class RdsBinlogEventParserProxy extends MysqlEventParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (StringUtils.isNotEmpty(accesskey) && StringUtils.isNotEmpty(secretkey)
|
if (rdsLocalBinlogEventParser == null && StringUtils.isNotEmpty(accesskey) && StringUtils.isNotEmpty(secretkey)
|
||||||
&& StringUtils.isNotEmpty(instanceId)) {
|
&& StringUtils.isNotEmpty(instanceId)) {
|
||||||
|
rdsLocalBinlogEventParser = new RdsLocalBinlogEventParser();
|
||||||
|
// rds oss mode
|
||||||
|
setRdsOssMode(true);
|
||||||
final ParserExceptionHandler targetHandler = this.getParserExceptionHandler();
|
final ParserExceptionHandler targetHandler = this.getParserExceptionHandler();
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
directory = System.getProperty("java.io.tmpdir", "/tmp") + "/" + destination;
|
directory = System.getProperty("java.io.tmpdir", "/tmp") + "/" + destination;
|
||||||
@@ -119,10 +122,18 @@ public class RdsBinlogEventParserProxy extends MysqlEventParser {
|
|||||||
long serverId = rdsBinlogEventParserProxy.getServerId();
|
long serverId = rdsBinlogEventParserProxy.getServerId();
|
||||||
rdsLocalBinlogEventParser.setServerId(serverId);
|
rdsLocalBinlogEventParser.setServerId(serverId);
|
||||||
rdsBinlogEventParserProxy.stop();
|
rdsBinlogEventParserProxy.stop();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.info("handle exception failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
logger.info("start rds mysql binlog parser!");
|
logger.info("start rds mysql binlog parser!");
|
||||||
rdsLocalBinlogEventParser.start();
|
rdsLocalBinlogEventParser.start();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.info("handle exception failed", e);
|
logger.info("handle exception failed", e);
|
||||||
|
rdsLocalBinlogEventParser.stop();
|
||||||
|
RdsBinlogEventParserProxy rdsBinlogEventParserProxy = RdsBinlogEventParserProxy.this;
|
||||||
|
rdsBinlogEventParserProxy.start();// 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ public class RdsLocalBinlogEventParser extends LocalBinlogEventParser implements
|
|||||||
if (entryPosition == null) {
|
if (entryPosition == null) {
|
||||||
throw new PositionNotFoundException("position not found!");
|
throw new PositionNotFoundException("position not found!");
|
||||||
}
|
}
|
||||||
long startTimeInMill = entryPosition.getTimestamp();
|
Long startTimeInMill = entryPosition.getTimestamp();
|
||||||
|
if (startTimeInMill == null || startTimeInMill <= 0) {
|
||||||
|
throw new PositionNotFoundException("position timestamp is empty!");
|
||||||
|
}
|
||||||
|
|
||||||
startTime = startTimeInMill;
|
startTime = startTimeInMill;
|
||||||
List<BinlogFile> binlogFiles = RdsBinlogOpenApi.listBinlogFiles(url,
|
List<BinlogFile> binlogFiles = RdsBinlogOpenApi.listBinlogFiles(url,
|
||||||
accesskey,
|
accesskey,
|
||||||
@@ -65,6 +69,10 @@ public class RdsLocalBinlogEventParser extends LocalBinlogEventParser implements
|
|||||||
instanceId,
|
instanceId,
|
||||||
new Date(startTime),
|
new Date(startTime),
|
||||||
new Date(endTime));
|
new Date(endTime));
|
||||||
|
if (binlogFiles.isEmpty()) {
|
||||||
|
throw new CanalParseException("start timestamp : " + startTimeInMill + " binlog files is empty");
|
||||||
|
}
|
||||||
|
|
||||||
binlogDownloadQueue = new BinlogDownloadQueue(binlogFiles, batchFileSize, directory);
|
binlogDownloadQueue = new BinlogDownloadQueue(binlogFiles, batchFileSize, directory);
|
||||||
binlogDownloadQueue.silenceDownload();
|
binlogDownloadQueue.silenceDownload();
|
||||||
needWait = true;
|
needWait = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.alibaba.otter.canal.parse;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@@ -10,21 +11,27 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.MysqlConnector;
|
import com.alibaba.otter.canal.parse.driver.mysql.MysqlConnector;
|
||||||
|
import com.alibaba.otter.canal.parse.driver.mysql.MysqlQueryExecutor;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.MysqlUpdateExecutor;
|
import com.alibaba.otter.canal.parse.driver.mysql.MysqlUpdateExecutor;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.HeaderPacket;
|
import com.alibaba.otter.canal.parse.driver.mysql.packets.HeaderPacket;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.client.BinlogDumpCommandPacket;
|
import com.alibaba.otter.canal.parse.driver.mysql.packets.client.BinlogDumpCommandPacket;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.client.RegisterSlaveCommandPacket;
|
import com.alibaba.otter.canal.parse.driver.mysql.packets.client.RegisterSlaveCommandPacket;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.server.ErrorPacket;
|
import com.alibaba.otter.canal.parse.driver.mysql.packets.server.ErrorPacket;
|
||||||
|
import com.alibaba.otter.canal.parse.driver.mysql.packets.server.ResultSetPacket;
|
||||||
import com.alibaba.otter.canal.parse.driver.mysql.utils.PacketManager;
|
import com.alibaba.otter.canal.parse.driver.mysql.utils.PacketManager;
|
||||||
|
import com.alibaba.otter.canal.parse.exception.CanalParseException;
|
||||||
import com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher;
|
import com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogContext;
|
import com.taobao.tddl.dbsync.binlog.LogContext;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
||||||
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.FormatDescriptionLogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.RotateLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.RotateLogEvent;
|
||||||
|
|
||||||
public class DirectLogFetcherTest {
|
public class DirectLogFetcherTest {
|
||||||
|
|
||||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
private boolean isMariaDB;
|
||||||
|
private int binlogChecksum;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimple() {
|
public void testSimple() {
|
||||||
@@ -33,6 +40,7 @@ public class DirectLogFetcherTest {
|
|||||||
MysqlConnector connector = new MysqlConnector(new InetSocketAddress("127.0.0.1", 3306), "xxxx", "xxxx");
|
MysqlConnector connector = new MysqlConnector(new InetSocketAddress("127.0.0.1", 3306), "xxxx", "xxxx");
|
||||||
connector.connect();
|
connector.connect();
|
||||||
updateSettings(connector);
|
updateSettings(connector);
|
||||||
|
loadBinlogChecksum(connector);
|
||||||
sendRegisterSlave(connector, 3);
|
sendRegisterSlave(connector, 3);
|
||||||
sendBinlogDump(connector, "mysql-bin.000001", 4L, 3);
|
sendBinlogDump(connector, "mysql-bin.000001", 4L, 3);
|
||||||
|
|
||||||
@@ -40,6 +48,8 @@ public class DirectLogFetcherTest {
|
|||||||
|
|
||||||
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
||||||
LogContext context = new LogContext();
|
LogContext context = new LogContext();
|
||||||
|
context.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
|
||||||
|
|
||||||
while (fetcher.fetch()) {
|
while (fetcher.fetch()) {
|
||||||
LogEvent event = null;
|
LogEvent event = null;
|
||||||
event = decoder.decode(fetcher, context);
|
event = decoder.decode(fetcher, context);
|
||||||
@@ -188,6 +198,44 @@ public class DirectLogFetcherTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadBinlogChecksum(MysqlConnector connector) {
|
||||||
|
checkMariaDB(connector);
|
||||||
|
if (isMariaDB) {
|
||||||
|
ResultSetPacket rs = null;
|
||||||
|
try {
|
||||||
|
rs = query("select @@global.binlog_checksum", connector);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CanalParseException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> columnValues = rs.getFieldValues();
|
||||||
|
if (columnValues != null && columnValues.size() >= 1 && columnValues.get(0).toUpperCase().equals("CRC32")) {
|
||||||
|
binlogChecksum = LogEvent.BINLOG_CHECKSUM_ALG_CRC32;
|
||||||
|
} else {
|
||||||
|
binlogChecksum = LogEvent.BINLOG_CHECKSUM_ALG_OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMariaDB(MysqlConnector connector) {
|
||||||
|
ResultSetPacket rs = null;
|
||||||
|
try {
|
||||||
|
rs = query("SELECT @@version", connector);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CanalParseException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> columnValues = rs.getFieldValues();
|
||||||
|
if (columnValues != null && columnValues.size() >= 1) {
|
||||||
|
isMariaDB = StringUtils.containsIgnoreCase(columnValues.get(0), "MariaDB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSetPacket query(String cmd, MysqlConnector connector) throws IOException {
|
||||||
|
MysqlQueryExecutor exector = new MysqlQueryExecutor(connector);
|
||||||
|
return exector.query(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
public void update(String cmd, MysqlConnector connector) throws IOException {
|
public void update(String cmd, MysqlConnector connector) throws IOException {
|
||||||
MysqlUpdateExecutor exector = new MysqlUpdateExecutor(connector);
|
MysqlUpdateExecutor exector = new MysqlUpdateExecutor(connector);
|
||||||
exector.update(cmd);
|
exector.update(cmd);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import com.google.protobuf.WireFormat;
|
|||||||
public class CanalMessageSerializer {
|
public class CanalMessageSerializer {
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static byte[] serializer(Message data) {
|
public static byte[] serializer(Message data, boolean filterTransactionEntry) {
|
||||||
try {
|
try {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
if (data.getId() != -1) {
|
if (data.getId() != -1) {
|
||||||
@@ -53,8 +53,14 @@ public class CanalMessageSerializer {
|
|||||||
output.checkNoSpaceLeft();
|
output.checkNoSpaceLeft();
|
||||||
return body;
|
return body;
|
||||||
} else if (!CollectionUtils.isEmpty(data.getEntries())) {
|
} else if (!CollectionUtils.isEmpty(data.getEntries())) {
|
||||||
|
// mq模式只会走到非rowEntry模式
|
||||||
CanalPacket.Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
|
CanalPacket.Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
|
||||||
for (CanalEntry.Entry entry : data.getEntries()) {
|
for (CanalEntry.Entry entry : data.getEntries()) {
|
||||||
|
if (filterTransactionEntry
|
||||||
|
&& (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
messageBuilder.addMessages(entry.toByteString());
|
messageBuilder.addMessages(entry.toByteString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.alibaba.otter.canal.kafka;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.BooleanUtils;
|
||||||
import org.apache.kafka.common.serialization.Serializer;
|
import org.apache.kafka.common.serialization.Serializer;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.common.CanalMessageSerializer;
|
import com.alibaba.otter.canal.common.CanalMessageSerializer;
|
||||||
@@ -15,13 +16,20 @@ import com.alibaba.otter.canal.protocol.Message;
|
|||||||
*/
|
*/
|
||||||
public class MessageSerializer implements Serializer<Message> {
|
public class MessageSerializer implements Serializer<Message> {
|
||||||
|
|
||||||
|
private boolean filterTransactionEntry = false;
|
||||||
|
|
||||||
|
public MessageSerializer(){
|
||||||
|
this.filterTransactionEntry = BooleanUtils.toBoolean(System.getProperty("canal.instance.filter.transaction.entry",
|
||||||
|
"false"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(Map<String, ?> configs, boolean isKey) {
|
public void configure(Map<String, ?> configs, boolean isKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(String topic, Message data) {
|
public byte[] serialize(String topic, Message data) {
|
||||||
return CanalMessageSerializer.serializer(data);
|
return CanalMessageSerializer.serializer(data, filterTransactionEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
|||||||
Callback callback) {
|
Callback callback) {
|
||||||
if (!mqProperties.getFlatMessage()) {
|
if (!mqProperties.getFlatMessage()) {
|
||||||
try {
|
try {
|
||||||
Message message = new Message(destination.getTopic(), CanalMessageSerializer.serializer(data));
|
Message message = new Message(destination.getTopic(), CanalMessageSerializer.serializer(data,
|
||||||
|
mqProperties.isFilterTransactionEntry()));
|
||||||
logger.debug("send message:{} to destination:{}, partition: {}",
|
logger.debug("send message:{} to destination:{}, partition: {}",
|
||||||
message,
|
message,
|
||||||
destination.getCanalDestination(),
|
destination.getCanalDestination(),
|
||||||
@@ -77,8 +78,8 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
|||||||
JSON.toJSONString(flatMessage),
|
JSON.toJSONString(flatMessage),
|
||||||
destination.getTopic(),
|
destination.getTopic(),
|
||||||
destination.getPartition());
|
destination.getPartition());
|
||||||
Message message = new Message(destination.getTopic(), JSON.toJSONString(flatMessage)
|
Message message = new Message(destination.getTopic(),
|
||||||
.getBytes());
|
JSON.toJSONString(flatMessage).getBytes());
|
||||||
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -98,28 +99,32 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
|||||||
int length = partitionFlatMessage.length;
|
int length = partitionFlatMessage.length;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
FlatMessage flatMessagePart = partitionFlatMessage[i];
|
FlatMessage flatMessagePart = partitionFlatMessage[i];
|
||||||
logger.debug("flatMessagePart: {}, partition: {}",
|
if (flatMessagePart != null) {
|
||||||
JSON.toJSONString(flatMessagePart),
|
logger.debug("flatMessagePart: {}, partition: {}",
|
||||||
i);
|
JSON.toJSONString(flatMessagePart),
|
||||||
final int index = i;
|
i);
|
||||||
try {
|
final int index = i;
|
||||||
Message message = new Message(destination.getTopic(),
|
try {
|
||||||
JSON.toJSONString(flatMessagePart).getBytes());
|
Message message = new Message(destination.getTopic(),
|
||||||
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
JSON.toJSONString(flatMessagePart).getBytes());
|
||||||
|
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
public MessageQueue select(List<MessageQueue> mqs, Message msg,
|
||||||
if (index > mqs.size()) {
|
Object arg) {
|
||||||
throw new CanalServerException("partition number is error,config num:"
|
if (index > mqs.size()) {
|
||||||
+ destination.getPartitionsNum()
|
throw new CanalServerException(
|
||||||
+ ", mq num: " + mqs.size());
|
"partition number is error,config num:"
|
||||||
|
+ destination.getPartitionsNum()
|
||||||
|
+ ", mq num: " + mqs.size());
|
||||||
|
}
|
||||||
|
return mqs.get(index);
|
||||||
}
|
}
|
||||||
return mqs.get(index);
|
}, null);
|
||||||
}
|
} catch (Exception e) {
|
||||||
}, null);
|
logger.error("send flat message to hashed partition error", e);
|
||||||
} catch (Exception e) {
|
callback.rollback();
|
||||||
logger.error("send flat message to hashed partition error", e);
|
}
|
||||||
callback.rollback();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user