HBase、MongoDB、cassandra比较

 前言

传统数据库遇到的问题,数据量很大的时候没法存储没有很好的备份机制数据达到必定数量开始缓慢,很大的话基本没法支撑;所以咱们须要探究更加合适的数据库来支撑咱们的业务。html

 

HBase

什么是HBase

Hbase(Hadoop Database)是创建在HDFS之上的分布式、面向列的NoSQL的数据库系统。node

 

HBase特色

优势linux

    1. 海量存储:适合存储PB级别的海量数据,采用廉价PC存储的状况下,能在几十到百毫秒内返回数据。
    2. 列式存储(半结构化或非结构化数据):即列族存储,对于数据结构字段不够肯定或杂乱无章很是难按一个概念去进行抽取的数据适合用。
    3. 极易扩展:一个是基于上层处理能力(RegionServer)的扩展,提高Hbsae服务更多Region的能力。一个是基于存储的扩展(HDFS),经过横向添加Datanode的机器,进行存储层扩容,提高Hbase的数据存储能力和提高后端存储的读写能力。
    4. 高并发:采用廉价PC,能得到高并发、低延迟、高性能的服务。
    5. 稀疏:列族中,能够指定任意多的列,列数据为空不会占用存储空间的,也提升了读性能
    6. 多版本号数据:依据Row key和Column key定位到的Value可以有随意数量的版本号值,版本号默认是单元格插入时的时间戳
    7. 适用于插入比查询操做更频繁的状况:好比,对于历史记录表和日志文件
    8. 数据类型单一:HBase中数据类型都是字符串
    9. 无模式:每一行都有一个能够排序的rowKey和任意多的大相径庭的列。

缺点git

    1. 单一RowKey固有的局限性决定了它不可能有效地支持多条件查询。
    2. 不适合于大范围扫描查询。
    3. 不直接支持 SQL 的语句查询。
    4. 仅支持行级(单行)事务(HBase的事务是行级事务,能够保证行级数据的原子性、一致性、隔离性以及持久性)。
    5. HBase的配置很是麻烦,最低的限度都须要包括Zookeeper ensemble、primary HMaster、secondary HMaster、RegionServers、active NameNode、standby NameNode、HDFS quorum journal manager及DataNodes。使用HBase需求大量的专业知识——甚至是最简单的监视。RegionServer存在单点故障,当它发生故障时,一个新的RegionServer必须被选举出,而在能够投入以前,必须从新完成write-ahead日志里的内容,即故障恢复较慢,WAL回放较慢。HBase的API很是笨拙而且具备太强的Java特点,非Java客户端只能委托给Thrit或者REST。

 

HBase的体系结构

 

 

值得参考的网址:http://www.javashuo.com/article/p-ynqtsygj-cn.html程序员

 

HBase使用场景

Hbase是一个经过廉价PC机器集群来存储海量数据的分布式数据库解决方案。它比较适合的场景归纳以下:github

    1. 是巨量大(百T、PB级别)
    2. 查询简单(基于rowkey或者rowkey范围查询)
    3. 不涉及到复杂的关联

有几个典型的场景特别适合使用Hbase来存储:spring

    1. 海量订单流水数据(长久保存)
    2. 交易记录
    3. 数据库历史数据

 

如何使用HBase

三种模式单机模式,伪分布式模式,分布式模式sql

通常生产环境用的是分布式模式,若是是学习的话,能够用单机模式和伪分布式模式。mongodb

 

安装zookeeper数据库

https://blog.csdn.net/weixin_41558061/article/details/80597174

全分布式模式的Hbase集群须要运行ZooKeeper实例,默认状况下HBase自身维护着一组默认的ZooKeeper实例,能够本身配置实例,这样Hbase会更加健壮

注意:使用默认的实例时,HBase将自动启动或中止ZooKeeper,当使用独立的ZooKeeper实例时,须要用户手动启动和中止ZooKeeper实例

 

安装Hadoop

hadoop分布式安装

 

安装HBase

http://www.javashuo.com/article/p-ngsgoyep-cw.html

 

    hbase_home/conf/hbase-site.xml文件中的configuration加入:    
 1 <property>  
 2   <name>hbase.rootdir</name>  
 3   <value>hdfs://hadoop0:9000/hbase</value>
 4 </property>
 5 <property>
 6   <name>hbase.cluster.distributed</name>
 7   <value>true</value>
 8 </property>
 9 <property>
