在大数据生态圈里,数据存储可分为两大类:一类是直接以文件形式存放在分布式文件系统上,处理工具可直接读写(Hive和Spark SQL);另一类通过NoSQL数据库来存储和管理数据。
一、批处理的数据存储无论为Hive还是Spark SQL,它们的数据库和数据表都是直接映射到HDFS的目录上,所有批处理的存储规划实际就是对HDFS存储空间的规划。批处理的主要工作内容是构建数据仓库。
1.1 CSV格式CSV是最为常见的文件格式,大多数数据库和数据采集工具都内置了对CSV格式的支持,使得CSV格式是一种非常理想的基于文件的数据交换方案。Hive字0.14版本就提供了读写CSV格式的Serde(序列化和反序列化类)。Hive可指定将CSV的文件作为数据表的存储文件。
1.2 JSON格式JSON也是使用频率极高的一类文件格式,与CSV格式相比,JSON格式最大的优势在于它是“自描述”的,它携带了格式信息。同时,JSON可以描述非关系型数据,这是JSON另一大优势。在Hive和Spark SQL下既有内置的JSON Serde,也有第三方的。
1.3 ORC格式纯文本格式的文件便于调试和排查错误,但是它们占用空间大,处理效率也不及二进制格式,因此在生成环境中,更多使用二进制格式来存储数据。ORC格式的优势主要有:
- 每个Task的输出会作为一个单独的文件,这会减少NameNode负荷;
- 支持Hive的很多数据类型,包括datetime、decimal,以及复合类型struct、list、map和union
- 在文件中集成轻量的索引时:跳过没有通过过滤条件的行、可以直接检索给定的行
- 基于数据类型的“块模式”压缩:对Interger类型的列提供字典编码、对String类型的列提供字典编码
- 使用单独的RecordReader并发读取同一个文件
- 无须扫描标记即可直接切分文件
- 在读写时限制使用总内存
- 使用Protocol Buffer存储元数据,允许添加或移除字段。
AVOR并不单单是一种文件格式,它实际上时一个完整的远程调用(RPC)框架,数据的序列化与反序列化是其整体方案的一部分,优势如下:
- 动态的类型化处理:AVOR格式并不强制要求针对传递的数据在Client端和Server端生成静态代码。
- 无标记的数据格式:AVOR格式将需要在读取数据时才使用Scheme信息,这样就不必再数据编码时加入过多的类型累心,会大大减小数据传输的体积,提升数据传输效率。
- 灵活的Schema变更支持:当数据的Schema发生变动时,AVOR格式允许新旧两种Schema并行。
Parquet格式区别于其他格式的最大特征时,它是一种面向列的存储格式,即它是按列来组织和存储数据的,一条记录会被拆分到多个列中存储。劣势存储至少在两个方面具有天然优势:
- 在面向列查询时,列式存储可极大地提高查询效率,典型的是OLAP维度计算,维度计算会聚焦于事实表某个维度列上的值进行过滤和聚合;
- 处理嵌套格式的数据,列式存储模型设计可很好地化解复杂的嵌套关系,使之在存储和检索某些非关系型数据上具有冷号的性能。
Hbase是一个分布式、可伸缩的NoSQL数据库,和所有其他的NoSQL产品相比,Hbase有一个非常显著的特点,就是它是构建在HDFS上的,它是Hadoop生态圈里的重要成员,与其他Hadoop成员(如HDFS、MR/Yarn)都有天然的集成。
2.2 CassandraCassandra是游离于Hadoop生态圈之外的一个优秀的NoSQL数据库,与Hbase的主从架构不同,它使用的世去中心化的无主架构。近几年,在大数据领域随着Spark的流行,一些新系统的架构对传统Hadoop生态圈的依赖程度有所下降,在NoSQL数据库的选择上,Cassandra变得比以前更流行。
Cassandra的无主架构使得它在维护较之Hbase更为简单,也更容易进行水平伸缩,这是很多团队选择Cassandra的原因之一。此外,Cassandra的多数据中心特性使得在同一个集群中构建面向不同用途的数据副本变得非常容易。
2.3 MongoDBMongoDB是使用C++语言编写的一个基本分布式文件存储的开源数据库系统,它是一个非常独立和完备的NoSQL系统,也支持多数据中心,能较为简单的进行扩容。此外,MongoDB也有内置的二级索引,并且提供非常友好的数据操作接口,这是Hbase和Cassandra如不MongoDB的地方
2.4 RedisRedis定位于内存数据库,在魂村数据和高并发场景有着广泛的应用。在大数据领域,Redis的一些典型应用场景有:配合Spark Streaming、Flink、Storm进行高速率、低延迟的实时数据处理,作为Cache缓存近期的原生数据或分析结果,为热数据读取提供支持。
三、Hbase与Cassandra结合项目需求和团队技术背景分析取舍:
- 简化技术堆栈:建立平台,要综合考虑平台的整体生态,特别是其他组件和应用对存储的需求。eg,建设平台需要一个时间序列数据库,选择OpenTSDB,或需要一个LOAP引擎,选择的是Kylin,这种情况下,建议选择Hbase。因为OpenTSDB和Kylin都会依赖Hbase,安装和维护一个Hbase集群是团队的必要工作了,从简化技术堆栈的角度考虑,延续对Hbase的使用比较明智,如再单独引入到另一个数据库产品,会增加平台的维护难度。
- 维护的便捷性:运维一个Hbase集群复杂,一方面它的架构比较复杂,另一方面它会周期性地进行Region的split和compaction,这对运维也提出了一定要求。此外,Cassandra使用的数据查询结构也比Hbase友好,在开发上层应用的时候更简单。
- 同时支撑批处理与实时访问:这是大数据平台的普遍需求,Lambda脚骨会针对两种场景做独立设计,然后将数据冗余存储两份,使用不同的技术堆栈,但这并不意味着在数据存储层面也必须使用不同技术,如批处理和实时组件都可方便高效地读写NoSQL数据库(如Spark Core、Spark SQL和Spark Streaming都可方便读写Cassandra),那完全可使用NoSQL数据库来统一数据存储,这是就会对NoSQL数据库提出要求,即需要一种透明的机制自动冗余数据并隔离硬件资源,使之相互不影响。对于Cassandra,它的“多数据中心”机制可完美满足需求,且实现容易。Hbase也有类似机制“Replication”,但Cassandra在这方面实现起来更加便捷,更易于维护。
- 平台的整体架构风格:一些新的大数据系统架构在视图摆脱对Hadoop的依赖,如SMACK架构就完全舍弃了Hadoop,因为Hbase总是要依赖HDFS的,所以在SMACK架构里,Cassandra是唯一的数据存储设施。
Hbase的记录是按Rowkey的字典顺序排列的,每个Region会等分Rowkey的一段区间,如Rowkey中包含了时间或某类持续递增的数值,则近期产生的数据将有可能被写入同一个Region上,这会导致某一个Region承担所有的写入负荷,而其他的Region则只能“静静地围观”,这就是“热点”问题。解决“热点”问题的关键是想办法让组成Rowkey的数值具有一定的离散型,而不是随时间连续递增。以下三种是常见的解决方案
(1)加盐
“加盐”是指在Rowkey前段追加一个随机值,是的Rowkey变得离散性。好处在于散列了分布,缺点是“加盐”之后将无法从记录自身直接推断出其Rowkey,所以在索引数据时,将不得不做全表扫描。
(2)哈希
哈希的思路是利用哈希算法的一个特性,即党原文仅有极微小的变化时会导致哈希值产生明显变化,这样原本连续的Rowkey经过哈希后,也将槟城完全离散。哈希的优势在于数据读取可追踪,即将要查询的原始Rowkey经过同样的哈希处理之后就可以准确地定位数据了。缺点是Rowkey经过哈希之后其组成部分的信息都将丢失,这使得Rowkey作为索引的价值大打折扣。
(3)反转
反转是一种有效而使用的技巧,它的思想是,对于那些单调递增的值,他们的高字节比较稳定,但是低字节却白你话比较迅速,如把这些值做反转处理,即将原来的低字节排到高字节的位置,高字节排到低字节文职,就可以有效地分散数据,同时保留了Rowkey的原始信息,便于数据的检索。
4.2 定长处理拼接到Rowkey的字段通常是不定长的,通常由几种常见处理方式:
- 使用统一的缩写或代码:这种方式简单易行,但不适合取值过多的字段,一方面不利于记忆,另一方面会出现代码冲突。
- 为每个子弹分配最大的字节长度,在最后一个字节指明实际长度:这种方式可很好得将原始字段信息保留在Rowkey中,同时能保持订场,但会使Rowkey的总长度迅速膨胀,Rowkey的生成和解析也变得复杂,如Rowkey结构不复杂可考虑这种方式
- 为字段和取值创建订场的UID,以UID作为Rowkey的组成部分:这是一个完全的解决方案,它的设计思路是是为每个需要出现在Rowkey中的字段值进行统一编码,得到一个定长的唯一ID(UID),将这些UID加入到Rowkey,如每一,则首先生成一个新的Uid,写入UID元数据表中,然后拼接Rowkey。在数据读取和检索时,也要先检查UID的元数据表,在得到对应的编码后再拼接Rowkey进行查询。



