Skip to content

Commit b81e9df

Browse files
支持不同topic指定专属partitionNum (#2479)
1 parent b79af46 commit b81e9df

File tree

11 files changed

+95
-4
lines changed

11 files changed

+95
-4
lines changed

connector/core/src/main/java/com/alibaba/otter/canal/connector/core/producer/MQDestination.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class MQDestination {
1414
private Integer partitionsNum;
1515
private String partitionHash;
1616
private String dynamicTopic;
17+
private String dynamicTopicPartitionNum;
1718

1819
public String getCanalDestination() {
1920
return canalDestination;
@@ -62,4 +63,12 @@ public String getDynamicTopic() {
6263
public void setDynamicTopic(String dynamicTopic) {
6364
this.dynamicTopic = dynamicTopic;
6465
}
66+
67+
public String getDynamicTopicPartitionNum() {
68+
return dynamicTopicPartitionNum;
69+
}
70+
71+
public void setDynamicTopicPartitionNum(String dynamicTopicPartitionNum) {
72+
this.dynamicTopicPartitionNum = dynamicTopicPartitionNum;
73+
}
6574
}

connector/core/src/main/java/com/alibaba/otter/canal/connector/core/producer/MQMessageUtils.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,38 @@ public List<DynamicTopicData> apply(String pkHashConfigs) {
103103
}
104104
});
105105

106+
private static Map<String, List<TopicPartitionData>> topicPartitionDatas = MigrateMap.makeComputingMap(CacheBuilder.newBuilder()
107+
.softValues(),
108+
new Function<String, List<TopicPartitionData>>() {
109+
110+
public List<TopicPartitionData> apply(String tPConfigs) {
111+
List<TopicPartitionData> datas = Lists.newArrayList();
112+
String[] tPArray = StringUtils.split(StringUtils.replace(tPConfigs,
113+
",",
114+
";"),
115+
";");
116+
for (String tPConfig : tPArray) {
117+
TopicPartitionData data = new TopicPartitionData();
118+
int i = tPConfig.lastIndexOf(":");
119+
if (i > 0) {
120+
String tStr = tPConfig.substring(0, i);
121+
String pStr = tPConfig.substring(i + 1);
122+
if (!isWildCard(tStr)) {
123+
data.simpleName = tStr;
124+
} else {
125+
data.regexFilter = new AviaterRegexFilter(tStr);
126+
}
127+
if (!StringUtils.isEmpty(pStr) && StringUtils.isNumeric(pStr)) {
128+
data.partitionNum = Integer.valueOf(pStr);
129+
}
130+
datas.add(data);
131+
}
132+
}
133+
134+
return datas;
135+
}
136+
});
137+
106138
/**
107139
* 按 schema 或者 schema+table 将 message 分配到对应topic
108140
*
@@ -619,6 +651,24 @@ public static boolean checkPkNamesHasContain(List<String> pkNames, String name)
619651
return false;
620652
}
621653

654+
public static Integer parseDynamicTopicPartition(String name, String tPConfigs) {
655+
if (!StringUtils.isEmpty(tPConfigs)) {
656+
List<TopicPartitionData> datas = topicPartitionDatas.get(tPConfigs);
657+
for (TopicPartitionData data : datas) {
658+
if (data.simpleName != null) {
659+
if (data.simpleName.equalsIgnoreCase(name)) {
660+
return data.partitionNum;
661+
}
662+
} else {
663+
if (data.regexFilter.filter(name)) {
664+
return data.partitionNum;
665+
}
666+
}
667+
}
668+
}
669+
return null;
670+
}
671+
622672
private static boolean isWildCard(String value) {
623673
// not contaiins '.' ?
624674
return StringUtils.containsAny(value, new char[] { '*', '?', '+', '|', '(', ')', '{', '}', '[', ']', '\\', '$',
@@ -656,6 +706,13 @@ public static class DynamicTopicData {
656706
public AviaterRegexFilter tableRegexFilter;
657707
}
658708

709+
public static class TopicPartitionData {
710+
711+
public String simpleName;
712+
public AviaterRegexFilter regexFilter;
713+
public Integer partitionNum;
714+
}
715+
659716
public static class EntryRowData {
660717

661718
public Entry entry;

connector/kafka-connector/src/main/java/com/alibaba/otter/canal/connector/kafka/producer/CanalKafkaProducer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,19 @@ public void send(MQDestination mqDestination, Message message, Callback callback
196196

197197
private List<Future> send(MQDestination mqDestination, String topicName, Message message, boolean flat) {
198198
List<ProducerRecord<String, byte[]>> records = new ArrayList<>();
199+
// 获取当前topic的分区数
200+
Integer partitionNum = MQMessageUtils.parseDynamicTopicPartition(topicName, mqDestination.getDynamicTopicPartitionNum());
201+
if (partitionNum == null) {
202+
partitionNum = mqDestination.getPartitionsNum();
203+
}
199204
if (!flat) {
200205
if (mqDestination.getPartitionHash() != null && !mqDestination.getPartitionHash().isEmpty()) {
201206
// 并发构造
202207
EntryRowData[] datas = MQMessageUtils.buildMessageData(message, buildExecutor);
203208
// 串行分区
204209
Message[] messages = MQMessageUtils.messagePartition(datas,
205210
message.getId(),
206-
mqDestination.getPartitionsNum(),
211+
partitionNum,
207212
mqDestination.getPartitionHash(),
208213
this.mqProperties.isDatabaseHash());
209214
int length = messages.length;
@@ -233,7 +238,7 @@ private List<Future> send(MQDestination mqDestination, String topicName, Message
233238
for (FlatMessage flatMessage : flatMessages) {
234239
if (mqDestination.getPartitionHash() != null && !mqDestination.getPartitionHash().isEmpty()) {
235240
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
236-
mqDestination.getPartitionsNum(),
241+
partitionNum,
237242
mqDestination.getPartitionHash(),
238243
this.mqProperties.isDatabaseHash());
239244
int length = partitionFlatMessage.length;

connector/rocketmq-connector/src/main/java/com/alibaba/otter/canal/connector/rocketmq/producer/CanalRocketMQProducer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,19 @@ public void send(MQDestination destination, com.alibaba.otter.canal.protocol.Mes
161161
}
162162

163163
public void send(final MQDestination destination, String topicName, com.alibaba.otter.canal.protocol.Message message) {
164+
// 获取当前topic的分区数
165+
Integer partitionNum = MQMessageUtils.parseDynamicTopicPartition(topicName, destination.getDynamicTopicPartitionNum());
166+
if (partitionNum == null) {
167+
partitionNum = destination.getPartitionsNum();
168+
}
164169
if (!mqProperties.isFlatMessage()) {
165170
if (destination.getPartitionHash() != null && !destination.getPartitionHash().isEmpty()) {
166171
// 并发构造
167172
MQMessageUtils.EntryRowData[] datas = MQMessageUtils.buildMessageData(message, buildExecutor);
168173
// 串行分区
169174
com.alibaba.otter.canal.protocol.Message[] messages = MQMessageUtils.messagePartition(datas,
170175
message.getId(),
171-
destination.getPartitionsNum(),
176+
partitionNum,
172177
destination.getPartitionHash(),
173178
mqProperties.isDatabaseHash());
174179
int length = messages.length;
@@ -207,7 +212,7 @@ public void send(final MQDestination destination, String topicName, com.alibaba.
207212

208213
for (FlatMessage flatMessage : flatMessages) {
209214
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
210-
destination.getPartitionsNum(),
215+
partitionNum,
211216
destination.getPartitionHash(),
212217
mqProperties.isDatabaseHash());
213218
int length = partitionFlatMessage.length;

deployer/src/main/resources/example/instance.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ canal.mq.partition=0
5454
# hash partition config
5555
#canal.mq.partitionsNum=3
5656
#canal.mq.partitionHash=test.table:id^name,.*\\..*
57+
#canal.mq.dynamicTopicPartitionNum=test.*:4,mycanal:6
5758
#################################################

deployer/src/main/resources/spring/default-instance.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,6 @@
200200
<property name="partition" value="${canal.mq.partition}" />
201201
<property name="partitionsNum" value="${canal.mq.partitionsNum}" />
202202
<property name="partitionHash" value="${canal.mq.partitionHash}" />
203+
<property name="dynamicTopicPartitionNum" value="${canal.mq.dynamicTopicPartitionNum}" />
203204
</bean>
204205
</beans>

deployer/src/main/resources/spring/file-instance.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,6 @@
186186
<property name="partition" value="${canal.mq.partition}" />
187187
<property name="partitionsNum" value="${canal.mq.partitionsNum}" />
188188
<property name="partitionHash" value="${canal.mq.partitionHash}" />
189+
<property name="dynamicTopicPartitionNum" value="${canal.mq.dynamicTopicPartitionNum}" />
189190
</bean>
190191
</beans>

deployer/src/main/resources/spring/group-instance.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,5 +276,6 @@
276276
<property name="partition" value="${canal.mq.partition}" />
277277
<property name="partitionsNum" value="${canal.mq.partitionsNum}" />
278278
<property name="partitionHash" value="${canal.mq.partitionHash}" />
279+
<property name="dynamicTopicPartitionNum" value="${canal.mq.dynamicTopicPartitionNum}" />
279280
</bean>
280281
</beans>

deployer/src/main/resources/spring/memory-instance.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,5 +174,6 @@
174174
<property name="partition" value="${canal.mq.partition}" />
175175
<property name="partitionsNum" value="${canal.mq.partitionsNum}" />
176176
<property name="partitionHash" value="${canal.mq.partitionHash}" />
177+
<property name="dynamicTopicPartitionNum" value="${canal.mq.dynamicTopicPartitionNum}" />
177178
</bean>
178179
</beans>

instance/core/src/main/java/com/alibaba/otter/canal/instance/core/CanalMQConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public class CanalMQConfig {
77
private Integer partitionsNum;
88
private String partitionHash;
99
private String dynamicTopic;
10+
private String dynamicTopicPartitionNum;
1011

1112
public String getTopic() {
1213
return topic;
@@ -47,4 +48,12 @@ public String getDynamicTopic() {
4748
public void setDynamicTopic(String dynamicTopic) {
4849
this.dynamicTopic = dynamicTopic;
4950
}
51+
52+
public String getDynamicTopicPartitionNum() {
53+
return dynamicTopicPartitionNum;
54+
}
55+
56+
public void setDynamicTopicPartitionNum(String dynamicTopicPartitionNum) {
57+
this.dynamicTopicPartitionNum = dynamicTopicPartitionNum;
58+
}
5059
}

0 commit comments

Comments
 (0)