第四步,数据的落盘,这个动作通常是异步的,在后面会详细展开将SSTable的存储 。第五步,这个就是多节点特性了,是一个节点异常的处理过程 。
总结一下,传统的数据库的写入(包括INSERT、UPDATE、Delete),通常是一个读后写的过程 。而Cassandra的写入,是没有先读这个动作的,这也是它快的根本原因 。一旦使用了IF NOT EXIST之类的语法,那么它的写入性能也就会要受损 。
接下来看一下Cassandra的读取,它的读取是多节点、多副本的读取 。此处,我们先关注一个节点上的情况 。

文章插图
第一步,如果这一行数据在Row Caches中,直接返回数据,这个好理解 。
第二步,检查检查KeyCaches里的索引,这里可以理解为,这是一个主键索引,它存储的是未来在Memtables或者SSTables用来定位的信息(书上原文是offset location) 。需要注意的是,这里面的值,在第三步、和第四步的时候,都可能用得上,而不是仅仅用于第三步 。看到这个地方,可以发现,其实这个图有个问题,就是没有指出KeyCaches的维护 。Cache是可以在建表时配置的一个参数 。可以推测,假如我们建表的时候,keys的Cache采用了ALL的设置,那么应该是在有新的KEY值写入Memtables时,维护到了Key Caches中 。
第三步,这一步需要关注是,对于一个指定的表(或列族),是只会使用唯一的一个Memtable 的,那么这个搜索就是线性的 。Memtable中的内容,是还没有FLUSH到SSTables里的数据,在查询是,它里面的内容和SSTables中的内容,都是要同步读取的,但对单节点而言,它的内容通常更新 。
与写入场景大有不同的地方是,读数据的关键步骤,是第4步,读SSTables 。这里在后面的内容展开,看一下第五步,如果Row Caches还可用,把这条记录加入的Row Caches 。Row Caches放的是一整行的数据,如前面提到了,适合于存放热点读取的数据 。
所有的数据库,通常都是有四大常规操作,谓之“增删改查” 。介绍了写入、查询之后,这里简单的介绍一下Cassandra的删和改 。一句话简述之,Cassandra的删除都是修改,Cassandra的修改都是写入,所以Cassandra只有写入和查询 。Cassandra一直写入数据,岂不是会存储爆炸不成 。在这里,我们介绍三个新概念(相对传统数据库)-Tombstones,Timestamps,Compaction 。
Cassandra的删除都是修改,这个好理解,在很多业务数据库表里面,经常会为了保留痕迹,而做一个逻辑删除动作 。也就是修改某个标识,表示这条记录以及删除或作废,而并没有在数据库里真正的删除 。Cassandra在收到Delete命令时,并不会立刻去删除这行记录 。而是会给这行记录一个Tombstones,表示它被删除了 。
Cassandra的修改都是写入 。前面提到Cassandra速度快,快在不需要定位数据 。任何Update命令,在传统数据库上,都需要把这条记录读到内存里,并上锁 。而在Cassandra上,Update命令会变成一条INSERT语句,那岂不是在系统里重KEY了吗?这里便要依靠记录上的Timestamps 。
Cassandra的每次查询,都会把所有重的KEY读出来,但是永远会以最新的Timestamps为准 。这就解决了把所有的修改,都变成写入的问题 。但是,这么干有两大显而易见问题 。第一,数据会无限的膨胀,吃掉磁盘 。第二,数据膨胀会带来查询需要读出的重复数据增加,无限的膨胀则会无限的增加,读取性能就会受损 。
所以这里,就要介绍压缩(Compaction)的概念 。这里要特别的注意,这不是我们通常说的数据库压缩技术,那个通常用的Compress 。只是由于多个官方文档都把Compaction翻译成了压缩,我个人觉得它更应该翻译成数据的整理 。Compaction是在数据库后台异步做的,接着前面的内容,它的内容至少有比如把墓碑数据真实移除,把时间戳比较老的数据移除,重新整理SSTable的存储文件等 。这样来解决前面那两个问题 。这个动作在某种意义上来讲甚至有一点像DB2数据库的REORG动作 。不同的数据库表,可以在Keyspace级别选择不一样的CompactionStrategy 。它常翻译为压缩算法,我觉得翻译成整理策略更加合适 。我觉压缩算法,应该和Compress的那个概念一致 。毕竟,这个Compaction没有给数据文件里连续的值,用个RLE算法,或者建个字典什么的对吧 。介绍完了这些之后,让我们来直面数据库最大的瓶颈 。
只要一个数据库不是内存数据库,那它永远都要面对它最大的性能瓶颈,磁盘IO 。我们前面提到的诸多概念,比如Cache、列存储、索引等等,他们优化性能的本质都指向一处,减少磁盘IO 。前面讲读写部分时,都跳过了第4步 。而对于SSTable的读取,其实才是影响性能的关键步骤 。
推荐阅读
- Win10 WSL配置centos的运行环境
- 使用Python「秒开」100GB+数据
- MySql主从复制,从原理到实践
- 五险一金:知道这6条才算懂
- 30 分钟包你学会 AWK
- 民间借贷中,借条中的“今借”和“今借到”有何区别?
- Dart 语言基础入门篇
- 淘宝店铺怎么样才算开店成功 淘宝店怎么样才能开好
- SQL优化的几种方式
- 数据库架构举例说明
