一、为什么选择Cassandra宽列存储

如果你用过传统的关系型数据库,比如MySQL,你会发现当数据量特别大或者需要快速写入时,性能可能会成为瓶颈。Cassandra作为一款分布式宽列存储数据库,天生适合处理海量数据和高并发写入的场景。

举个例子,假设你要做一个物联网平台,每天有上百万设备上报数据。如果用MySQL,单表数据量大了以后查询会变慢,分库分表又增加了复杂性。而Cassandra的分布式架构可以轻松水平扩展,写入性能几乎线性增长。

二、Cassandra数据建模的核心思想

和关系型数据库不同,Cassandra没有JOIN操作,它的查询模式决定了数据该如何组织。简单来说,Cassandra的数据建模要遵循一个黄金法则:

"基于查询来设计表结构"

也就是说,你要先想清楚业务中最常用的查询是什么,然后让表结构直接适配这些查询,甚至不惜数据冗余。

举个例子,我们要存储用户的订单信息。在MySQL里你可能会设计用户表和订单表,然后通过用户ID关联查询。但在Cassandra中,更好的做法是直接把用户信息和最新订单放在一起:

-- 技术栈:Cassandra CQL
CREATE TABLE user_recent_orders (
    user_id uuid,
    order_time timestamp,
    order_data text,  -- 订单详情JSON
    user_name text,   -- 用户名(冗余存储)
    PRIMARY KEY ((user_id), order_time)
) WITH CLUSTERING ORDER BY (order_time DESC);

注意两点:

  1. 主键的第一部分是分区键(user_id),决定了数据在集群中的分布
  2. 我们按order_time降序排列,这样最新订单总是排在前面

三、实际案例:电商库存系统设计

让我们看一个更复杂的例子:电商平台的库存管理系统。需要支持以下查询:

  1. 查看某商品的实时库存
  2. 获取某仓库的所有商品库存
  3. 查询库存低于警戒线的商品

在Cassandra中,我们可能需要设计多个表来优化不同查询:

-- 商品库存表(按商品查询优化)
CREATE TABLE product_inventory (
    product_id uuid,
    warehouse_id uuid,
    quantity int,
    last_updated timestamp,
    PRIMARY KEY ((product_id), warehouse_id)
);

-- 仓库库存表(按仓库查询优化)
CREATE TABLE warehouse_inventory (
    warehouse_id uuid,
    product_id uuid,
    quantity int,
    last_updated timestamp,
    PRIMARY KEY ((warehouse_id), product_id)
);

-- 低库存预警表
CREATE TABLE low_stock_alerts (
    alert_level int,  -- 警戒级别
    product_id uuid,
    warehouse_id uuid,
    quantity int,
    PRIMARY KEY ((alert_level), product_id, warehouse_id)
);

这种设计看起来有数据冗余,但在Cassandra中是完全正常的。我们通过写多个表来优化读性能,因为Cassandra的写入成本很低。

四、性能优化技巧

  1. 分区大小控制:单个分区的数据不宜过大,通常建议不超过100MB。比如按时间存储日志时,可以按天或周分区:
CREATE TABLE app_logs (
    log_date date,    -- 按天分区
    log_time timestamp,
    log_level text,
    message text,
    PRIMARY KEY ((log_date), log_time)
);
  1. 避免热点:如果分区键的值分布不均匀,会导致某些节点负载过高。比如用用户ID做分区键时,可以在前面加个哈希前缀:
CREATE TABLE user_actions (
    bucket int,       -- 0-9的哈希值
    user_id uuid,
    action_time timestamp,
    action_type text,
    PRIMARY KEY ((bucket, user_id), action_time)
);
  1. 合理使用物化视图:Cassandra的物化视图可以自动维护数据冗余,但要注意它会影响写入性能。

五、什么时候不该用Cassandra

虽然Cassandra很强大,但也不是万能的。以下场景可能不适合:

  1. 需要复杂事务的业务(如银行核心系统)
  2. 频繁更新的数据(Cassandra的更新实际上是写入新版本)
  3. 需要复杂JOIN操作的报表系统

六、最佳实践总结

  1. 先明确查询模式,再设计表结构
  2. 接受数据冗余,用空间换时间
  3. 控制分区大小,避免超大分区
  4. 考虑数据分布的均匀性
  5. 合理使用二级索引和物化视图

记住,Cassandra的数据建模是一门艺术,需要根据具体业务不断调整。刚开始可能会觉得反范式设计很奇怪,但一旦掌握,你会发现它能解决很多传统数据库难以处理的问题。