同时使用Spark与Flink Cassandra连接器的Maven依赖冲突解决
我太懂你这种头疼的情况了——同时用Flink和Spark操作Cassandra,结果因为两个连接器依赖的cassandra-driver-core版本打架,导致Spark直接报错,排除依赖还不管用,只能删掉Flink的连接器才能正常运行。别慌,咱们一步步来解决这个问题:
核心原因
Flink Cassandra连接器和Spark Cassandra Connector各自依赖了不同版本的cassandra-driver-core,而Java运行时只会加载一个版本的类,当代码调用了某个版本特有的方法时,就会出现NoSuchMethodError这类错误。单纯排除依赖没用,因为可能还有其他间接依赖引入驱动,或者两个连接器对驱动版本的兼容性要求需要统一协调。
解决方案
1. 用dependencyManagement强制锁定统一的驱动版本
首先得确定一个同时兼容Flink 1.4.2和Spark Cassandra Connector 2.0.8的cassandra-driver-core版本。查官方文档可知:
- Flink 1.4.2的
flink-connector-cassandra_2.11兼容Datastax Java Driver 3.x系列 - Spark Cassandra Connector 2.0.8同样兼容3.x系列
咱们选一个稳定的版本,比如3.10.2,然后在pom.xml的dependencyManagement节点里强制锁定:
<dependencyManagement> <dependencies> <!-- 强制统一cassandra-driver-core版本 --> <dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>3.10.2</version> </dependency> <!-- 同时锁定驱动的其他相关依赖,避免遗漏 --> <dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-mapping</artifactId> <version>3.10.2</version> </dependency> </dependencies> </dependencyManagement>
然后保留你原来的两个连接器依赖(带排除):
<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-cassandra_2.11</artifactId> <version>1.4.2</version> <exclusions> <exclusion> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> </exclusion> <exclusion> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-mapping</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.datastax.spark</groupId> <artifactId>spark-cassandra-connector_2.11</artifactId> <version>2.0.8</version> <exclusions> <exclusion> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> </exclusion> <exclusion> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-mapping</artifactId> </exclusion> </exclusions> </dependency>
2. 检查依赖树,确认没有版本冲突
执行Maven命令查看完整依赖树,确保cassandra-driver-core只有咱们指定的版本:
mvn dependency:tree | grep cassandra-driver-core
如果输出里出现其他版本,找到对应的依赖包,在其依赖声明里添加排除规则。
3. 极端情况:用Shade插件做类隔离
如果上面的方法还是不行,说明两个框架对驱动的兼容性要求差异太大,可以用Maven Shade插件重命名Flink依赖的驱动包名,实现类隔离:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <!-- 重命名Flink使用的cassandra驱动包名 --> <relocation> <pattern>com.datastax.cassandra</pattern> <shadedPattern>shaded.com.datastax.cassandra.flink</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>
这个方法会把Flink依赖的驱动类重命名到新的包下,和Spark使用的驱动类完全隔离,从根本上避免冲突。
验证
配置完成后,执行mvn clean package重新打包,然后分别测试Flink和Spark的Cassandra读写功能,确认两者都能正常工作。
内容的提问来源于stack exchange,提问作者Soheil Pourbafrani




