Understanding the architecture-P
一个分区器决定了数据将会在集群的节点中如何分布(包括副本)。从根本上说,一个分区器就是一个function,根据hash从partition key产生一个token,代表一行数据。每一行数据会通过这个hash值分布在集群中。
Murmur3Partitioner 和RandomPartitioner 都是使用token将数据均匀分配到每个节点。通过ring或者其他的分组方式如keyspace,将来自所有table的数据均匀的分配(在节点上)。即使表使用不同的partition keys,比如usernames,或者timestamps都没有关系(都会均匀的分配在每个节点)。不仅如此,打到集群的读写请求也能均匀的分布。因为每个hash-range都负责相同数量的行,所以负载均衡被简化了。
这两个分区器的主要不同点在于如何去产生token值。RandomPartitioner 使用加密hash,所以需要产生hash值的时间更长。但Cassandra并不需要加密的hash,因此使用Murmur3Partitioner能够有3-5倍的性能提升。
Cassandra提供了以下3种partitioners,可以在cassandra.yaml文件中配置。
Murmur3Partitioner(默认): 基于MurmurHash hash,将数据均匀的分布在集群
RandomPartitioner: 基于MD5 hash,将数据均匀的分布在集群中
ByteOrderedPartitioner: 通过键的字节来保持数据词汇的有序分布
Murmur3是Cassandra1.2+ 默认的分区策略。这也是大多数集群的正确选择。分区器并不是可适应的。数据通过某个分区器分区后,不是很容易就能转换为另一个分区器的。
Note
如果使用了虚拟节点,你不需要去计算tokens。如果不使用虚拟节点,则必须要计算tokens,将cassandra.yaml中的initial_token参数设为这些tokens。可以参考Generating tokens,然后使用Partitioner对应的function来产生token。
Murmur3Partitioner
Murmur3Partitioner 是默认的分区器,提供了更快的hashing。相比较其他的分区器,极大的提高了性能。Murmur3Partitioner 可以在虚拟节点情况下使用。如Generating tokens中所述,如果不使用虚拟节点,则必须要计算tokens。
可以在一个刚搭建的新集群中使用Murmur3Paritioner; 但不能在一个已有的集群中更换分区器。Murmur3Partitioner 使用MurmurHash function,这个hashing function为partition key创建一个64位的hash值。可能的范围值是-2^63 到(2^63)-1.
使用Murmur3Partitioner,可以在一个CQL 查询中使用token function 对结果分页
RandomPartitioner
RandomPartitioner 是Cassandra1.2 之前版本的默认分区器。RandomPartitioner可以和虚拟节点一起使用。如Generating tokens中所述,如果不使用虚拟节点,则必须要计算tokens。RandomPartitioner 使用row key的MD5 hash值将数据均匀的分布在集群的节点上,hash 值的范围值是(2^127)-1
使用RandomPartitioner,可以在一个CQL 查询中使用token function 对结果分页
ByteOrderedPartitioner
ByteOrderedPartitioner 使分区有序。通过key的字母顺序来对row排序。可以看partition key数据的实际值来计算token,采用16进制表示key的首字母。例如,如果你想让行按字母顺序排列,你可以指定一个token A使用16进制的41表示。
使用有序分区器允许通过主键有序扫描。这意味着你可以扫描行就好像在索引中移动游标。例如,如果你的程序使用usernames作为行键值,你可以扫描用户(姓名在Jake和Joe之间)。对于Random分区器是无法实现的,因为键值按照username的MD5的存储,而不是顺序的。
尽管对于有序分区器来说,扫描行这种能力听起来是一个很棒的特性,但通过table indexes也能实现同样的功能。
因为以下原因,不建议使用有序分区器:
负载平衡难
需要更多的管理开销去实现集群的负载平衡。一个顺序的分区器需要管理员根据行键值的可能的分布情况去手动计算 partition ranges。在实践中,一旦数据已经加载后,需要经常性的改变节点的token去适应实际数据的分布。
顺序写导致热点
如果你的程序在某一段时间内的写入或者更新包含很多按顺序排列的行的时候,它们不会均匀的分布在集群上,会分布同一节点上。对于处理和时间相关的数据的app来说,这通常是一个问题。
多表时负载不平衡
如果你的应用程序用到多个表,这些表有不同的row keys 和不同的数据分布。在同一个集群中,对于某一张表balance分布了,但对于另一个表,可能会导致热点和不均匀分布。