前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Cassandra的数据布局 - 调试SSTables

Cassandra的数据布局 - 调试SSTables

作者头像
you
发布2018-05-30 11:26:40
3.2K0
发布2018-05-30 11:26:40

当您事先知道数据的格式并且可以基于过往的经验做决策时,使用Apache Cassandra处理大规模的该类型的数据是非常容易的。

我们最近为一家基于用户行为推送广告的营销公司提供服务,其数据格式主要基于短时间内大多数用户(存储在数据库中的有效UUID标识)的广告点击行为。当用户打开某个网站并点击某个广告时,系统会将该用户的UUID记录在数据库中并且将用户的广告点击次数作为用户的画像记录在后台系统中(系统通过这些历史数据可以勾勒出用户的喜好并且推荐合适的广告给他们)。通常情况下,用户在初次访问网站5分钟之内就会离开且再次访问的比率不足1%。

营销公司的案例对我们调试SSTables并不重要,但是对我们在部署Cassandra时如何设置某些属性非常重要,它能够告诉我们为什么我们需要深入到SSTable层级去了解数据。我们使用的是Cassandra的3.x版本,携带了很多可以操作SSTable的工具。基于前文叙述的场景,我们使用的是一种全新的且未大规模使用的被称为TimeWindowCompaction的策略,其中Window周期为1天、数据的TTL(存活周期)为30天。之所以这样选择,是因为我们认为99%的数据读取访问需求能够被缓存在系统内存的最近的SSTable满足(通常同一天内读取请求总是在写入请求完成之后的很短的时间内发生的)。TWCS(Time Window Compaction Strategy

,时间窗口合并策略,下文同)看起来特别适合类似这样的场景,虽然读取一天之前的数据只能很慢地从众多SSTables中读取,但是这部分回头用户的比率不足1%,所以我们可以不用做特别的优化处理,是这样吗?

实际不是的,因为在运行几天之后,得到的结果让我们感到震惊。nodetool tablehistograms命令显示出在10天的周期中,50%的数据读取访问至少读取了10个SSTables,这就需要10次磁盘寻道和磁盘读取,从而与内存读取或者少量的磁盘读取相比需要花费更长的时延。这个现象驱使我们去研究我们的数据的格式以及如何在磁盘上布局的,也给我们提供了机会去研究SSTable工具及其配置选项并写下本文。

当然,直觉上我们认为nodetool会提供很多有用的命令帮助我们定位数据实际的布局的细节。我们深入的挖掘我们写入的数据并提取了部分读取访问时延很高的请求的UUID用于后续的分析研究。接下来本文将描述我们是如何一步一步地确定这些UUID表示的请求的高延时是因为大量的SSTable从磁盘的读取导致的。

Nodetool Tablehistograms [Keyspace] [Table]

这是第一个很有用的命令。请注意,从Cassandra3.x版本才改名为tablehistograms,之前版本叫cfhistogram,但是两个命令都可以兼容。同样的,cfstats和tablestats也是类似的。对于指定的表(table),该命令可以展示如下有用的信息,比如不同百分比时的访问延时、单个读取请求访问的SSTables的个数、分区的大小、单元格个数。它的输出信息非常清晰比如首先会给出是否出现错误。在我们的示例中,该命令展示了50%的读取请求需要访问10个SStables。

代码语言:javascript
复制
centos@cassandra - c -2 ] $ nodetool tablehistograms keyspace table ;
keyspace / table histograms
Percentile SSTables Write Latency Read Latency Partition Size Cell Count
                              ( micros )           ( micros )            ( bytes )
50 %             10.00              14.24             182.79                103                  1
75 %             10.00              17.08             315.85                149                  2
95 %             10.00              20.50            7007.51                372                  7
98 %             10.00              24.60           10090.81                642                 12
99 %             10.00              29.52           12108.97                770                 14
Min              8.00               3.31              29.52                 43                  0
Max             13.00            1358.10           62479.63               1597       

