Cassandra读数据到底咋回事,内部流程和细节那些你可能没注意到的东西
- 问答
- 2026-01-16 04:26:05
- 2
关于Cassandra读数据的过程,很多人可能只知道它很快,是去多个节点读,但里面的门道其实很深,它不像传统数据库那样直接去主节点要数据就完事了,而是一个涉及协调、猜测、比较和修复的复杂过程。
你得忘掉“主节点”这个概念,Cassandra是去中心化的,你连接的任何节点都可以作为“协调者”,当你发送一个读请求给协调者节点时,好戏就开始了,协调者会根据你数据的主键和配置的副本策略,算出这个数据应该存储在哪些节点上(这些节点叫副本节点),这里第一个细节就来了:协调者会向所有副本节点发送读请求吗?不一定。
Cassandra有一个叫“读一致性级别”的设置,比如ONE、QUORUM、ALL,如果你设成ONE,协调者只会向一个副本节点要数据;如果设成QUORUM,它会向足够多的节点要数据(通常是超过半数),但这里有个关键点,为了速度,即使你设成ONE,协调者默认也会向所有存有这个数据的副本节点发送请求(这个行为由read_request_timeout_in_ms等参数控制,它会在超时前等待所有响应,但最终只根据一致性级别决定需要多少份有效响应),它这么做不是为了满足一致性级别,而是为了一个更重要的目的:读修复。

这就引出了最核心、也是最容易被忽略的细节之一,数据在多个副本上可能不一致,因为写入可能有时延或者节点曾经宕机,Cassandra在读取的时候,是解决这种不一致的最佳时机,协调者向多个节点(即使一致性级别是ONE)要数据,收到响应后,它会做一个“摘要查询”和“完整数据查询”的区分,它会向一个节点请求完整的数据行,向其他节点只请求一个数据的“(比如基于时间戳的哈希值),这样做是为了减少网络传输,协调者比较这些响应:
- 如果所有副本返回的摘要或数据都一致,那最好,它直接把数据返回给客户端。
- 如果不一致,协调者就会发现冲突,这时,它会向持有最新版本数据的节点(根据Cassandra的“最后写入获胜”规则,通过比较时间戳决定)请求完整数据,然后将这个最新的数据返回给客户端。
但事情还没完!接下来就是“读修复”,协调者会在后台,把刚才确定的最新数据,悄悄地写回那些持有旧版本数据的副本节点上,这个过程对客户端是透明的,你几乎无感,这就是为什么Cassandra能最终一致——通过不断的读操作,自动修复数据的不一致,这是它内部一个非常巧妙的设计。

另一个深一点的细节是关于墓碑的处理,当你删除一条数据时,Cassandra并不立即物理删除,而是写一个叫“墓碑”的特殊标记,在读取时,如果协调者发现某个副本返回的数据带有墓碑,而其他副本返回的是真实数据,它就会根据墓碑的时间戳和策略来判断这条数据到底应该被认为是存在的还是已被删除的,如果确认为已删除,它会在返回结果给客户端的同时,启动读修复,用这个墓碑去“覆盖”那些还存有旧数据的副本,确保删除操作也能最终一致。
然后不得不提的是SSTable和MemTable的配合,数据在内存中叫MemTable,满了之后会被刷到磁盘上,形成一个个不可变的SSTable文件,一次读请求,协调者节点(如果它本身也是副本)或者副本节点在处理时,它可能既要去内存中的MemTable里找,又要去磁盘上多个不同时间生成的SSTable文件里找,为了高效,Cassandra用了布隆过滤器,每个SSTable都有一个布隆过滤器,它是一个很快的数据结构,能告诉你“这个SSTable肯定不包含你要的键”或者“可能包含你要的键”,这样,节点就不用傻傻地扫描每一个SSTable文件,而是先问布隆过滤器,只去那些“可能包含”键的SSTable里查找,大大提升了速度。
还有一个影响性能的关键点:压缩,因为SSTable文件越来越多,读操作需要检查的文件也越多,速度会变慢,Cassandra有个后台进程叫压缩,它会将多个SSTable合并成一个新的SSTable,在这个过程中,它会合并重复的数据(保留最新的),并清除掉已经过了存活时间的墓碑,一个好的压缩策略对维持读性能至关重要。
Cassandra的读远不止是“去拿数据”,它是一个由协调者导演的,涉及多节点通信、数据版本比较、后台修复(读修复)、多层存储(MemTable+SSTable)查询和高效过滤(布隆过滤器)的协同流程,它巧妙地将数据一致性修复的成本分摊到了日常的读操作中,用空间(多节点查询)和后台计算换取了高可用和最终一致性。
本文由度秀梅于2026-01-16发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/81580.html
