浅谈hbase和cassandra

Posted 73号弓箭手

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈hbase和cassandra相关的知识,希望对你有一定的参考价值。

一:简介

关于hbase和cassandra的探讨,主要从多个方面来说,从最基本的一步步往深入的说,从最基本的部署运维,到支持特性,使用功能以及各自的优势;

先从比较宏观的角度分析,HBase是基于Google的bigtable的论文实现的列式数据库,cap理论中更倾向于强调c(副本数据一致性)和p(分区容错性)。而Cassandra是号称dynamo 加上 bigtable(数据模型)的实现,cap中强调a(可用性) 和 p。而且底层都是使用lsm-tree 来做存储引擎的核心数据结构;

HBase基本上就是bigtable的开源实现,对标的bigtable的chubby(分布式锁服务)HBase有对应的zookeeper,HBase用regionserver管理region里的数据,实际上的数据副本容错的机制是交付给底层的分布式文件系统hdfs,类比bigtable的gfs,HBase有hmaster做元信息管理。Cassandra在架构上更多借鉴了dynamo,一种完全的区中心对等的分布式数据库,她的每个节点维护一份元信息,每一个节点在集群中的身份完全一样。

HBase

HBase保证写入的一致性。当一份数据被要求复制N份的时候,只有N份数据都被真正复制到N台服务器上之后,客户端才会成功返回。如果在复制过程中出现失败,所有的复制都将失败。连接上任何一台服务器的客户端都无法看到被复制的数据。HBase提供行锁,但是不提供多行锁和事务。HBase基于HDFS,因此数据的多份复制功能和可靠性将由HDFS提供。HBase和MapReduce天然集成。

Cassandra

写入的时候,有多种模式可以选择。当一份数据模式被要求复制N份的时候,可以立即返回,可以成功复制到一个服务器之后返回,可以等到全部复制到N份服务器之后返回,还可以设定一个复制到quorum份服务器之后返回。Quorum后面会有具体解释。复制不会失败。最终所有节点数据都将被写入。而在未被完全写入的时间间隙,连接到不同服务器的客户端有可能读到不同的数据。在集群里面,所有的服务器都是等价的。不存在任何一个单点故障。节点和节点之间通过Gossip协议互相通信。写入顺序按照timestamp排序,不提供行锁。新版本的Cassandra已经集成了MapReduce了。

相对于配置Cassandra,配置HBase是一个艰辛、复杂充满陷阱的工作。Facebook关于为何采取HBase,里面有一句,大意是,Facebook长期以来一直关注HBase的开发并且有一只专门的经验丰富的HBase维护的team来负责HBase的安装和维护。可以想象,Facebook内部关于使用HBase和Cassandra有过激烈的斗争,最终人数更多的HBase team占据了上风。对于大公司来说,养一只相对庞大的类似DBA的team来维护HBase不算什么大的开销,但是对于小公司,这实在不是一个可以负担的起的开销。

另外HBase在高可靠性上有一个很大的缺陷,就是HBase依赖HDFS。HDFS是Google File System的复制品,NameNode是HDFS的单点故障点。而到目前为止,HDFS还没有加入NameNode的自我恢复功能。不过我相信,Facebook在内部一定有恢复NameNode的手段,只是没有开源出来而已。

相反,Cassandra的P2P和去中心化设计,没有可能出现单点故障。从设计上来看,Cassandra比HBase更加可靠。关于数据一致性,实际上,Cassandra也可以以牺牲响应时间的代价来获得和HBase一样的一致性。而且,通过对Quorum的合适的设置,可以在响应时间和数据一致性得到一个很好的折衷值。

二:部署运维

单纯的就部署和运维hbase以及Cassandra来说,部署hbase前,需要部署的组件有zookeeper,hdfs,然后才是hbase。对应的Cassandra就比较简单很多,编译完成一个jar包,单台服务器启动一个Cassandra进程即可。

在部署hbase的时候,可能需要规划好,哪些机器跑hmaser,rs,zk,hdfs的相关进程等, 还有可能为了集群的性能,还要预先规划好多少个rs。自己人工去部署这么一个hbase集群还是比较麻烦的,更别提自己维护(阿里云ApsaraDB-HBase你值得拥有)。