Nodetool Tablestats [Keyspace]

接下来的第二步我们通常会查看是否有故障。该命令会展示关于该表的键空间的详细的汇总信息,包括总的SSTable个数、memtable的元数据信息、bloom filters、每行的单元格信息以及键的个数。在我们的示例中,总计有12个SSTables,而上一步中通过cfhistograms获取的信息表明我们在读取请求时访问了绝大部分的SSTables。另外,比较重要的信息是Bloom filter false positives和Bloom filter false ratio的值,Bloom filter用来标明Cassandra的某个SSTable没有某个数据的概率,而false positives表示误报数据在SSTable不存在的数量,从这两项的信息可知我们并没有出现Bloom filter的误报。同时信息还展示了由于数据实际是存储在10个SSTables中,因而我们确实访问了10次SSTables。

代码语言:javascript
复制
Keyspace : keyspace
Read Count :  72628768
Read Latency :  0.7189103991823186 ms .
Write Count :  652226331
Write Latency :  0.012940205744315465 ms .
Pending Flushes :  0
Table : table
SSTable count :  13
Space used  ( live ) :  99252365458
Space used  ( total ) :  99252365458
Space used by snapshots  ( total ) :  0
Off heap memory used  ( total ) :  892785184
SSTable Compression Ratio :  0.0
Number of  keys  ( estimate ) :  279335104
Memtable cell count :  710670
Memtable data size :  40221377
Memtable off heap memory used :  0
Memtable switch count :  903
Local read count :  72628771
Local read latency :  0.981 ms
Local write count :  652226458
Local write latency :  0.015 ms
Pending flushes: 0
Bloom filter false positives: 1
Bloom filter false ratio: 0.00000
Bloom filter space used: 759080720
Bloom filter off heap memory used: 759080536
Index summary off heap memory used: 133704648
Compression metadata off heap memory used: 0
Compacted partition minimum bytes: 43
Compacted partition maximum bytes: 1597
Compacted partition mean bytes: 150
Average live cells per slice (last five minutes): 13.261506069748489
Maximum live cells per slice (last five minutes): 35
Average tombstones per slice (last five minutes): 1.0
Maximum tombstones per slice (last five minutes): 1

SSTablemetadata工具

接下来就是Cassandra提供的可以帮助调试SSTables的一些SSTable工具。其中一个就是SSTablemetadata,该工具的所有的细节信息都可以在DataSTax网站找到。它可以帮助显示特定的SSTable的很多有用的信息,比如最小时间戳、最大时间戳、可清理的tombstones(tombstone用于表明已删除的列)、关于tombstone的细节信息等。由于Alex Dejanovski在Last Pickle网站的博客描述了TWCS -它是如何工作,你应该什么时候使用它,在最小时间戳和最大时间戳一致时,我们可以很容易的把我们从SSTables中获取的元数据用到TWCS中并进行调试。

代码语言:javascript
复制
for f in *Data.db; do meta=$(sudo sstablemetadata $f); echo -e "Max:" $(date --date=@$(echo "$meta" | grep Maximum\ time | cut -d" "  -f3| cut -c 1-10) '+%m/%d/%Y') "Min:" $(date --date=@$(echo "$meta" | grep Minimum\ time | cut -d" "  -f3| cut -c 1-10) '+%m/%d/%Y') $(echo "$meta" | grep droppable) ' \t ' $(ls -lh $f | awk '{print $5" "$6" "$7" "$8" "$9}'); done | sort    

上面的命令将会遍历所有的SSTable数据文件,执行sstablemetadata命令并获取每个文件的最小和最大的时间戳、可清理的tombstone的个数和部分来源于"ls"命令的文件属性信息。我们的示例显示我们的表除了最新一天的SSTable使用SizeTieredCompaction之外,其他的都确实存储了1天以上的数据。

