Cassandra作为一个分布式NoSQL数据库,数据如何分布到集群各个节点是最核心的设计问题之一。决定数据分布的关键组件就是partitioner,中文叫分区器。分区器负责根据partition key计算出一个token值,集群再依据这个token判断数据应该归属哪个节点。Cassandra目前默认使用的分区器是Murmur3Partitioner,也是官方推荐的唯一选择。这篇文章就来详细聊聊Murmur3分区器的原理、配置方法以及使用中的注意事项。

一、分区器的核心作用与Murmur3的基本原理
在Cassandra中,每条数据写入前,都要先经过分区器计算。分区器拿partition key作为输入,输出一个固定范围内的数值,这个数值就是token。整个token空间形成一个环状结构,也就是常说的token ring。每个节点在环上拥有一个或多个token区间,数据落在哪里,完全由分区器算出的结果决定。
Murmur3Partitioner使用的是MurmurHash 3算法。这个算法最初由Austin Appleby在2008年提出,名字来源于两个mul操作,因为它在计算过程中大量使用乘法。与传统的加密哈希不同,MurmurHash追求的不是安全性,而是速度和分布均匀性。它不抗碰撞攻击,但对于数据分片这种场景来说,这恰恰不是问题,反而是优势——省去了加密操作的开销,吞吐量提升明显。
Murmur3Partitioner的token范围是-2的63次方到2的63次方减1,也就是一个64位有符号长整型所能表示的全部数值。它直接对partition key的字节进行哈希,输出一个64位的token。相比老版RandomPartitioner使用的MD5哈希(token范围是0到2的127次方减1),Murmur3计算更快、生成的token更短,比较和存储开销更小。从Cassandra 1.2版本开始,Murmur3成为默认分区器,RandomPartitioner则逐渐被标记为过时。
二、Murmur3与其他分区器的对比
Cassandra历史上提供过三种分区器,除了Murmur3Partitioner和RandomPartitioner,还有一个几乎没人使用的ByteOrderedPartitioner。理解三者的差异,有助于明白为什么Murmur3最终胜出。
ByteOrderedPartitioner简称BOP,它直接把partition key的字节作为token。这样做的好处是数据按key的字典序排列,支持范围扫描partition key。但缺点非常致命:容易出现数据热点。比如按时间作为key前缀时,所有新写入都集中在一个区间,导致某个节点持续过载。同时顺序写入还会导致旧数据与新数据分布失衡,memtable合并和compaction压力集中。官方早已明确不建议使用BOP。
RandomPartitioner使用MD5哈希,分布均匀性没问题,但MD5计算成本高,token是128位的大整数,占用的空间和比较成本都更大。Murmur3在保证分布质量的同时,哈希速度比MD5快数倍。下面这个表格总结了三者的主要区别:
| 分区器 | 哈希算法 | token范围 | 数据分布 | 是否推荐 |
|---|---|---|---|---|
| Murmur3Partitioner | MurmurHash 3 | -2^63 ~ 2^63-1 | 均匀 | 推荐,默认 |
| RandomPartitioner | MD5 | 0 ~ 2^127-1 | 均匀 | 已过时 |
| ByteOrderedPartitioner | 无(key本身) | 字节序 | 易倾斜 | 不推荐 |
需要注意的是,token值的具体大小本身没有业务含义。Murmur3算出的token可能是负数,这只是因为64位有符号整型的表示方式,不代表任何排序或优先级问题。
三、Murmur3分区器的配置方法
分区器的配置位于cassandra.yaml文件中,通过partitioner参数指定。对于新建集群,直接使用默认值即可:
# cassandra.yaml 中的分区器配置 # 默认就是 Murmur3Partitioner,一般无需修改 partitioner: org.apache.cassandra.dht.Murmur3Partitioner
配置文件中只需要写类的简短名称,Cassandra会自动补全完整的包路径。如果写完整类名也可以,两种写法等价。
除了集群级别的分区器,还可以针对单个表调整token感知行为。比如在创建表时使用token函数进行查询。下面是一个查询特定token范围数据的示例:
-- 查看 token 的计算结果 SELECT token(user_id), user_id, user_name FROM my_keyspace.users WHERE user_id = 'user123'; -- 如果需要手动指定 token 分区,可以使用大括号语法 SELECT * FROM my_keyspace.users WHERE token(user_id) > -4611686018427387904 AND token(user_id) <= 0 ALLOW FILTERING;
此外,虚拟节点(vnode)与Murmur3配合使用时,建议将initial_token留空,让Cassandra自动分配token。num_tokens参数默认值是256,也就是说每个节点会在token环上随机占据256个位置,这大幅提升了数据分布的均匀程度。
四、分区器选择的常见问题与注意事项
分区器一旦选定就无法在线更换,这是最容易踩的坑。因为不同分区器对同一个key计算出的token完全不同,如果强行把一个现有集群从RandomPartitioner切换到Murmur3,所有数据的归属关系都会错乱,Cassandra会找不到已有的数据。如果确实需要迁移,只能通过新建集群加数据搬运的方式,比如用Spark或者COPY命令导出再导入。
第二个常见问题是数据倾斜的排查。即便Murmur3分布均匀,如果partition key设计不当,依然会出现大分区。比如一个分区积累了上亿行数据,再均匀的哈希也救不了。可以用下面的命令检查各节点的数据分布情况:
-- 查看各个表的最大分区大小(需要开启对应的表属性) SELECT * FROM system.size_estimates WHERE keyspace_name = 'my_keyspace';
第三个注意点与 Cassandra 的重建和修复操作有关。使用Murmur3时,nodetool工具输出的token范围可能显示为负数到正数的跨越区间,这是正常的,不要误以为是配置错误。同时在做增删节点操作时,依赖vnode自动分配即可,无需手动计算token,这也是Murmur3加vnode方案最大的便利之处。
总结一下,Murmur3Partitioner凭借MurmurHash算法的高性能和良好分布特性,成为Cassandra数据分区的标准方案。新集群直接使用默认配置即可,重点应该放在partition key的设计上,避免超大分区的产生。而对于仍在使用RandomPartitioner的老集群,规划一次数据迁移是值得投入的工作。
Cassandra partitionerMurmur3分区器Cassandra配置修改时间:2026-09-06 02:54:38