4、Cassandra深度解析:Cassandra特性、分布式架构原理、在ThingsBoard中的角色、安装与集群部署

好,咱们进入第四讲。这一章我打算好好聊聊Cassandra。说实话,在ThingsBoard的整个数据链路里,Cassandra是我个人觉得最「硬核」的一环。很多朋友刚开始接触TB时,看到默认数据库是Cassandra,心里会犯嘀咕:这玩意儿到底好在哪?为什么不用MySQL?

嗯,别急。咱们今天就把Cassandra的底裤扒干净。从它的核心特性,到分布式架构原理,再到它在ThingsBoard里具体扮演什么角色,最后我会手把手带你装一个集群。你跟着走一遍,心里就有底了。

4.1 Cassandra的核心特性

Cassandra是什么?说白了,它是一个去中心化的、分布式的NoSQL数据库。它最初由Facebook开发,后来捐给了Apache基金会。我最早接触它是在2015年,当时一个物联网项目的数据量暴涨,MySQL扛不住了,我们被迫换库。那会儿踩了不少坑,但也积累了一些经验。

它的核心特性,我归纳为四点:

  • 线性扩展能力:加节点就能提升性能,不需要停机。我在项目中见过从3个节点扩展到30个节点,吞吐量几乎线性增长。
  • 无单点故障:每个节点地位平等,没有主从之分。你挂掉一个节点,集群照样提供服务。
  • 最终一致性:Cassandra不追求强一致性,而是追求高可用。你想想看,物联网设备每秒上报成千上万条数据,如果每条都要等所有节点确认,那延迟得多高?
  • 列族存储模型:它不像关系型数据库那样有行有列,而是基于列族(Column Family)来组织数据。这个模型对时序数据特别友好。

重要提示:Cassandra的写入性能极强,单节点每秒可以处理数万次写入。但它的读取性能相对弱一些,尤其是范围查询。这一点在ThingsBoard中体现得很明显——写入遥测数据飞快,但查询历史数据时,如果没建好索引,可能会慢得让你怀疑人生。

4.2 分布式架构原理

Cassandra的分布式架构,我习惯用「环」来理解。所有节点组成一个环,数据按照分区键(Partition Key)的哈希值,均匀分布到各个节点上。

这里有几个关键概念:

  • 分区器(Partitioner):决定数据放在哪个节点。默认是Murmur3Partitioner,一致性哈希算法。
  • 副本因子(Replication Factor):一份数据存几份。比如RF=3,意味着每条数据存3个副本。
  • 一致性级别(Consistency Level):读写操作需要多少个节点确认才算成功。常用的有ONE、QUORUM、ALL。

举个例子。假设你有6个节点,RF=3。当你写入一条数据时,Cassandra会计算这条数据的主副本位置,然后自动把数据复制到环上接下来的两个节点。这样,即使你挂掉两个节点,数据依然完整。

我记得有一次线上事故,一个节点磁盘满了,直接宕机。但集群照常运行,用户完全没感知。这就是无单点故障的魅力。

避坑指南:我曾经犯过一个错误——把RF设成了1,觉得省空间。结果一个节点挂了,数据直接丢了一部分。后来我学乖了,生产环境RF至少设3,一致性级别用QUORUM。虽然写入慢一点,但数据安全第一。

4.3 在ThingsBoard中的角色

ThingsBoard为什么选Cassandra?说白了,物联网场景下,数据写入是海量的、持续的,但读取往往是最近的数据。Cassandra的写入性能正好匹配这个需求。

在ThingsBoard中,Cassandra主要存储以下几类数据:

数据类型说明Cassandra表名
遥测数据(Telemetry)设备上报的传感器值,如温度、湿度ts_kv_cf
最新遥测值每个设备每个属性的最新值ts_kv_latest_cf
事件数据告警、生命周期事件等event_storage
审计日志用户操作记录audit_log

其中,ts_kv_cf 是核心表。它的设计很有意思:

CREATE TABLE thingsboard.ts_kv_cf (
    entity_id timeuuid,
    key int,
    partition int,
    ts bigint,
    bool_v boolean,
    str_v text,
    long_v bigint,
    dbl_v double,
    PRIMARY KEY ((entity_id, key, partition), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

注意这个主键设计。分区键是 (entity_id, key, partition),排序键是 ts。这意味着同一个设备、同一个属性键的数据,会按照时间戳倒序排列。查询最近100条数据时,效率极高。

嗯,这里要注意。如果你要查询某个设备一整天的数据,Cassandra可能就不太擅长了。因为数据分散在不同的分区里,需要扫描多个分区。我一般建议在ThingsBoard中配置数据保留策略,比如只保留7天的原始数据,超过的自动清理。

4.4 安装与集群部署

好,咱们动手。我以Ubuntu 20.04为例,部署一个3节点的Cassandra集群。

4.4.1 单节点安装

先装Java。Cassandra依赖Java 8或11:

sudo apt update
sudo apt install openjdk-11-jdk -y
java -version

然后下载Cassandra。我习惯用4.0版本,稳定且性能好:

wget https://dlcdn.apache.org/cassandra/4.0.7/apache-cassandra-4.0.7-bin.tar.gz
tar -xzf apache-cassandra-4.0.7-bin.tar.gz
sudo mv apache-cassandra-4.0.7 /opt/cassandra

配置环境变量:

echo 'export CASSANDRA_HOME=/opt/cassandra' >> ~/.bashrc
echo 'export PATH=$PATH:$CASSANDRA_HOME/bin' >> ~/.bashrc
source ~/.bashrc

启动Cassandra:

sudo /opt/cassandra/bin/cassandra -R

nodetool status 检查状态。看到 UN 表示节点正常。

警告:Cassandra默认会占用大量内存。如果你是在开发机上测试,建议修改 conf/jvm.options 文件,把 -Xms-Xmx 调小,比如设为2G。否则你的机器可能会卡死。我曾经在2G内存的云服务器上直接跑默认配置,结果SSH都连不上了。

4.4.2 集群部署

假设你有三台机器:

  • node1: 192.168.1.101
  • node2: 192.168.1.102
  • node3: 192.168.1.103

每台机器都按上面的步骤安装好Cassandra。然后修改 conf/cassandra.yaml 文件:

cluster_name: 'ThingsBoard Cluster'
seed_provider:
    - class_name: org.apache.cassandra.locator.SimpleSeedProvider
      parameters:
          - seeds: "192.168.1.101,192.168.1.102"
listen_address: 192.168.1.101  # 每台机器填自己的IP
rpc_address: 0.0.0.0
endpoint_snitch: GossipingPropertyFileSnitch

注意,种子节点(seeds)只需要配置2-3个,不需要把所有节点都列进去。我一般选前两个节点作为种子。

然后修改 conf/cassandra-rackdc.properties

dc=DC1
rack=RAC1

如果你有多个数据中心,可以在这里配置。不过咱们先简单点,所有节点都在同一个数据中心。

配置完成后,依次启动每个节点。启动顺序无所谓,Cassandra会自动发现彼此。

启动后,用 nodetool status 查看集群状态。你应该能看到三个节点都是 UN 状态。

4.4.3 配置ThingsBoard连接Cassandra

最后一步,让ThingsBoard连上你的Cassandra集群。修改ThingsBoard的 conf/thingsboard.yml 文件:

cassandra:
  cluster_name: "ThingsBoard Cluster"
  contact_points: "192.168.1.101,192.168.1.102,192.168.1.103"
  keyspace: "thingsboard"
  replication_factor: 3

重启ThingsBoard服务。如果一切正常,ThingsBoard会自动创建所需的表结构。

个人经验:我第一次部署集群时,忘了改 listen_address,结果节点之间互相找不到。排查了半天才发现是IP没改。你配置的时候,一定记得每台机器的 listen_address 要填自己的IP,不要照抄我的示例。

好了,这一章的内容就到这里。Cassandra的深度解析,咱们从特性讲到了架构,再到ThingsBoard中的角色,最后动手部署了集群。下一章,我会带你看看PostgreSQL在ThingsBoard中的用法,以及它和Cassandra如何配合。咱们到时候见。