代码语言:javascript
复制
[centos@cassandra-c-3]$ for f in *Data.db; do meta=$(sudo sstablemetadata $f); echo -e "Max:" $(date --date=@$(echo "$meta" | grep Maximum\ time | cut -d" "  -f3| cut -c 1-10) '+%m/%d/%Y') "Min:" $(date --date=@$(echo "$meta" | grep Minimum\ time | cut -d" "  -f3| cut -c 1-10) '+%m/%d/%Y') $(echo "$meta" | grep droppable) ' \t ' $(ls -lh $f | awk '{print $5" "$6" "$7" "$8" "$9}'); done | sort
Max: 01/01/2017 Min: 12/31/2016 Estimated droppable tombstones: 0.0    5.0G Jan 6 08:30 mc-647149-big-Data.db
Max: 01/02/2017 Min: 01/01/2017 Estimated droppable tombstones: 0.0    4.7G Jan 6 08:26 mc-647148-big-Data.db
Max: 01/03/2017 Min: 01/02/2017 Estimated droppable tombstones: 0.0    3.7G Jan 6 08:18 mc-647147-big-Data.db
Max: 01/04/2017 Min: 01/03/2017 Estimated droppable tombstones: 0.0    3.7G Jan 6 08:16 mc-647146-big-Data.db
Max: 01/05/2017 Min: 01/04/2017 Estimated droppable tombstones: 0.0    5.6G Jan 6 08:29 mc-647145-big-Data.db
Max: 01/06/2017 Min: 01/05/2017 Estimated droppable tombstones: 0.0    4.0G Jan 7 00:28 mc-647404-big-Data.db
Max: 01/07/2017 Min: 01/06/2017 Estimated droppable tombstones: 0.0    5.5G Jan 8 00:25 mc-647749-big-Data.db
Max: 01/08/2017 Min: 01/07/2017 Estimated droppable tombstones: 0.0    5.1G Jan 9 00:39 mc-648048-big-Data.db
Max: 01/09/2017 Min: 01/08/2017 Estimated droppable tombstones: 0.0    1.7G Jan 9 12:38 mc-648130-big-Data.db
Max: 01/09/2017 Min: 01/09/2017 Estimated droppable tombstones: 0.0    112M Jan 9 12:51 mc-648135-big-Data.db
Max: 01/09/2017 Min: 01/09/2017 Estimated droppable tombstones: 0.0    31M Jan 9 12:55 mc-648136-big-Data.db
Max: 01/09/2017 Min: 01/09/2017 Estimated droppable tombstones: 0.0    31M Jan 9 13:00 mc-648137-big-Data.db
Max: 12/31/2016 Min: 12/30/2016 Estimated droppable tombstones: 0.0    5.2G Jan 6 08:31 mc-647150-big-Data.db

Nodetool Getendpoints [Keyspace] [Table] [Primary_Key]

在我们通过tablehistogram证明我们的读取请求确实访问很多SSTables并且Bloom filter没有出现误报之后,我们希望能证明那些有问题的UUIDs(请求时延很高的UUIDs)需要访问的数据确实分散在多个SSTables中。所以我们选取了部分UUIDs并用Getendpoints命令进行验证,该命令能够展示一个特定的主键存储在哪些机器上。首先我们需要登录拥有数据的机器,然后才能获取相应的SSTables。

代码语言:javascript
复制
[centos@cassandra-c-1 ~]$ nodetool getendpoints keyspace table 71cc1d9a-c161-485b-a2a7-ba0fbfb34bef;
cassandra-c-1
cassandra-a-2
Cassandra-b-3

从命令结果可知,该UUID存在于展示的3个机器上,我们可以使用nodetool getsstables命令去获取该UUID实际位于哪个SSTable中。

Nodetool GetSSTables [Keyspace] [Table] [Primary_Key]

接着我们看一个很酷的命令getsstables,它能展示一个特定的主键的数据具体存在于哪些磁盘上的SSTables文件中。基于前文所述的所有信息,我们希望能证明那些延时很高的UUIDs确实是分散在硬盘上的多个SSTables中。我们使用如下的一些高延时的UUIDs作为示例。

