正如Apache Cassandra的名称是来自于著名的物洛伊女巫一样,在它身上确实存在着各种误解。和大多数误解一样,至少在一开始时它们确实是有那么一点道理的,但随着Cassandra不断地深化与改善,这些误解的内容已经不复存在了。在本文中,我将针对五个常见的疑惑作出解释,澄清人们的困惑。
误解:Cassandra就是一个嵌套的map
随着使用Cassandra的应用程序变得越来越复杂,以下观点正在逐渐变得清晰起来:与“任何东西都是一个数组缓冲”或者“任何东西都是一个字符串”这种设计方式相比,schema与数据类型会使大型应用的开发与维护更加简单,
现如今,理解Cassandra的数据模型的最好方式是将其想像为表与行的组合,并且与关系型数据相似的是,Cassandra的列也是强类型的,并且可以进行索引。
你也许还听到过其它这些说法:
- “Cassandra是一种列数据库。”列数据库会将某个列的全部数据一起保存在磁盘上,这种方式对于数据仓库的检索方式是比较适合的,但对于那些需要对特定的行进行快速访问的应用程序来说就不太适合了。
- “Cassandra是一种宽行数据库。”这种说法有一定的道理,因为Cassandra的存储引擎是由Bigtable所启发而设计的,而后者可以说是宽行数据库的祖先了。但宽行数据库的数据模型与存储引擎结合得太过紧密,虽然实现起来比较容易,但针对它进行开发就增加了困难,而且它还使许多优化方式变得不可行了。
我们之所以在开始的部分选择避开“表与行”这种方法,原因之一是因为Cassandra的表与你所熟的关系型数据库的表的确存在着某些微妙的差别。首先,主键的首个元素是分区键,在同一个分区中的所有行都会存储在同一台服务器上,而分区是分布在整个集群中的。
其次,Cassandra不支持关联查询与子查询,这是因为在分布式系统中跨越硬件进行关联查询的性能很差。Cassandra的做法是鼓励你采用去正规化(denormalization)的方式,从一个单独的表中获取你所需的数据,同时提供集合等工具以简化操作。
举例来说,考虑一下以下代码所表示的users表:
CREATE TABLE users ( user_id uuid PRIMARY KEY, name text, state text, birth_year int );
目前多数主流服务都会考虑到一个用户可以拥有多个email地址的情况。在关系型数据库中,我们必需建立一个多对一的关系,随后使用关联查询将地址与用户关联起来,如以下所示:
CREATE TABLE users_addresses ( user_id uuid REFERENCES users, email text ); SELECT * FROM users NATURAL JOIN users_addresses;
而在Cassandra中,我们会以去正规化的方式将所有email地址直接加入用户表中,使用一个set集合就可以完美地实现这一点:
ALTER TABLE users ADD email_addresses set<text>;
随后我们可以以如下方式为用户添加多个地址:
UPDATE users SET email_addresses = {‘jbe@gmail.com’, ‘jbe@datastax.com’} WHERE user_id = ‘73844cd1-c16e-11e2-8bbd-7cd1c3f676e3’
关于Cassandra数据模型的更多内容,包括自届满数据(self-expiring data)以及分布式计数器,请参考在线文档,
误解:Cassandra的读取速度较慢
Cassandra采用的日志结构存储引擎意味着它不会在硬盘中寻找更新,也不会造成固态硬盘的写入放大,而同时它的读取速度也很快。
以下图示是关于随机访问读取、随机访问及顺序扫描,以及混合读写情况下的吞吐数据,它们来自于多伦多大学的NoSQL性能指标分析结果:
来自Endpoint公司的性能指标检测对Cassandra、HBase与MongoDB进行了比较,也证实了以上结论的正确性。
Cassandra是怎样实现的呢?从一个较高的层次来看,Cassandra的存储引擎看起来与Bigtable很像,它们都使用了一些相同的术语。更新内容会添加到某个commitlog中,随后收集到某个“memtable”里,该表会最终将数据写入磁盘并进行索引,类似于一个“sstable”:
原生的日志结构存储系统确实会倾向于在读取时稍慢,而由于同样的原因,它们在写入时会比较快:因为新的数据不会替换每一行中的原始数据,而是在后台压缩后再进行合并。因此在最坏的情况下,为了获取某个“碎片化”的行中的每一列的值,你将不得不检查多个sstable。
为了达到更好的读取性能,Cassandra对此基本设计方式进行了一些改善:
- 压缩策略是以插件形式提供的。例如LeveledCompactionStrategy会通过更为激进的方式组合重叠的sstable,以实现对读取的优化。
- Cassandra以时间倒序对sstable进行检查,如果你要求Cassandra执行SELECT x, y FROM foo WHERE key = 42语句,当Cassandra找到x和y对应的某个最新写入的数据时,它就不会再去检查时间更早的sstable。同样的原则也可以应用在对某个范围内的扫描上,虽然稍有些麻烦,但并非不可能实现。
- 在必须要从多个sstable中进行读取的情况下,我们将会在读取时将去碎片化的结果重新写入,这样之后的读取操作就只需要访问一个单独的表了。
- 当某个分区被访问时,它的索引就会被缓存起来,因此只需(每个sstable)一次查找就可以访问分区中的所有行了。
- 存储引擎的元数据中会从堆中被剔除出去,这样就避免了垃圾回收带来的影响问题。
误解:Cassandra的运行很麻烦
比起在一台独立的机器上运行数据库,在一个分布式系统上运行会在以下三个方面遇到更多的困难:
- 初始化时的部署与配置
- 日常维护工作,例如升级、添加新节点、或者替换故障节点
- 故障检测
Cassandra是一个完整的分布式系统:因为Cassandra集群中的每一台机器都具有相同的角色,不存在专门的元数据服务器以调整内存中的各种信息,也不存在专门的配置服务器以进行分发,同样也不存在主服务器或者是故障转移服务器。这种特性使运行Cassandra从各方面而言都要比其它的一些替代产品来得更简单。这也意味着可以很方便地搭建一个单节点的集群以进行开发与测试任务,而它的功能表现与在一个包含大量节点的完整集群中的表现完全一样。
从某种意义上说,初始化时的部署工作其实是一项最不重要的任务,因为如果其它方面的表现相同,那么即使是初始化时的安装稍为复杂一些,随着系统生命周期的推移,这一点麻烦也不是很大的问题,并且自动化的安装工具能够为你隐藏大多数头疼的细节问题。但是!如果你因为对某个系统的了解太小而选择放弃手动安装,那么当你需要对某个问题进行故障诊断时就会遇到麻烦,因为解决问题需要你完全掌握系统中的各个部分是怎样在一起动作的。
因此我的建议是,如果你打算利用某些工具来进行安装,例如Windows MSI安装文件、Oracle的Ops Center Provisioning、或是自配置的AMI,请确保你已经深刻理解了安装过程中的细节。你可以研究一下这个搭建Cassandra集群的两分钟示例。
Cassandra的日常维护工作很简单。任一时刻都可以在某台节点上进行升级工作,而当某个节点停机时,其它节点会保留本应应用在该节点上的升级内容,并在该节点恢复后将升级内容重新发送给它。此外,添加新节点的操作可以在整个集群中并行进行,在操作完成后也无需重新进行平衡。
即使是对那些时间较长的、计划之外的停机状态进行处理也非常方便。Cassandra可在运行时进行修复,如同其它数据库中的rsync一样,它只需传输丢失的数据即可,这就将网络数据传输降至最低。如果你没有特别留意的话,也许根本不会意识到它的发生。
Cassandra在对多数据中心的支持方面在整个业界都处于领先地位,即使是整个AWS区域挂掉,甚至是整个数据中心在飓风中被摧毁这些极端情况下,也可以顺利地进行恢复。
最后,DataStax OpsCenter能够让你随时看到集群的各种重要系统指标,这样就可以方便地将历史活动数据与造成服务性能下降的事故相关联起来,以达到简化故障检测的目的。Cassandra的DataStax社区版本自带了一个“轻量级”版本的OpsCenter,可以在生产环境中免费使用。而DataStax企业版则包括了备份与恢复的调度,可配置的系统警告以及其它各种特性。
误解:在Cassandra上进行开发非常困难
早先的Cassandra Thrift API的目标是尽量减少用户开发一个跨平台的应用所付出的精力,而它也达到了这一目标,但现在业界已公认这套API是难以使用的。随后Cassandra推出了一套自己的SQL语言:CQL。它提供了一套更易于使用的接口,学习曲线更为平滑,同时还推出了一套异步协议,因此取代了Thrift API的使用。
CQL的早期使用者在两年前就可以使用0.8版本了,而今年1月份发布的1.2版本终于使CQL成为一个可用于生产环境的产品了。新版本包含了多种驱动程序,性能也比Thrift更好。DataStax也为最流行的各种CQL驱动程序提供了官方支持,从此就可以不必再依赖来自社区的Thrift驱动程序的支持了,有时这种支持真的很差。
除了在线文档中所介绍的CQL基础知识外,Patrick McFadin的演讲“Next Top Data Model”(第1部分、第2部分)也是一个很好的CQL介绍。
误解:Cassandra依然是一种无人问津的边缘产品
从开源的角度来说,Apache Cassandra已有5年的历史,并且已经发布了多个版本,最新的版本2.0还是在今年七月刚刚发布的。而从企业的角度来说,DataStax提供了DataStax企业版,其中包含了一个经过认证的Cassandra版本,该版本经过了特定的测试、性能指标衡量、并且得到认可在生产环境中进行使用。
各个商业机构都看到了Cassandra为他们的组织所带来的价值,财富榜上的百强内有20个机构都依赖于Cassandra为他们的关键应用程序提供服务,这些机构来自几乎每个行业,包括金融、医疗、零售、娱乐、在线广告与市场。
将应用迁移至Cassandra平台上的最常见原因之一,是现有技术的伸缩性已经不足以满足现代化大数据应用程序的需求了。全球最大的云应用Netflix已经将其95%的数据从Oracle迁移至Cassandra,而Barracuda Networks也用Cassandra取代了MySQL,因为MySQL已经不能够应对巨量的垃圾请求了。而Ooyala每天都要进行20亿次数据处理,它所使用的Cassandra已有超过两个PB的数据量了。
对于那些管理和维护成本过高的陈旧的关系型数据库,Cassandra也在逐步取而代之。Constant Contact的首个基于Cassandra的项目开发了三个月,成本为25万美元,而他们之前基于关系型数据库的方案则开发了九个月,花费了250万美元。如今,他们已经搭建了6个集群,共有超过100TB的数据存放于Cassandra中。
在DataStax的案例学习页面,以及Planet Cassandra的用户访问页面上还可以找到许多其它案例。
这一条并非误解:关于在旧金山举办的2013 Cassandra Summit大会
我们刚刚结束了本次会议,这可以说是学习更多Cassandra知识的最好机会了。本次会议有超过1100名与会者和65场演讲,主讲者分别来自Accenture、Barracuda Networks、Blue Mountain Capital、Comcast、Constant Contact、eBay、Fusion-io、Intuit、Netflix、Sony、Splunk、Spotify、Walmart和其它一些公司。演讲的幻灯片已上传,而演讲视频也即将开放下载,具体时间请密切关注Planet Cassandra的公告。
关于作者
Jonathan Ellis是DataStax公司的CTO兼联合创始人。在创办DataStax之前,他在受雇于Rackspace公司时在工作中大量使用了Apache Cassandra。而在Rackspace之前,他基于Reed-Solomon编码技术,为内容备份提供商Mozy编写了一个可容纳多个PB、伸缩性良好的存储系统。
查看英文原文:Cassandra Mythology