10   <name>hbase.zookeeper.quorum</name>
11   <value>hadoop0</value>
12 </property>
13 <property>
14   <name>dfs.replication</name>   //指定Hlog和Hfile副本数,此参数值并不能大于HDFS节点数,若是datanode只有一台则此参数应该设置为1
15   <value>1</value>
16 </property>

 

注意事项

1.关于Hadoop

  1.  目前的HBase只能依赖特定的Hadoop版本,HBae和Hadoop之间的RPC是版本话的,须要调用方与被调用方相互匹配,细微的差别可能致使通讯失败

  2. 因为Hadoop依赖于Hadoop,它要求Hadoop的JAR必须部署在HBase的lib目录下。HBase使用的Hadoop版本必须与底层Hadoop集群上使用的Hadoop版本一直,于是使用Hadoop集群上运行的JAR替换HBase的lib目录中依赖的Hadoop的JAR能够避免版本不匹配的问题

  3. 集群中全部的节点都要更新为同样的JAR,不然版本不匹配问题可能形成集群没法启动或者假死现象

 

2.关于HBase Shell

  1.若是使用的分布式模式,那么在关闭Hadoop以前必定要确认HBase已经被正常关闭了

  2. 使用stop-hbase.sh关闭HBase时,控制台会打印关于中止的信息,会周期性的打印 ".",关闭脚本须要几分钟完成,若是集群中机器数量不少,那么执行时间会更长

介绍比较全面的网址:http://www.javashuo.com/article/p-paqmevof-dg.html

 

了解完HBase后,可带着问题看这一篇文章:https://blog.csdn.net/nosqlnotes/article/details/79647096 

 

MongoDB

什么是MongoDB

MongoDB是一个介于关系数据库和非关系数据库之间,基于分布式文件存储,由C 语言编写的数据库。

 

MongoDB特色

优势

高性能、易部署、易使用、高写负载,存储数据很是方便。

        • 面向文档存储(类JSON数据模式简单而强大)
        • 动态查询

        • 全索引支持,扩展到内部对象和内嵌数组

        • 查询记录分析

        • 快速,就地更新

        • 高效存储二进制大对象 (好比照片和视频)

        • 复制和故障切换支持

        • Auto- Sharding自动分片支持云级扩展性

        • 支持RUBY,PYTHON,JAVA,C ,PHP,C#等多种语言。
        • MapReduce 支持复杂聚合

        • 商业支持,培训和咨询

 缺点

        • 不支持事务(进行开发时须要注意,哪些功能须要使用数据库提供的事务支持)
        • MongoDB占用空间过大 (不过这个肯定对于目前快速下跌的硬盘价格来讲,也不算什么缺点了)
          • 2.一、空间的预分配:
            当MongoDB的空间不足时它就会申请生成一大块硬盘空间,并且申请的量都是有64M、128M、256M来增长直到2G为单个文件的较大致积,而且随着数量叠增,能够在数据目录下看到整块生成并且不断递增的文件。

          • 2.二、删除记录不释放空间:

            这很容易理解,为避免记录删除后的数据的大规模挪动,原记录空间不删除,只标记“已删除”便可,之后还能够重复利用。

        • MongoDB没有如MySQL那样成熟的维护工具,这对于开发和IT运营都是个值得注意的地方
        • 在32位系统上,不支持大于2.5G的数据(不少操做系统都已经抛弃了32位版本,因此这个也算不上什么缺点了,3.4版本已经放弃支持32 位 x86平台)

 

MongoDB原理

mongodb在电脑磁盘文件系统之上,又包装了本身的一套文件系统---gridfs,里面存储的是一个一个的json二进制对象,也就是Bson。

存储容量需求超出单机磁盘容量时,用分片技术去解决

  详情可参考网址:

http://www.javashuo.com/article/p-rmmcgnlx-ds.html

http://www.javashuo.com/article/p-shvescuy-ho.html

 

场景适用

适用场景

        MongoDB 的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS 系统(具备丰富的功能)之间架起一座桥梁,它集二者的优点于一身。根据官方网站的描述,Mongo 适用于如下场景。
● 网站数据:Mongo 很是适合实时的插入,更新与查询,并具有网站实时数据存储所需的复制及高度伸缩性。
● 缓存:因为性能很高,Mongo 也适合做为信息基础设施的缓存层。在系统重启以后,由Mongo 搭建的持久化缓存层能够避免下层的数据源过载。
● 大尺寸、低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此以前,不少时候程序员每每会选择传统的文件进行存储。
● 高伸缩性的场景:Mongo 很是适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持。
● 用于对象及JSON 数据的存储:Mongo 的BSON 数据格式很是适合文档化格式的存储及查询。

