速度和可扩展性是ApacheCassandra不变的追求;了解如何充分利用其专业知识。ApacheCassandra是一个数据库,但它不仅仅是一个数据库;它是一个复制的数据库,针对可伸缩性、高可用性、低延迟和良好的性能进行了调整。Cassandra可以帮助您的数据在区域中断、硬件故障以及许多管理员认为数据过多的情况下幸存下来。凭借对数据分区的透彻了解,您可以使Cassandra集群设计良好、性能极佳且可扩展。在本文中,我将探讨分区的定义方式、Cassandra如何使用它们,以及您应该了解的一些最佳实践和已知问题。基本概念是这样的:数据分布、复制、索引等数据库关键功能使用的原子单元,单个这样的数据块就是一个分区。分布式数据系统通常将传入数据分配到这些分区中,使用简单的数学函数(例如身份或哈希函数)执行分区过程,并使用生成的“分区键”对数据进行分组并进一步形成分区。例如,假设传入的数据是服务器日志,使用“identity”分区函数和每个日志的时间戳(四舍五入到小时值)作为分区键,我们可以对这些数据进行分区,使每个分区保存一个小时的价值的日志。Cassandra中的数据分区Cassandra作为分布式系统运行,并遵循上述数据分区原则。使用Cassandra,数据分区依赖于在集群级别配置的算法和在表级别配置的分区键。Cassandra数据分区Cassandra查询语言(CQL)使用熟悉的SQL术语表、行、列等。在上面的示例图中,表配置的主键包括分区键,具体格式为:PrimaryKey=分区键+[聚类列]。Cassandra中的主键不仅定义了唯一的数据分区,还包含有关分区内数据排列的信息。数据排列信息取决于聚类列(可选)。每个唯一的分区键代表服务器中管理的许多行(包括其副本所在的服务器)。在CQL中定义主键接下来的四个示例演示了如何使用CQL语法来表达主键。定义主键会导致数据行被划分到不同的集合中,通常这些集合是分区。定义方法一(partitionkey:log_hour,clusteringcolumn:none)CREATETABLEserver_logs(log_hourTIMESTAMPPRIMARYKEY,log_leveltext,messagetext,servertext)这里log_hour相同的所有行都会进入同一个分区。定义方法2(partitionkey:log_hour,clusteringcolumn:log_level)CREATETABLEserver_logs(log_hourTIMESTAMP,log_leveltext,messagetext,servertext,PRIMARYKEY(log_hour,log_level))这种定义方法使用与方法1键相同的分区,但这样一来,每个分区的所有行都会按照log_level升序排列。定义方法3(分区键:log_hour,server,聚类列:none)CREATETABLEserver_logs(log_hourTIMESTAMP,log_leveltext,messagetext,servertext,PRIMARYKEY((log_hour,server)))在这个定义中,server和Rowswith同样的log_hour字段会进入同一个分区。定义方法4(分区键:log_hour,server,聚簇列:log_level)CREATETABLEserver_logs(log_hourTIMESTAMP,log_leveltext,messagetext,servertext,PRIMARYKEY((log_hour,server),log_level))WITHCLUSTERINGORDERBY(column3描述);这个定义方法和方法3分区一样,但是分区中的行会按照log_level降序排列。Cassandra如何使用分区键Cassandra依靠分区键来确定在哪个节点上存储数据并在需要时定位数据。Cassandra通过查看表中的分区键并使用令牌(-2^{63}?263到+2^{63}-1+263?1类型值范围内的长整数)来执行这些读取和写入数据分布和索引。这些令牌通过分区程序映射到分区键,分区程序使用分区函数将分区键转换为令牌。通过这种令牌机制,Cassandra集群的每个节点都拥有一组数据分区。然后分区键在每个节点上启用数据索引。具有3个节点和基于令牌的所有权图的Cassandra集群显示了一个三节点Cassandra集群和相应的令牌范围分配。这只是一个简单的示意图:具体实现过程使用Vnodes。数据分区对Cassandra集群的影响仔细的分区键设计对于为您的用例实现理想的分区大小至关重要。适当的分区可以实现数据分布均匀和强大的I/O性能。分区大小对Cassandra集群有几个需要注意的含义:读取性能-为了在磁盘上的SSTables文件中定位分区,Cassandra使用缓存、索引和索引摘要等数据结构。过大的分区会降低维护这些数据结构的效率,从而对性能产生负面影响。新版本的Cassandra在这方面取得了长足的进步:特别是Cassandra引擎版本3.6及更高版本引入了存储改进,为大型分区提供更好的性能以及对内存问题和崩溃的更强恢复能力。内存使用——更大的分区会给JVM堆带来更大的压力,更大的分区也会降低垃圾回收机制的效率。CassandraRepair-大分区使Cassandra更难执行修复维护操作(通过跨副本比较数据来保持数据一致)。“墓碑”删除-听起来很可怕,Cassandra使用称为“墓碑”的独特标记来记录要删除的数据。如果没有合适的数据删除模式和压缩策略,大分区会使删除过程更加困难。虽然这些影响可能有利于分区键的简单设计以产生小分区,但数据访问模式也对理想分区大小有很大影响(有关更多信息,请阅读我们关于Cassandra数据建模的深入教程)。数据访问方式可以定义为表的查询方式,包括表的所有select查询。理想情况下,CQL选择查询应在where子句中仅使用一个分区键。也就是说,当查询可以从单个分区而不是许多较小的分区中获取所需数据时,Cassandra效率最高。分区键设计的最佳实践遵循分区键设计的最佳实践原则,这将帮助您获得理想的分区大小。根据经验,Cassandra中最大的分区应保持在100MB以下。理想情况下,它应该小于10MB。虽然Cassandra3.6及更高版本对大分区有更好的支持,但每个工作负载都必须经过仔细测试和基准测试,以确保分区键设计支持所需的集群性能。具体来说,这些最佳实践原则适用于任何分区键设计:分区键必须旨在将理想数量的数据放入每个分区,以支持其访问模式的需要。分区键应该不允许无限分区:那些分区的大小可能会随着时间的推移无限增长。例如,在上面的server_logs示例中,随着服务器日志数量的不断增加,使用server列作为分区键会导致无界分区。相比之下,使用log_hour将每个分区限制为一小时数据的方案会更好。分区键还应避免创建分区偏斜,在这种情况下分区增长不均匀,并且某些分区可能会随着时间的推移无限增长。在server_logs示例中,在一台服务器生成的日志远远多于其他服务器的情况下使用服务器列会造成分区倾斜。为避免这种情况,从表中引入另一个属性以强制均匀分布是值得的,即使要创建一个虚拟列来这样做也是如此。使用时间元素和其他属性的复合分区键,有利于时间序列数据的分区。这种方法可以防止无限分区,允许访问模式在查询特定数据时使用时间属性,并允许删除特定时间段内的数据。上面的每个示例都使用log_hour时间属性来演示这一点。还有一些工具可用于帮助测试、分析和监控Cassandra分区,以检查所选模式是否有效。通过仔细设计分区键、调整解决方案的数据和要求并遵循优化分区大小的最佳实践原则,您可以充分利用数据分区并更好地发挥Cassandra的可扩展性和性能潜力。
