环境信息
canal version: 1.1.3-alpha2 mysql version: 5.7.22
问题描述
1.1.3中新增的对 Message 的 partition 逻辑,如果一个 Canal Entry 包含 n 个 rowData,则 Canal Entry 在partition 之后会重复 n 倍
// canal/server/src/main/java/com/alibaba/otter/canal/common/MQMessageUtils.java for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) { int hashCode = table.hashCode(); if (hashMode.autoPkHash) { // isEmpty use default pkNames for (CanalEntry.Column column : rowData.getAfterColumnsList()) { if (column.getIsKey()) { hashCode = hashCode ^ column.getValue().hashCode(); } } } else if (!hashMode.tableHash) { for (CanalEntry.Column column : rowData.getAfterColumnsList()) { if (checkPkNamesHasContain(hashMode.pkNames, column.getName())) { hashCode = hashCode ^ column.getValue().hashCode(); } } }
int pkHash = Math.abs(hashCode) % partitionsNum;
pkHash = Math.abs(pkHash);
partitionEntries[pkHash].add(entry);
}
步骤重现
对于一个n行的表 t delete from t; Canal Entry 的 rowData 会产生多行
期待结果
partition 后产生一个 Entry
现执行情况
partition 后产生n个 Entry
原提问者GitHub用户oscar-zyh
您报告的问题是 Canal 1.1.3-alpha2 中新增的 Message partition 逻辑可能导致数据重复的问题。具体来说,如果一个 Canal Entry 包含 n 个 rowData,则 partition 之后会产生 n 个相同的 Entry,导致数据重复。
这个问题的原因是在对每个 rowData 进行 hashCode 计算时,使用了表名和主键的哈希值。当一个 Entry 包含多行数据时,它们的主键哈希值可能相同,导致它们被分配到同一个 partition 中。在 partition 后,这些行数据就会被组合成多条相同的 Entry,进而导致数据重复。
目前,我们已经在 Canal 1.1.4 中修复了这个问题,并且添加了对应的测试用例。修复方式是对主键哈希值进行了优化,以避免产生多条相同的 Entry。我们建议您升级到 Canal 1.1.4 或更高版本,以避免这个问题。
如果您无法立即升级到 Canal 1.1.4,也可以采用以下两个临时解决方案来避免数据重复:
在使用 Message partition 时,尽量避免一个 Entry 包含多行数据。如果必须包含多行数据,可以尝试调整哈希策略,例如使用更多的列来计算哈希值。
在使用 Message partition 时,可以将 partitionsNum 设置为 1,这样就不会产生多个相同的 Entry。但是,这样可能会影响性能和可靠性。
希望以上信息能够帮助您解决问题。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。