Cassandra部署的时候比较简单,一个tar包搞定,由于cassandra数据落本地盘,需要人为的配置一些参数比如是否需要虚拟节点(vnode)以及多少vnode;需要基于业务的场景选择特定的key的放置策略(partitioner),这个放置策略的选择以及一些参数的配置需要一定的门槛。

简单总结下:部署运维的话,hbase依赖组件多,部署麻烦一点,但是相关资料很多,降低了难度;cassandra部署依赖少,但是配置参数多,相关资料较少。

特别是使用云HBase完全避免了部署造成的各种麻烦,比手工部署运维任何大数据数据库都方便太多。

三.特性对比



Cassandra HBase
一致性 Quorum NRW策略

通过Gossip协议同步Merkle Tree,维护集群节点间的数据一致性

单节点,无复制,强一致性
可用性 1,基于Consistent Hash相邻节点复制数据,数据存在于多个节点,无单点故障。

2,某节点宕机,hash到该节点的新数据自动路由到下一节点做 hinted handoff,源节点恢复后,推送回源节点。

3,通过Gossip协议维护集群所有节点的健康状态,并发送同步请求,维护数据一致性。

4,SSTable,纯文件,单机可靠性一般。

1,存在单点故障,Region Server宕机后,短时间内该server维护的region无法访问,等待failover生效。

2,通过Master维护各Region Server健康状况和Region分布。

3,多个Master,Master宕机有zookeeper的paxos投票机制选取下一任Master。Master就算全宕机,也不影响Region读写。Master仅充当一个自动运维角色。

4,HDFS为分布式存储引擎,一备三,高可靠,0数据丢失。

5,HDFS的namenode是一个SPOF。

伸缩性 1,Consistent Hash,快速定位数据所在节点。

2,扩容需在Hash Ring上多个节点间调整数据分布。

1,通过Zookeeper定位目标Region Server,最后定位Region。

2,Region Server扩容,通过将自身发布到Master,Master均匀分布。

负载均

请求Zookeeper取得整个集群地址,然后根据Consistent Hash选择合适的节点。client会缓存集群地址。 请求Zookeeper取读写数据路由表定位Region Server,Master会修改这个路由表。Client自身也会缓存一部分路由信息。
数据差异比较算法 Merkle Tree , Bloom Filter Bloom Filter
锁与事务 Client Timestap(Dynamo使用vector lock) Optimistic Concurrency Control
读写性能 数据读写定位非常快。 数据读写定位可能要通过最多6次的网络RPC,性能较低。
CAP点评 1,弱一致性,数据可能丢失。

2,可用性高。

3,扩容方便。

1,强一致性,0数据丢失。

2,可用性低。

3,扩容方便。


3.1.特性概述

HBase的社区文章里面有介绍hbase的特性点,翻译过来有如下的几个点:

1.强一致性的读写:HBase不是一个最终一致性的存储。2.自动sharding:HBase的table在集群种被分布在各个region,region可以做自动切分。3.regionserver的failover;4.Hadoop/HDFS的集成;5.MapReduce:支持大数据的并行处理;6.JAVA Client 以及Thrift/RESR API 访问;7.Block Cache 以及Bloom filter;8.操作管理。

就上述HBase的特性,C*也有相应的自己的特性:

1.C*借鉴Dynamo的架构思想,把自己叫做一个最终一致性的系统,但是从[这篇文章](http://www.allthingsdistributed.com/2008/12/eventually_consistent.html)可以看出,如果使用至少是QUORUM 读写,还算是一个强一致的系统。 2.C*的sharding方式:一致性hash,有2种:(1)人为配置好initial_token;2.使用vnode,集群初始化以及节点bootstrap的时候会计算token,基于这些token做数据sharding。 3.可以容忍:replicator_number - (read/write level sufficient nodes)个节点挂了,比如3个副本,读写级别QUORUM(sufficient nodes是2),能容忍1节点挂; 4.支持MapReduce; 5.Thrift、CQL访问; 6.大数据处理的bloom filter 必备; 7.自己有jmx等常见管理,且datastax 公司有提供ops center;

从上述特性来看,各个数据库各有千秋,但是有各自的适合场景,如果业务对数据一致性要求比较苛刻,那么HBase可能更合适,毕竟C 还是存在一定的问题,比如删除数据可能复现;C推荐放置策略用Random以及Murmur3等方式,这样把key打散的很随机,以此做节点负载均衡,这样做scan业务自己的需求数据,可能数据库要全集群都访问,当然可以使用OrderPreserving 和 ByteOrdered可以不用全集群都访问,可是负载不是很均匀,HBase这点却支持的不错;就易用性来说,Cassandra做的还是不错的,在数据库内部提供cql,一种类sql的语句。HBase还是主要JAVA API/Thrift的接口支持,但是后续HBase这方面应该会提高,前段时间的HBase 2017 Asia 阿里也介绍了sql on HBase。

后续在易用性这一块HBase应该是越来越好,会弥补上在易用性这一块的欠缺。试想下,如果Nosql都支持大部分的SQL的功能和语法,那是多完美的事情。

3.2.特性对比

本小结就 HBase 和 C*在部分相关特性上进行细一步的分析对比,大概对比的部分选择为:一致性;sharding方式;用户使用方式;数据复制;

3.2.1 一致性:

一般的一致性在这里是指副本数据的一致性,我们常用的是3副本用来做冗余。HBase的话主要是依赖底层的HDFS来支持副本冗余,一次写入被regionserver收到以后,发送给底层的HDFS,而HDFS会对应的给这个数据在整个文件系统里面写多份;这里是多份副本全部写完成才会返回。读数据的话,在底层HDFS的处理是读主要的这份数据就可以,因为多份数据都是一样的(正常情况)。

C在建表的时候会指定表的副本数(常见3副本),一次数据写入,会基于当前表的副本数以及节点的snitch策略来找到需要写的数据节点,发出多份请求(3份),然后基于传递的写入级别等待对应的响应数即可,比如A,B,C三个副本,QUORUM级别写入,可能存在的情况是,A,B成功C写入失败(无论是网络还是节点跪了),那么这个时候3个副本实际上是不一致的。但是这里对于 C 来说,她能忍。而且如果你读的级别是QUORUM可以读到最新的数据,但是如果你用ONE级别去读数据,那么存在读到老数据的风险,但是C 存在这种情况(当然这里先不考虑C 内部的机制自己修回副本数据)。

C *由于不能保证副本一致性,自己提出了几种方式来做弥补:1.读修复;2.Hinted-Handoff;3.Anti-entropy repair ;但是各种机制的引入也不是很完美的解决问题,此外还相应的会引入一些问题,比如使用1的话,那些读不到的数据存在一直数据不一致的风险;使用3的方式去进行全量/增量数据对比,会消耗很多物理资源,影响在线服务的请求,这是在线服务不能忍受的。

这种情况下来看,HBase的读写以及数据一致性模型是比较简单的。简单就是美,这对具体的业务场景进行适配也是很nice的一面,如果一个数据库的模型过于复杂,业务方拿来用也需要很高的门槛。

2.2.2 shadring 方式:

HBase 的各个regionserver 在最初负责的region,是可以在最初的建表时候,可以做预分配,也可以让hbase自己做这件事情,那么每个regionserver就会负责相应的region的数据的读写等。对于出现热点region的情况的话,hbase自己支持region的split操作,将热点region一分为二。

C* 不支持所谓的热点数据spli region的功能,那么对于这种情况的话,她做了一个预先设置,输入的数据做hash打散,也就是我们知道的一致性hash,她内部支持4种hash策略,Murmur3,Random,OrderPreserving等,其中,前2种是做了随机的hash,OrderPreserving 是类似字典序的方式,最初无论是使用vnode的方式还是initial_tokne的方式人为设置节点token,来一个请求,计算随机hash可以把key比较随机打散到集群中的某个节点,通过snitch 和 keyspace 副本方式找到落得节点信息,因为前面的随机hash可以人为是比较随机的,那么这实际上可以理解为一种负载均衡。但是如果是OrderPreserving 这种方式,实际上就会有问题;出现热点也没办法;

而且我们知道随机hash如果要做scan,实际上是很蛋疼的,基本上所有节点都要操作。字典序可以避免操作所有的数据节点,从这点看,HBase还是占点优势。

2.2.3 用户使用方式

HBase现在提供给用户主要是JAVA/THrift/REST的接口,大概的操作也就是CRUD操作;这些使用还是不是具有亲和性。比如我现在要往表“table”里面写一条数据,rowkey是“test” 列是“cn1” "cn2",value是“value1”, "value2"那么我需要进行下面的操作:

    Configuration conf = HBaseConfiguration.create();    HTable htable = new HTable( conf, "table");    Put put = new Put(Bytes.toBytes("test"));    put.add(Bytes.toBytes("cn1"), Bytes.toBytes("qual1"),        Bytes.toBytes("value1"));    put.add(Bytes.toBytes("cn2"), Bytes.toBytes("qua2"),        Bytes.toBytes("value2"));    table.put(put);

但是对于C 而言,支持2种方式,1.THrift;2.CQL;thrift我们就不讨论了,主要介绍CQL,这是一种类sql的语言,主要用于操作C,那么通样写一条数据cql是:

INSERT INTO xxx.table (cn1, cn2) VALUES (value1, value2);

此外C* 支持多种索引,特别是有一种新的索引,sasi index支持prefix,contains等操作;

不过HBase也有支持sql的组件且也在往这边发展也不是太大问题;

2.2.4 数据复制

一般数据复制,有全量数据复制和增量数据复制2个情况,主要是为了集群的高可用做铺垫,全量复制的时候,有的使用copytble的方式,这边比较简单,但是因为是mr做批量读取写入(我们之前就是用这种方式导Cassandra的数据),但是会比较耗时,因为每次请求一个网络来回;也有基于snapshot做复制的方式,这种方式会好点;增量复制的话,使用的是复制Hlog的方式,这是一种异步的复制方式,在zk记录checkpoint,复制完log以后修改checkpoint的问位置。

C 的数据复制,也与2种方案,但是都是需要时在Network的拓扑配置下,同cluster的不同dc环境下的操作,全量复制是一种叫做rebuild的方式,直接拖数据的stream,类似C 做节点启动bootstrap的过程,C* 的增量复制 提供了2种方式:EACH_QUORUM,LOCAL_QUORUM 前者是同步写主备,后者是写本地,返回client,远端是否成功不care;对于这个而言的话,异步存在丢数据的风险,同步在跨region以及并发量大的情况下,请求失败率会很高。但是,上面的方式是需要部署在同clsuter下面的不同dc,不同cluster没有解决方案。此外对于同步和异步方案之间没有一种折中的方式,毕竟有的场景对性能要求高,同步复制影响线上写成功的概率,异步复制会丢数据。但是阿里HBase在这方面去做了一个同步异步并存的方式,同步异步共存复制。

四.各自优势

通过上述 的描述以及各自的功能特性的对比,我们可以得到HBase 和 C 对比,2种产品各有千秋,其中HBase对数据一致性要求更高,C相应的强调可用性。且现阶段C 的接口比较有亲和性,但是HBase 和 Hadoop系统天然的无缝对接,这是C 还有点欠缺的。C *也使用了各自方式去弥补欠缺,但是实际上数据一致性上做的还是和这种强一致的系统差把火,而HBase在可用性上所做的工作实际上个人觉得可以做的更好,亲和性以及易用性这些事情实际上HBase也在做工作。



-End-



如果觉得不错,那就分享给更多的小伙伴吧!!下方点赞留言▼▼▼



以上是关于浅谈hbase和cassandra的主要内容,如果未能解决你的问题,请参考以下文章

技术热点Cassandra与HBase的大数据对决 谁是胜者?

HBase 与 Cassandra 架构对比分析的经验分享

如何从 cassandra 或 hbase 中提取 leveldb 类型的数据存储(sstable + memtable)?

Cassandra 与 Hbase 的实时数据对比

大规模数据处理 Hbase vs Cassandra [关闭]

cassandra,hbase,kafka,elasticsearch redis 对比总结