提交 bc056288 编写于 作者: M mcy

rdb 批量提交优化

上级 fc6c8713
...@@ -28,16 +28,16 @@ canal.conf: ...@@ -28,16 +28,16 @@ canal.conf:
- instance: example - instance: example
groups: groups:
- outAdapters: - outAdapters:
# - name: logger - name: logger
- name: rdb # - name: rdb
key: oracle1 # key: oracle1
properties: # properties:
jdbc.driverClassName: oracle.jdbc.OracleDriver # jdbc.driverClassName: oracle.jdbc.OracleDriver
jdbc.url: jdbc:oracle:thin:@localhost:49161:XE # jdbc.url: jdbc:oracle:thin:@localhost:49161:XE
jdbc.username: mytest # jdbc.username: mytest
jdbc.password: m121212 # jdbc.password: m121212
threads: 5 # threads: 5
commitSize: 5000 # commitSize: 5000
# - name: rdb # - name: rdb
# key: postgres1 # key: postgres1
# properties: # properties:
......
...@@ -5,9 +5,6 @@ import java.sql.SQLException; ...@@ -5,9 +5,6 @@ import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
...@@ -18,11 +15,14 @@ import org.slf4j.Logger; ...@@ -18,11 +15,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.otter.canal.client.adapter.OuterAdapter; import com.alibaba.otter.canal.client.adapter.OuterAdapter;
import com.alibaba.otter.canal.client.adapter.rdb.config.ConfigLoader; import com.alibaba.otter.canal.client.adapter.rdb.config.ConfigLoader;
import com.alibaba.otter.canal.client.adapter.rdb.config.MappingConfig; import com.alibaba.otter.canal.client.adapter.rdb.config.MappingConfig;
import com.alibaba.otter.canal.client.adapter.rdb.service.RdbEtlService; import com.alibaba.otter.canal.client.adapter.rdb.service.RdbEtlService;
import com.alibaba.otter.canal.client.adapter.rdb.service.RdbSyncService; import com.alibaba.otter.canal.client.adapter.rdb.service.RdbSyncService;
import com.alibaba.otter.canal.client.adapter.rdb.support.SimpleDml;
import com.alibaba.otter.canal.client.adapter.support.*; import com.alibaba.otter.canal.client.adapter.support.*;
@SPI("rdb") @SPI("rdb")
...@@ -30,8 +30,8 @@ public class RdbAdapter implements OuterAdapter { ...@@ -30,8 +30,8 @@ public class RdbAdapter implements OuterAdapter {
private static Logger logger = LoggerFactory.getLogger(RdbAdapter.class); private static Logger logger = LoggerFactory.getLogger(RdbAdapter.class);
private Map<String, MappingConfig> rdbMapping = new HashMap<>(); // 文件名对应配置 private Map<String, MappingConfig> rdbMapping = new HashMap<>(); // 文件名对应配置
private Map<String, MappingConfig> mappingConfigCache = new HashMap<>(); // 库名-表名对应配置 private Map<String, MappingConfig> mappingConfigCache = new HashMap<>(); // 库名-表名对应配置
private DruidDataSource dataSource; private DruidDataSource dataSource;
...@@ -39,6 +39,12 @@ public class RdbAdapter implements OuterAdapter { ...@@ -39,6 +39,12 @@ public class RdbAdapter implements OuterAdapter {
private int commitSize = 3000; private int commitSize = 3000;
private volatile boolean running = false;
private List<SimpleDml> dmlList = Collections.synchronizedList(new ArrayList<>());
private Lock syncLock = new ReentrantLock();
private ExecutorService executor = Executors.newFixedThreadPool(1);
@Override @Override
public void init(OuterAdapterConfig configuration) { public void init(OuterAdapterConfig configuration) {
Map<String, MappingConfig> rdbMappingTmp = ConfigLoader.load(); Map<String, MappingConfig> rdbMappingTmp = ConfigLoader.load();
...@@ -81,52 +87,54 @@ public class RdbAdapter implements OuterAdapter { ...@@ -81,52 +87,54 @@ public class RdbAdapter implements OuterAdapter {
if (commitSize != null) { if (commitSize != null) {
this.commitSize = Integer.valueOf(commitSize); this.commitSize = Integer.valueOf(commitSize);
} }
rdbSyncService = new RdbSyncService(this.commitSize, rdbSyncService = new RdbSyncService(threads != null ? Integer.valueOf(threads) : null, dataSource);
threads != null ? Integer.valueOf(threads) : null,
dataSource);
}
private AtomicInteger batchRowNum = new AtomicInteger(0); running = true;
private List<Dml> dmlList = Collections.synchronizedList(new ArrayList<>());
private Lock syncLock = new ReentrantLock();
private Condition condition = syncLock.newCondition();
private ExecutorService executor = Executors.newFixedThreadPool(1);
@Override
public void sync(Dml dml) {
boolean first = batchRowNum.get() == 0;
int currentSize = batchRowNum.addAndGet(dml.getData().size());
dmlList.add(dml);
if (first) { executor.submit(() -> {
// 开启超时判断 while (running) {
executor.submit(() -> {
try { try {
syncLock.lock(); int size1 = dmlList.size();
if (!condition.await(5, TimeUnit.SECONDS)) { Thread.sleep(3000);
// 批量超时 int size2 = dmlList.size();
if (size1 == size2) {
// 超时提交
sync(); sync();
} }
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} finally {
syncLock.unlock();
} }
}); }
} });
}
@Override
public void sync(Dml dml) {
String destination = StringUtils.trimToEmpty(dml.getDestination());
String database = dml.getDatabase();
String table = dml.getTable();
MappingConfig config = mappingConfigCache.get(destination + "." + database + "." + table);
List<SimpleDml> simpleDmlList = SimpleDml.dml2SimpleDml(dml, config);
if (currentSize > commitSize) { dmlList.addAll(simpleDmlList);
if (dmlList.size() > commitSize) {
sync(); sync();
} }
if (logger.isDebugEnabled()) {
logger.debug("DML: {}", JSON.toJSONString(dml, SerializerFeature.WriteMapNullValue));
}
} }
private void sync() { private void sync() {
try { try {
syncLock.lock(); syncLock.lock();
rdbSyncService.sync(mappingConfigCache, dmlList); if (!dmlList.isEmpty()) {
batchRowNum.set(0); rdbSyncService.sync(dmlList);
dmlList.clear(); dmlList.clear();
condition.signal(); }
} finally { } finally {
syncLock.unlock(); syncLock.unlock();
} }
...@@ -226,6 +234,7 @@ public class RdbAdapter implements OuterAdapter { ...@@ -226,6 +234,7 @@ public class RdbAdapter implements OuterAdapter {
@Override @Override
public void destroy() { public void destroy() {
running = false;
executor.shutdown(); executor.shutdown();
if (rdbSyncService != null) { if (rdbSyncService != null) {
......
...@@ -23,18 +23,14 @@ public class BatchExecutor { ...@@ -23,18 +23,14 @@ public class BatchExecutor {
private Integer key; private Integer key;
private Connection conn; private Connection conn;
private int commitSize = 3000;
private AtomicInteger idx = new AtomicInteger(0); private AtomicInteger idx = new AtomicInteger(0);
private ExecutorService executor = Executors.newFixedThreadPool(1); private ExecutorService executor = Executors.newFixedThreadPool(1);
private Lock commitLock = new ReentrantLock(); private Lock commitLock = new ReentrantLock();
private Condition condition = commitLock.newCondition(); private Condition condition = commitLock.newCondition();
public BatchExecutor(Integer key, Connection conn, Integer commitSize){ public BatchExecutor(Integer key, Connection conn){
this.key = key; this.key = key;
this.conn = conn; this.conn = conn;
if (commitSize != null) {
this.commitSize = commitSize;
}
try { try {
this.conn.setAutoCommit(false); this.conn.setAutoCommit(false);
...@@ -71,29 +67,6 @@ public class BatchExecutor { ...@@ -71,29 +67,6 @@ public class BatchExecutor {
} catch (SQLException e) { } catch (SQLException e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
// int i = idx.incrementAndGet();
//
// // 批次的第一次执行设置延时
// if (i == 1) {
// executor.submit(() -> {
// try {
// commitLock.lock();
// conn.commit(); //直接提交一次
// if (!condition.await(5, TimeUnit.SECONDS)) {
// // 超时提交
// commit();
// }
// } catch (Exception e) {
// logger.error(e.getMessage(), e);
// } finally {
// commitLock.unlock();
// }
// });
// }
//
// if (i == commitSize) {
// commit();
// }
} }
public void commit() { public void commit() {
......
package com.alibaba.otter.canal.client.adapter.rdb.support;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.otter.canal.client.adapter.rdb.config.MappingConfig;
import com.alibaba.otter.canal.client.adapter.support.Dml;
import org.apache.commons.lang.StringUtils;
public class SimpleDml {
private String destination;
private String database;
private String table;
private String type;
private Map<String, Object> data;
private Map<String, Object> old;
private MappingConfig config;
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public Map<String, Object> getOld() {
return old;
}
public void setOld(Map<String, Object> old) {
this.old = old;
}
public MappingConfig getConfig() {
return config;
}
public void setConfig(MappingConfig config) {
this.config = config;
}
public static List<SimpleDml> dml2SimpleDml(Dml dml, MappingConfig config) {
List<SimpleDml> simpleDmlList = new ArrayList<>();
int len = dml.getData().size();
String destination = StringUtils.trimToEmpty(dml.getDestination());
String database = dml.getDatabase();
String table = dml.getTable();
for (int i = 0; i < len; i++) {
SimpleDml simpleDml = new SimpleDml();
simpleDml.setDestination(dml.getDestination());
simpleDml.setDatabase(dml.getDatabase());
simpleDml.setTable(dml.getTable());
simpleDml.setType(dml.getType());
simpleDml.setData(dml.getData().get(i));
if (dml.getOld() != null) {
simpleDml.setOld(dml.getOld().get(i));
}
simpleDml.setConfig(config);
simpleDmlList.add(simpleDml);
}
return simpleDmlList;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册