|
@@ -5,6 +5,7 @@ import java.sql.SQLException;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.locks.Condition;
|
|
|
import java.util.concurrent.locks.Lock;
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
@@ -20,6 +21,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
|
|
|
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.MappingConfig;
|
|
|
+import com.alibaba.otter.canal.client.adapter.rdb.monitor.RdbConfigMonitor;
|
|
|
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.support.SimpleDml;
|
|
@@ -28,22 +30,33 @@ import com.alibaba.otter.canal.client.adapter.support.*;
|
|
|
@SPI("rdb")
|
|
|
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> mappingConfigCache = new HashMap<>(); // 库名-表名对应配置
|
|
|
+ private Map<String, MappingConfig> rdbMapping = new HashMap<>(); // 文件名对应配置
|
|
|
+ private Map<String, Map<String, MappingConfig>> mappingConfigCache = new HashMap<>(); // 库名-表名对应配置
|
|
|
|
|
|
- private DruidDataSource dataSource;
|
|
|
+ private DruidDataSource dataSource;
|
|
|
|
|
|
- private RdbSyncService rdbSyncService;
|
|
|
+ private RdbSyncService rdbSyncService;
|
|
|
|
|
|
- private int commitSize = 3000;
|
|
|
+ private int commitSize = 3000;
|
|
|
|
|
|
- private volatile boolean running = false;
|
|
|
+ private volatile boolean running = false;
|
|
|
|
|
|
- private List<SimpleDml> dmlList = Collections.synchronizedList(new ArrayList<>());
|
|
|
- private Lock syncLock = new ReentrantLock();
|
|
|
- private ExecutorService executor = Executors.newFixedThreadPool(1);
|
|
|
+ private List<SimpleDml> dmlList = Collections
|
|
|
+ .synchronizedList(new ArrayList<>());
|
|
|
+ private Lock syncLock = new ReentrantLock();
|
|
|
+ private ExecutorService executor = Executors.newFixedThreadPool(1);
|
|
|
+
|
|
|
+ private RdbConfigMonitor rdbConfigMonitor;
|
|
|
+
|
|
|
+ public Map<String, MappingConfig> getRdbMapping() {
|
|
|
+ return rdbMapping;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Map<String, MappingConfig>> getMappingConfigCache() {
|
|
|
+ return mappingConfigCache;
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
public void init(OuterAdapterConfig configuration) {
|
|
@@ -56,11 +69,15 @@ public class RdbAdapter implements OuterAdapter {
|
|
|
rdbMapping.put(key, mappingConfig);
|
|
|
}
|
|
|
});
|
|
|
- for (MappingConfig mappingConfig : rdbMapping.values()) {
|
|
|
- mappingConfigCache
|
|
|
- .put(StringUtils.trimToEmpty(mappingConfig.getDestination()) + "."
|
|
|
- + mappingConfig.getDbMapping().getDatabase() + "." + mappingConfig.getDbMapping().getTable(),
|
|
|
- mappingConfig);
|
|
|
+ for (Map.Entry<String, MappingConfig> entry : rdbMapping.entrySet()) {
|
|
|
+ String configName = entry.getKey();
|
|
|
+ MappingConfig mappingConfig = entry.getValue();
|
|
|
+ Map<String, MappingConfig> configMap = mappingConfigCache
|
|
|
+ .computeIfAbsent(StringUtils.trimToEmpty(mappingConfig.getDestination()) + "."
|
|
|
+ + mappingConfig.getDbMapping().getDatabase() + "."
|
|
|
+ + mappingConfig.getDbMapping().getTable(),
|
|
|
+ k1 -> new HashMap<>());
|
|
|
+ configMap.put(configName, mappingConfig);
|
|
|
}
|
|
|
|
|
|
Map<String, String> properties = configuration.getProperties();
|
|
@@ -93,19 +110,22 @@ public class RdbAdapter implements OuterAdapter {
|
|
|
|
|
|
executor.submit(() -> {
|
|
|
while (running) {
|
|
|
+ int beginSize = dmlList.size();
|
|
|
try {
|
|
|
- int size1 = dmlList.size();
|
|
|
Thread.sleep(3000);
|
|
|
- int size2 = dmlList.size();
|
|
|
- if (size1 == size2) {
|
|
|
- // 超时提交
|
|
|
- sync();
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- logger.error(e.getMessage(), e);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ int endSize = dmlList.size();
|
|
|
+
|
|
|
+ if (endSize - beginSize < 300) {
|
|
|
+ sync();
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ rdbConfigMonitor = new RdbConfigMonitor();
|
|
|
+ rdbConfigMonitor.init(configuration.getKey(), this);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -113,16 +133,18 @@ public class RdbAdapter implements OuterAdapter {
|
|
|
String destination = StringUtils.trimToEmpty(dml.getDestination());
|
|
|
String database = dml.getDatabase();
|
|
|
String table = dml.getTable();
|
|
|
- MappingConfig config = mappingConfigCache.get(destination + "." + database + "." + table);
|
|
|
+ Map<String, MappingConfig> configMap = mappingConfigCache.get(destination + "." + database + "." + table);
|
|
|
|
|
|
- List<SimpleDml> simpleDmlList = SimpleDml.dml2SimpleDml(dml, config);
|
|
|
+ if (configMap != null) {
|
|
|
+ configMap.values().forEach(config -> {
|
|
|
+ List<SimpleDml> simpleDmlList = SimpleDml.dml2SimpleDml(dml, config);
|
|
|
+ dmlList.addAll(simpleDmlList);
|
|
|
|
|
|
- dmlList.addAll(simpleDmlList);
|
|
|
-
|
|
|
- if (dmlList.size() > commitSize) {
|
|
|
- sync();
|
|
|
+ if (dmlList.size() >= commitSize) {
|
|
|
+ sync();
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
if (logger.isDebugEnabled()) {
|
|
|
logger.debug("DML: {}", JSON.toJSONString(dml, SerializerFeature.WriteMapNullValue));
|
|
|
}
|
|
@@ -235,6 +257,10 @@ public class RdbAdapter implements OuterAdapter {
|
|
|
@Override
|
|
|
public void destroy() {
|
|
|
running = false;
|
|
|
+ if (rdbConfigMonitor != null) {
|
|
|
+ rdbConfigMonitor.destroy();
|
|
|
+ }
|
|
|
+
|
|
|
executor.shutdown();
|
|
|
|
|
|
if (rdbSyncService != null) {
|