mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
@@ -75,6 +75,7 @@ public class CanalConstants {
|
|||||||
public static final String CANAL_MQ_VHOST = ROOT + "." + "mq.vhost";
|
public static final String CANAL_MQ_VHOST = ROOT + "." + "mq.vhost";
|
||||||
public static final String CANAL_MQ_ALIYUN_UID = ROOT + "." + "mq.aliyunuid";
|
public static final String CANAL_MQ_ALIYUN_UID = ROOT + "." + "mq.aliyunuid";
|
||||||
public static final String CANAL_MQ_EXCHANGE = ROOT + "." + "mq.exchange";
|
public static final String CANAL_MQ_EXCHANGE = ROOT + "." + "mq.exchange";
|
||||||
|
public static final String CANAL_MQ_DATABASE_HASH = ROOT + "." + "mq.database.hash";
|
||||||
|
|
||||||
public static String getInstanceModeKey(String destination) {
|
public static String getInstanceModeKey(String destination) {
|
||||||
return MessageFormat.format(INSTANCE_MODE_TEMPLATE, destination);
|
return MessageFormat.format(INSTANCE_MODE_TEMPLATE, destination);
|
||||||
|
|||||||
@@ -298,6 +298,11 @@ public class CanalStarter {
|
|||||||
mqProperties.setExchange(exchange);
|
mqProperties.setExchange(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String databaseHash = CanalController.getProperty(properties, CanalConstants.CANAL_MQ_DATABASE_HASH);
|
||||||
|
if (!StringUtils.isEmpty(databaseHash)){
|
||||||
|
mqProperties.setDatabaseHash(Boolean.valueOf(databaseHash));
|
||||||
|
}
|
||||||
|
|
||||||
for (Object key : properties.keySet()) {
|
for (Object key : properties.keySet()) {
|
||||||
key = StringUtils.trim(key.toString());
|
key = StringUtils.trim(key.toString());
|
||||||
if (((String) key).startsWith(CanalConstants.CANAL_MQ_PROPERTIES)) {
|
if (((String) key).startsWith(CanalConstants.CANAL_MQ_PROPERTIES)) {
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ canal.mq.username=
|
|||||||
canal.mq.password=
|
canal.mq.password=
|
||||||
canal.mq.aliyunuid=
|
canal.mq.aliyunuid=
|
||||||
|
|
||||||
|
canal.mq.database.hash = true
|
||||||
##################################################
|
##################################################
|
||||||
######### Kafka Kerberos Info #############
|
######### Kafka Kerberos Info #############
|
||||||
##################################################
|
##################################################
|
||||||
|
|||||||
@@ -234,10 +234,11 @@ public class MQMessageUtils {
|
|||||||
*
|
*
|
||||||
* @param partitionsNum 分区数
|
* @param partitionsNum 分区数
|
||||||
* @param pkHashConfigs 分区库表主键正则表达式
|
* @param pkHashConfigs 分区库表主键正则表达式
|
||||||
|
* @param databaseHash 是否取消根据database进行hash
|
||||||
* @return 分区message数组
|
* @return 分区message数组
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Message[] messagePartition(EntryRowData[] datas, long id, Integer partitionsNum, String pkHashConfigs) {
|
public static Message[] messagePartition(EntryRowData[] datas, long id, Integer partitionsNum, String pkHashConfigs,boolean databaseHash) {
|
||||||
if (partitionsNum == null) {
|
if (partitionsNum == null) {
|
||||||
partitionsNum = 1;
|
partitionsNum = 1;
|
||||||
}
|
}
|
||||||
@@ -279,7 +280,10 @@ public class MQMessageUtils {
|
|||||||
RowChange.Builder rowChangeBuilder = RowChange.newBuilder(rowChange);
|
RowChange.Builder rowChangeBuilder = RowChange.newBuilder(rowChange);
|
||||||
|
|
||||||
for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
|
for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
|
||||||
int hashCode = database.hashCode();
|
int hashCode = 0;
|
||||||
|
if(databaseHash){
|
||||||
|
hashCode = database.hashCode();
|
||||||
|
}
|
||||||
CanalEntry.EventType eventType = rowChange.getEventType();
|
CanalEntry.EventType eventType = rowChange.getEventType();
|
||||||
List<CanalEntry.Column> columns = null;
|
List<CanalEntry.Column> columns = null;
|
||||||
if (eventType == CanalEntry.EventType.DELETE) {
|
if (eventType == CanalEntry.EventType.DELETE) {
|
||||||
@@ -444,9 +448,10 @@ public class MQMessageUtils {
|
|||||||
* @param flatMessage flatMessage
|
* @param flatMessage flatMessage
|
||||||
* @param partitionsNum 分区数量
|
* @param partitionsNum 分区数量
|
||||||
* @param pkHashConfigs hash映射
|
* @param pkHashConfigs hash映射
|
||||||
|
* @param databaseHash 是否取消根据database进行hash
|
||||||
* @return 拆分后的flatMessage数组
|
* @return 拆分后的flatMessage数组
|
||||||
*/
|
*/
|
||||||
public static FlatMessage[] messagePartition(FlatMessage flatMessage, Integer partitionsNum, String pkHashConfigs) {
|
public static FlatMessage[] messagePartition(FlatMessage flatMessage, Integer partitionsNum, String pkHashConfigs,boolean databaseHash) {
|
||||||
if (partitionsNum == null) {
|
if (partitionsNum == null) {
|
||||||
partitionsNum = 1;
|
partitionsNum = 1;
|
||||||
}
|
}
|
||||||
@@ -476,7 +481,10 @@ public class MQMessageUtils {
|
|||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (Map<String, String> row : flatMessage.getData()) {
|
for (Map<String, String> row : flatMessage.getData()) {
|
||||||
int hashCode = database.hashCode();
|
int hashCode = 0;
|
||||||
|
if(databaseHash){
|
||||||
|
hashCode = database.hashCode();
|
||||||
|
}
|
||||||
if (pkNames != null) {
|
if (pkNames != null) {
|
||||||
for (String pkName : pkNames) {
|
for (String pkName : pkNames) {
|
||||||
String value = row.get(pkName);
|
String value = row.get(pkName);
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public class MQProperties {
|
|||||||
private String exchange = "";
|
private String exchange = "";
|
||||||
// 消息发送的并行度
|
// 消息发送的并行度
|
||||||
private int parallelThreadSize = 8;
|
private int parallelThreadSize = 8;
|
||||||
|
//是否取消根据database进行hash
|
||||||
|
private boolean databaseHash = true;
|
||||||
|
|
||||||
|
|
||||||
public static class CanalDestination {
|
public static class CanalDestination {
|
||||||
|
|
||||||
@@ -339,6 +342,13 @@ public class MQProperties {
|
|||||||
this.parallelThreadSize = parallelThreadSize;
|
this.parallelThreadSize = parallelThreadSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getDatabaseHash() {
|
||||||
|
return databaseHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDatabaseHash(boolean databaseHash) {
|
||||||
|
this.databaseHash = databaseHash;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MQProperties [servers=" + servers + ", retries=" + retries + ", batchSize=" + batchSize + ", lingerMs="
|
return "MQProperties [servers=" + servers + ", retries=" + retries + ", batchSize=" + batchSize + ", lingerMs="
|
||||||
@@ -352,7 +362,9 @@ public class MQProperties {
|
|||||||
+ kerberosEnable + ", kerberosKrb5FilePath=" + kerberosKrb5FilePath + ", kerberosJaasFilePath="
|
+ kerberosEnable + ", kerberosKrb5FilePath=" + kerberosKrb5FilePath + ", kerberosJaasFilePath="
|
||||||
+ kerberosJaasFilePath + ", username=" + username + ", password=" + password + ", vhost=" + vhost
|
+ kerberosJaasFilePath + ", username=" + username + ", password=" + password + ", vhost=" + vhost
|
||||||
+ ", aliyunUID=" + aliyunUID + ", exchange=" + exchange + ", parallelThreadSize=" + parallelThreadSize
|
+ ", aliyunUID=" + aliyunUID + ", exchange=" + exchange + ", parallelThreadSize=" + parallelThreadSize
|
||||||
+ "]";
|
+ ",databaseHash=" + databaseHash +"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,14 @@ public class CanalKafkaProducer extends AbstractMQProducer implements CanalMQPro
|
|||||||
private Producer<String, byte[]> producer;
|
private Producer<String, byte[]> producer;
|
||||||
private MQProperties kafkaProperties;
|
private MQProperties kafkaProperties;
|
||||||
|
|
||||||
|
private boolean databaseHash;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(MQProperties kafkaProperties) {
|
public void init(MQProperties kafkaProperties) {
|
||||||
super.init(kafkaProperties);
|
super.init(kafkaProperties);
|
||||||
|
|
||||||
this.kafkaProperties = kafkaProperties;
|
this.kafkaProperties = kafkaProperties;
|
||||||
|
databaseHash = kafkaProperties.getDatabaseHash();
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.put("bootstrap.servers", kafkaProperties.getServers());
|
properties.put("bootstrap.servers", kafkaProperties.getServers());
|
||||||
properties.put("acks", kafkaProperties.getAcks());
|
properties.put("acks", kafkaProperties.getAcks());
|
||||||
@@ -172,7 +175,8 @@ public class CanalKafkaProducer extends AbstractMQProducer implements CanalMQPro
|
|||||||
Message[] messages = MQMessageUtils.messagePartition(datas,
|
Message[] messages = MQMessageUtils.messagePartition(datas,
|
||||||
message.getId(),
|
message.getId(),
|
||||||
canalDestination.getPartitionsNum(),
|
canalDestination.getPartitionsNum(),
|
||||||
canalDestination.getPartitionHash());
|
canalDestination.getPartitionHash(),
|
||||||
|
databaseHash);
|
||||||
int length = messages.length;
|
int length = messages.length;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Message messagePartition = messages[i];
|
Message messagePartition = messages[i];
|
||||||
@@ -201,7 +205,8 @@ public class CanalKafkaProducer extends AbstractMQProducer implements CanalMQPro
|
|||||||
if (canalDestination.getPartitionHash() != null && !canalDestination.getPartitionHash().isEmpty()) {
|
if (canalDestination.getPartitionHash() != null && !canalDestination.getPartitionHash().isEmpty()) {
|
||||||
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
|
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
|
||||||
canalDestination.getPartitionsNum(),
|
canalDestination.getPartitionsNum(),
|
||||||
canalDestination.getPartitionHash());
|
canalDestination.getPartitionHash(),
|
||||||
|
databaseHash);
|
||||||
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];
|
||||||
|
|||||||
@@ -40,10 +40,13 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|||||||
private MQProperties mqProperties;
|
private MQProperties mqProperties;
|
||||||
private static final String CLOUD_ACCESS_CHANNEL = "cloud";
|
private static final String CLOUD_ACCESS_CHANNEL = "cloud";
|
||||||
|
|
||||||
|
private boolean databaseHash;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(MQProperties rocketMQProperties) {
|
public void init(MQProperties rocketMQProperties) {
|
||||||
super.init(rocketMQProperties);
|
super.init(rocketMQProperties);
|
||||||
this.mqProperties = rocketMQProperties;
|
this.mqProperties = rocketMQProperties;
|
||||||
|
this.databaseHash = rocketMQProperties.getDatabaseHash();
|
||||||
RPCHook rpcHook = null;
|
RPCHook rpcHook = null;
|
||||||
if (rocketMQProperties.getAliyunAccessKey().length() > 0
|
if (rocketMQProperties.getAliyunAccessKey().length() > 0
|
||||||
&& rocketMQProperties.getAliyunSecretKey().length() > 0) {
|
&& rocketMQProperties.getAliyunSecretKey().length() > 0) {
|
||||||
@@ -125,7 +128,7 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|||||||
com.alibaba.otter.canal.protocol.Message[] messages = MQMessageUtils.messagePartition(datas,
|
com.alibaba.otter.canal.protocol.Message[] messages = MQMessageUtils.messagePartition(datas,
|
||||||
message.getId(),
|
message.getId(),
|
||||||
destination.getPartitionsNum(),
|
destination.getPartitionsNum(),
|
||||||
destination.getPartitionHash());
|
destination.getPartitionHash(),databaseHash);
|
||||||
int length = messages.length;
|
int length = messages.length;
|
||||||
|
|
||||||
ExecutorTemplate template = new ExecutorTemplate(executor);
|
ExecutorTemplate template = new ExecutorTemplate(executor);
|
||||||
@@ -168,7 +171,7 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|||||||
for (FlatMessage flatMessage : flatMessages) {
|
for (FlatMessage flatMessage : flatMessages) {
|
||||||
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
|
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
|
||||||
destination.getPartitionsNum(),
|
destination.getPartitionsNum(),
|
||||||
destination.getPartitionHash());
|
destination.getPartitionHash(),databaseHash);
|
||||||
int length = partitionFlatMessage.length;
|
int length = partitionFlatMessage.length;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
partitionFlatMessages.get(i).add(partitionFlatMessage[i]);
|
partitionFlatMessages.get(i).add(partitionFlatMessage[i]);
|
||||||
|
|||||||
Reference in New Issue
Block a user