代码语言:javascript
复制
[centos@cassandra-c-1 ~]$ nodetool getsstables table keyspace 71cc1d9a-c161-485b-a2a7-ba0fbfb34bef;
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571812-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-572698-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-572403-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571804-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571808-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571807-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571809-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-571805-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-573006-big-Data.db
/mnt/cassandra/data/data/keyspace/table-62f30431acf411e69a4ed7dd11246f8a/mc-573001-big-Data.db

结果显示这个特定的UUID的数据分散在10个SSTables中同时也表明这个UUID的数据是每天写入的(因为我们使用的TWCS是1天的桶,也就是说该UUID的数据位于同一天的SSTable中并且读取时需要合并10个SSTables的数据)。

CQLSH追踪

到此为止,我们知道了某个UUID的数据分散在很多SSTables中,但是这对读请求的访问路径有什么影响呢?最简单的验证方式就是开启CQLSH(Cassandra Query Language Shell)并启动过程追踪。追踪是Cassandra的一个很酷的特性,能够展示每个查询请求的读取路径的完整细节(请注意追踪是很消耗资源的,所以最好只在调试时打开该功能)。当追踪功能开启时,所有命令都将被追踪,而追踪结果展示出某个UUID的读取的数据确实是合并了来自10个SSTables的内容。

代码语言:javascript
复制
Merging data from memtables and 10 sstables [SharedPool-Worker-2] | 2017-01-10 10:39:16.092003 | 10.200.254.23 |           1328

上述追踪得到的信息证实了我们前面提到的某个UUID的读取请求的数据来源于10个SSTables数据的合并。

SSTable系列工具

浏览互联网时,我们偶然发现了sstable-tools - 一系列非常酷并且很有用的辅助SSTables的工具。Andy Tolbert(来自DataStax的开发人员)开发了它们并将其作为产品的一部分引入了Cassandra4.0,它提供了很多有用的特性,比如提供了一个类似于Cassandra用于查询表的cqlsh shell工具,但是该工具仅局限在SSTable内部进行查询,对于定位单个文件内部到底有哪些内容非常有用。它主要使用类似于sstablemetadata的输出描述SSTable的内容,但是输出结果具有更结构化和更易读的呈现方式。总的来说它展示了列数目的柱状图、分区大小的柱状图、最新tombstones、最小和最大的时间戳,对于调试tombstones和多分区时真的很有用。

结论

在上面的文章中,我们展示了我们的调试过程以及我们如何最终证明那些延时较高的读取请求是因为读取请求路径需要访问多个SSTables导致的。我们验证了一个延时敏感的用例,从我们选择的压缩合并方式看读取指定的主键理应只有1个SSTable文件的磁盘访问(最新的文件),但是结果恰恰相反,访问分散在多个SSTables中从而导致多次磁盘访问。这就非常清晰地表明我们并不知道我们数据的访问模式且我们对于访问模式也没有一个清晰的概念。针对这个问题,比较好的解决方案是使用LeveledCompactionStrategy,它以层级的方式存储数据可以以较少的SSTables读取在更多的使用场景中提供更好的性能表现。调整策略后,我们的测试验证了每个读请求至少减少了1~3次SSTables的访问从而有效地提升了性能(99.9%的请求延时有2倍的提升)。

您是如何调试SSTables中的数据的,您是否还有本文没有提到的很酷的工具可以用于定位数据在磁盘的位置的?

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Nodetool Tablehistograms [Keyspace] [Table]
  • Nodetool Tablestats [Keyspace]
  • SSTablemetadata工具
  • Nodetool Getendpoints [Keyspace] [Table] [Primary_Key]
  • Nodetool GetSSTables [Keyspace] [Table] [Primary_Key]
  • CQLSH追踪
  • SSTable系列工具
  • 结论
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档