不适场景

● 高度事务性的系统:例如,银行或会计系统。传统的关系型数据库目前仍是更适用于须要大量原子性复琐事务的应用程序。
● 传统的商业智能应用:针对特定问题的BI 数据库会产生高度优化的查询方式。对于此类应用,数据仓库多是更合适的选择。
● 须要SQL 的问题。

 

如何使用MongoDB

linux平台安装MongoDB

http://www.runoob.com/mongodb/mongodb-linux-install.html

spring中集成MongoDB,经过引入MongoDB的maven依赖,引入约束mongo来配置spring托管

xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation=" 
    http://www.springframework.org/schema/data/mongo
    http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd"

 

  配置链接池

<!--链接池配置-->
<mongo:mongo host="${mongo.host}" port="${mongo.port}">
    <mongo:options connections-per-host="${mongo.options.connections-per-host}"
                   threads-allowed-to-block-for-connection-multiplier="${mongo.options.threads-allowed-to-block-for-connection-multiplier}"
                   connect-timeout="${mongo.options.connect-timeout}"
                   max-wait-time="${mongo.options.max-wait-time}"
                   auto-connect-retry="${mongo.options.auto-connect-retry}"
                   socket-keep-alive="${mongo.options.socket-keep-alive}"
                   socket-timeout="${mongo.options.socket-timeout}"
                   slave-ok="${mongo.options.slave-ok}"
                   write-number="${mongo.options.write-number}"
                   write-timeout="${mongo.options.write-timeout}"
                   write-fsync="${mongo.options.write-fsync}"/>
</mongo:mongo>
<!--链接池工厂配置-->
<mongo:db-factory dbname="${mongo.dbname}" username="${mongo.username}" password="${mongo.password}"  mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
<!--实体映射自动扫描注入的包-->
<mongo:mapping-converter>
    <mongo:custom-converters base-package="com.xyh.mongodb_model" />
</mongo:mapping-converter>

 

在实体类中加入相应的@Document、@id、@Indexed、@PersistenceConstructor注解,来实现对数据实例化对象进行增删改查的操做。

详细信息可参考网址:http://www.javashuo.com/article/p-yapknazt-bc.html

 

Cassandra

什么是Cassandra

Cassandra是数据放置在具备多个复制因子的不一样机器上,处理大量数据的分布式架构的非关系数据库。

 

Cassandra特色

优势

               配置简单

        不须要多模块协同操做。

模式灵活
  使用Cassandra,像文档存储,你没必要提早解决记录中的字段。你能够在系统运行时随意的添加或移除字段。这是一个惊人的效率提高,特别是在大型部署上。

真正的可扩展性
  Cassandra是纯粹意义上的水平扩展。为给集群添加更多容量,能够指向另外一台电脑。你没必要重启任何进程,改变应用查询,或手动迁移任何数据。

多数据中心识别
  你能够调整你的节点布局来避免某一个数据中心起火,一个备用的数据中心将至少有每条记录的彻底复制。

范围查询
  若是你不喜欢所有的键值查询,则能够设置键的范围来查询。


列表数据结构
  在混合模式能够将超级列添加到5维。对于每一个用户的索引,这是很是方便的。


分布式写操做
  有能够在任何地方任什么时候间集中读或写任何数据。而且不会有任何单点失败。 

缺点
存储那种巨大的(几百T甚至P)的超大文件目前是无能为力的。
 

原理

在Cassandra中,是无中心的P2P架构,网络中的全部节点都是对等的,它们构成了一个环,节点之间经过P2P协议每秒钟交换一次数据,这样每一个节点都拥有其它全部节点的信息,包括位置、状态等,以免单点故障。

写请求

当写事件发生时,首先由Commit Log捕获写事件并持久化;每一个数据中心选取一个Coordinator来完成它所在数据中心的数据复制;存储结构相似LSM树(Log-Structured Merge Tree)这种结构;Commit Log记录每次写请求的完整信息,此时并不会根据主键进行排序,而是顺序写入;写入到Memtable时,Cassandra可以动态地为它分配内存空间;当memtable中的数据刷到SSTable后,Commit Log中的数据将被清理掉;Cassandra对Update操做的处理和传统关系数据库彻底不同,并不当即对原有数据进行更新,而是会增长一条新的记录,后续在进行Compaction时将数据再进行合并。Delete操做也一样如此,要删除的数据会先标记为Tombstone,后续进行Compaction时再真正永久删除。

 图来源网址:https://www.yiibai.com/cassandra/cassandra-architecture.html

