Spring Boot 与 Cassandra 的整合,本质上是通过 Spring Data Cassandra 模块屏蔽底层驱动细节,让开发者像操作关系型数据库一样使用 Cassandra。但 Cassandra 的分布式特性决定了它不能照搬 JPA 那套思路,从依赖引入到实体注解,从连接配置到查询方式,都需要针对无主架构和高可用目标做特殊设计。第一步要做的,是在项目中引入正确的依赖并确保版本兼容。

依赖配置与连接初始化
在 Spring Boot 项目中使用 Cassandra,需要引入 spring-boot-starter-data-cassandra 依赖。该 starter 会自动配置 CqlSession、CassandraTemplate 以及 Repository 扫描支持。以 Maven 为例,在 pom.xml 中添加以下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
连接配置通常放在 application.yml 中。Cassandra 集群可能包含多个节点,Spring Boot 允许通过 spring.cassandra.contact-points 指定种子节点列表,并且支持配置本地数据中心名称。这里有一个关键点:如果客户端连接到多数据中心的 Cassandra 集群,必须明确指定 local-datacenter,否则驱动会默认使用第一个数据中心,导致跨机房请求出现高延迟甚至连接失败。一个典型的配置如下:
spring:
data:
cassandra:
keyspace-name: my_keyspace
contact-points: 10.0.0.11,10.0.0.12,10.0.0.13
port: 9042
local-datacenter: dc1
schema-action: none
request:
timeout: 5s
consistency: local_quorum
schema-action 设置为 none 表示不让应用自动创建或修改 Keyspace 和表结构,生产环境通常由数据库管理员统一管理。如果设置为 create-if-not-exists,在开发环境很方便,但生产环境容易因误操作导致 schema 漂移。request.consistency 指定默认的读写一致性级别,这个值可以根据业务特点在 Repository 方法上单独覆盖。
连接初始化时,Spring Boot 会基于这些配置创建 CqlSession 实例。如果需要更细粒度的控制,比如自定义重试策略或负载均衡策略,可以定义 DriverConfigLoaderBuilderCustomizer 类型的 Bean。例如开启 speculative execution 来降低长尾延迟:
@Bean
public DriverConfigLoaderBuilderCustomizer cassandraCustomizer() {
return builder -> builder
.withInt(DefaultDriverOption.SPECULATIVE_EXECUTION_MAX, 3)
.withInt(DefaultDriverOption.SPECULATIVE_EXECUTION_DELAY, 100)
.withString(DefaultDriverOption.RECONNECTION_POLICY_CLASS, "Exponential");
}
这段代码不是必须的,但在高可用场景中很有价值。Cassandra 驱动本身具备节点故障检测和自动重连能力,默认的重连策略已经可以应对大多数网络抖动。如果接触到的环境网络质量不稳定,适当调整重连间隔和 speculative execution 参数能显著提高请求成功率。
实体建模与 Repository 操作
Cassandra 是列族存储,数据模型设计围绕查询而非关系。使用 Spring Data Cassandra 时,实体类需要用 @Table 注解标记,主键通过 @PrimaryKey 或 @PrimaryKeyColumn 定义。复合主键可以使用 @PrimaryKeyClass 表示。下面是一个订单实体的例子,其中分区键是 userId,聚簇键是 orderId,这样同一个用户的所有订单会落在同一分区,方便按用户查询订单列表。
@Table("orders")
public class Order {
@PrimaryKeyColumn(name = "user_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String userId;
@PrimaryKeyColumn(name = "order_id", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
private String orderId;
@Column("amount")
private BigDecimal amount;
@Column("status")
private String status;
// getters and setters omitted
}
在 Repository 层,Spring Data Cassandra 提供了 CassandraRepository 接口,它继承了 CrudRepository 并额外支持 @Query 注解执行 CQL 语句。但是与关系型数据库不同,Cassandra 的查询条件非常受限,必须基于主键或二级索引,否则会触发全表扫描并导致性能灾难。下面的 Repository 定义了两个方法:按用户查询订单和按订单状态更新。
public interface OrderRepository extends CassandraRepository<Order, OrderKey> {
@Query("SELECT * FROM orders WHERE user_id = ?0")
List<Order> findByUserId(String userId);
@Query("UPDATE orders SET status = ?1 WHERE user_id = ?0 AND order_id = ?2")
void updateStatus(String userId, String orderId, String status);
}
注意这里主键类 OrderKey 需要单独定义,并与实体中的主键列对应。如果只使用简单主键,可以省略主键类。但复合主键使用主键类可以更好地表达分区键和聚簇键的关系。另外,@Query 中的 CQL 语句必须与表结构严格匹配,尤其是列名区分大小写的问题——Cassandra 中未加引号的标识符默认会被转成小写,所以实体中的列名要与建表语句保持一致。
实际开发中还有一个容易忽略的细节:Cassandra 不支持事务,也不支持跨分区原子操作。因此 Order 实体的更新必须基于完整主键执行,否则驱动会抛出 InvalidQueryException。如果需要批量写入多个分区,可以使用 BatchStatement,但要理解 Cassandra 的 batch 并不是事务,它只保证原子性在单分区内,跨分区 batch 可能造成热点并拖慢集群。
高可用配置与一致性调优
高可用是 Cassandra 的核心优势之一。Cassandra 通过数据副本和一致性级别的组合来提供容错能力。在 Spring Boot 中,可以通过 spring.data.cassandra.request.consistency 设置全局默认一致性级别,也可以在 @Query 注解中使用 @Consistency 为单个查询覆盖。常见的搭配方式如下表所示:
| 业务场景 | 读一致性 | 写一致性 | 说明 |
|---|---|---|---|
| 强一致读 | QUORUM | QUORUM | 读写都要求多数副本确认,能避免脏读但延迟较高 |
| 高可用写 | ONE | ANY | 写入容忍节点宕机,但读可能读到旧数据 |
| 低延迟读 | LOCAL_ONE | LOCAL_QUORUM | 只访问本地数据中心副本,适合多活架构 |
这里要特别区分 LOCAL_QUORUM 和 QUORUM。前者只计算本地数据中心的副本,适合多数据中心部署,避免跨机房网络延迟;后者计算所有数据中心的副本,在全球部署时可能导致写请求需要等待远端副本确认,拖慢整体响应。如果你的应用部署在单个数据中心,推荐使用 LOCAL_QUORUM 以获得更低延迟,同时保持本地多数副本的一致性。
Cassandra 的复制策略同样影响高可用。Keyspace 的复制模式通常在创建时指定,比如使用 NetworkTopologyStrategy 并为每个数据中心设置副本因子。Spring Boot 应用无法自动创建或修改这个策略,需要管理员提前执行 CQL:
CREATE KEYSPACE my_keyspace WITH replication = {
'class': 'NetworkTopologyStrategy',
'dc1': 3,
'dc2': 2
};
上面的配置表示 dc1 数据中心存储 3 份副本,dc2 存储 2 份。当某个节点宕机时,只要副本数满足一致性级别要求,读写请求依然可以成功。Spring Boot 客户端无需关心副本位置,驱动会根据 token 路由到正确的副本节点。
故障转移层面的调优还包括连接池大小和请求超时。默认情况下,Cassandra 驱动的连接池会根据节点数量和本地并发自动调整,但生产环境建议显式设置 spring.data.cassandra.pool.heartbeat-interval 和 spring.data.cassandra.request.timeout。例如:
spring:
data:
cassandra:
pool:
heartbeat-interval: 30s
idle-timeout: 60s
request:
timeout: 3s
page-size: 5000
设置合理的超时时间可以防止某个节点无响应时请求堆积。Cassandra 驱动内部会标记不可用节点并暂时剔除,当节点恢复后自动重新加入。这种机制结合一致性级别,使得应用在部分节点故障时依然保持可用。
最后要提醒一个常见的误区:很多团队在从关系型数据库迁移到 Cassandra 时,习惯性地使用 SELECT * FROM table 并且不加分区键过滤,这在 Cassandra 中是灾难性的。高可用分布式存储的前提是合理的查询建模,把访问模式放在设计阶段考虑,而不是事后补救。只有数据模型、复制策略和一致性级别三者协同,才能发挥 Cassandra 真正的分布式优势。
Spring BootCassandra分布式存储修改时间:2026-08-20 09:57:00