读请求

读取数据时,首先检查Bloom filter,每个SSTable都有一个Bloom filter用来检查partition key是否在这个SSTable,这一步是在访问任何磁盘IO的前面就会作掉。若是存在,再检查partition key cache。读请求(Read Request)分两种,一种是Rirect Read Request,根据客户端配置的Consistency Level读取到数据便可返回客户端结果。一种是Background Read Repair Request,除了直接请求到达的节点外,会被发送到其它复制节点,用于修复以前写入有问题的节点,保证数据最终一致性。

行缓存和键缓存请求流程图

图来源网址:http://www.javashuo.com/article/p-ymhcqiej-ms.html

可参考网址:http://www.javashuo.com/article/p-qfyvgfjz-en.html

 

如何使用Cassandra

Cassandra集群搭建

https://github.com/maomao1994/TPC-H/blob/master/Cassandra-CQL/Cassandra-CQL%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA.md

https://blog.csdn.net/ch648966459/article/details/51671276/#commentBox

 

代码应用

引入pom.xml

<dependency>
 <groupId>com.datastax.cassandra</groupId>
 <artifactId>cassandra-driver-core</artifactId>
 <version>3.1.1</version>
</dependency> 
<dependency> 
 <groupId>com.datastax.cassandra</groupId>
 <artifactId>cassandra-driver-extras</artifactId>
 <version>3.1.1</version>
</dependency>

 

链接代码

        String[] hosts = new String[]{"192.168.1.1", "192.168.1.2", "192.168.1.3"};//cassandra主机地址
 
        //认证配置
        AuthProvider authProvider = new PlainTextAuthProvider("ershixiong", "123456");
 
 
        LoadBalancingPolicy lbp = new TokenAwarePolicy(
                DCAwareRoundRobinPolicy.builder().withLocalDc("myDC").build()
        );
 
        //读超时或链接超时设置
        SocketOptions so = new SocketOptions().setReadTimeoutMillis(3000).setConnectTimeoutMillis(3000);
 
        //链接池配置
        //PoolingOptions poolingOptions = new PoolingOptions().setConnectionsPerHost(HostDistance.LOCAL, 2, 3);
        //集群在同一个机房用HostDistance.LOCAL   不一样的机房用HostDistance.REMOTE   忽略用HostDistance.IGNORED
        PoolingOptions poolingOptions= new PoolingOptions()
                .setMaxRequestsPerConnection(HostDistance.LOCAL, 64)//每一个链接最多容许64个并发请求
                .setCoreConnectionsPerHost(HostDistance.LOCAL, 2)//和集群里的每一个机器都至少有2个链接
                .setMaxConnectionsPerHost(HostDistance.LOCAL, 6);//和集群里的每一个机器都最多有6个链接
 
        //查询配置
        //设置一致性级别ANY(0),ONE(1),TWO(2),THREE(3),QUORUM(4),ALL(5),LOCAL_QUORUM(6),EACH_QUORUM(7),SERIAL(8),LOCAL_SERIAL(9),LOCAL_ONE(10);
        //能够在每次生成查询statement的时候设置,也能够像这样全局设置
        QueryOptions queryOptions = new QueryOptions().setConsistencyLevel(ConsistencyLevel.ONE);
 
        //重试策略
        RetryPolicy retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE;
 
        int port = 9042;//端口号
 
        String keyspace = "keyspacename";//要链接的库,能够不写
 
        Cluster cluster = Cluster.builder()
                .addContactPoints(hosts)
                .withAuthProvider(authProvider)
                .withLoadBalancingPolicy(lbp)
                .withSocketOptions(so)
                .withPoolingOptions(poolingOptions)
                .withQueryOptions(queryOptions)
                .withRetryPolicy(retryPolicy)
                .withPort(port)
                .build();
        Session session = cluster.connect(keyspace);

 

具体可参考:https://blog.csdn.net/u010003835/article/details/52516571

scylla、hazelcast你们也能够私下研究一下。 

结论

当你仅仅是存储海量增加的消息数据,存储海量增加的图片,小视频的时候,你要求数据不能丢失,你要求人工维护尽量少,你要求能迅速经过添加机器扩充存储,那么毫无疑问,Cassandra如今是占据上风的。

可是若是你但愿构建一个超大规模的搜索引擎,产生超大规模的倒排索引文件(固然是逻辑上的文件,真实文件实际上被切分存储于不一样的节点上),那么目前HDFS+HBase是你的首选。

相关文章
相关标签/搜索