对于写密集型应用,每天写入量巨大,数据增长量无法预估,且对性能和可靠性要求非常高,普通关系型数据库无法满足其需求。对于全文搜索和数据分析这类对查询性能要求极高的场景也是如此。为了进一步满足上面两类场景的需求,有了宽表存储和搜索引擎技术,本文将对他们的架构、原理、优缺点做介绍。
— 宽表存储 —
宽表存储最早来自Google的Bigtable论文,最初的定义为:A Bigtable is a sparse, distributed, persistent multidimensional sorted map. The map is indexed by a row key, column key, and a timestamp; each value in the map is an uninterpreted array of bytes.
《Bigtable: A distributed storage system for structured data》
Bigtable 会把数据存储在若干个 Table(表)中,Table 中的每个 Cell(数据单元)的形式如下:Cell 内的数据由字节串(string)构成,使用行、列和时间戳三个维度进行定位。
图片来源于《Bigtable: A distributed storage system for structured data》
Bigtable 在存储数据时会按照 Cell 的 Row Key 对 Table 进行字典排序,并且将一个 Table 按 Row 切分成若干个相邻的 Tablet,并将 Tablet 分配到不同的 Tablet Server 上存储。如此一来,客户端查询较为接近的 Row Key 时 Cell 落在同一个 Tablet 上的概率也会更大,查询的效率也会更高。
Table 中的不同 Cell 可以保存同一份数据的多个版本,以时间戳进行区分。时间戳本质上为 64 位整数,可由 Bigtable 自动设定为数据写入的当前时间(微秒),也可由应用自行设定,但应用需要自行确保 Cell 间不会出现冲突。对于拥有相同 Row Key 和 Column Key 的 Cell,Bigtable 会按照时间戳降序进行排序,如此一来最新的数据便会被首先读取。
由于Google Bigtable解决了海量数据场景下并发检索与查询、高速日志写入等核心业务场景需求,工业界受其启发开发了一些项目,如HBase、Cassandra等,并统称其为Wide Column Store(宽表存储,又称表格存储)。宽表存储可以无schema限制,表的字段可以自由扩展。一个数据表可以有无穷多的column,并且每行可以有不同的column,也允许每行有很多的空值,类似一个稀疏矩阵。一个列族(column family)存储经常被一起查询的相关数据。
当前DB-Engine中宽表NoSQL数据库的排名如下表,可以看到最受欢迎的主要是Cassandra、HBase和Azure上的Cosmos DB。接下来我们将介绍一下HBase的情况。
HBase是一个面向列的分布式NoSQL数据库,是Google Bigtable 框架的开源实现,能够响应随机、实时的数据检索需求。HBase主要的存储和处理对象是大宽表,存储模式可以兼容本地存储、HDFS和Amazon S3等Hadoop支持的文件系统,相比于RDBMS有很强的线性扩展能力。HBase通过采用基于LSM树的存储系统以保证稳定的数据写速率,同时利用其日志管理机制以及HDFS多副本机制确保数据库容错能力。通常的适用场景为:面向多版本、稀疏的、半结构化和结构化的数据高并发写入/查询的OLTP业务。
HBase的数据模型由不同的逻辑概念构成,包括:表、行、行键、列、列族、单元、时间戳。
- 表(Table):Table是HBase中数据的组织形式,是列的集合,和传统数据库中表的意义类似,同时也能够涵盖列数据在不同时间戳下的更新记录。
- 列(Column):是数据库中单独的数据项,每一个Column包含数据的一种类型。
- 列族(ColumnFamily):HBase中表的数据都是按照ColumnFamily分组,ColumnFamily是一个或多个HBase表中相近类型列的聚合。HBase将同一个ColumnFamily的数据放在一个文件中存储,可以起到类似于垂直分区的作用。查询时能减少不必要的扫描,增加查询速度。
- 行(Row):Row是RowKey和ColumnFamily的集合,一个Row中可以包括一个或多个ColumnFamily。
- 行键(RowKey):HBase中的行数据以RowKey形式进行排序,具有主键的作用,在查询时HBase可以通过RowKey定位数据,Region也是通过RowKey划分的。
- 时间戳(Timestamp):Timestamp是给定值的版本标识,和值同时写入HBase数据库。Timestamp可以是任何类型的时间格式,对于每个RowKey来说可以有多个时间版本的记录更新。
片来源于《HBase: The Definitive Guide》
在HBase中,表按照RowKey被切分为多个Regions存储。每个Region是HBase数据管理的基本单位,Region通过RowKey切分,具有类似水平范围分区的作用,数据得以分布于集群的各个节点,不同节点上的Region共同组合成表的整体逻辑视图,通过扩展Region可以提升容量。
片来源于《HBase: The Definitive Guide》Regions由HRegionServer维护,HRegionServer受到HMaster统一管理。HMaster可以自动调整HRegionServer中的Region数量,这样就实现了存储数据的无限扩展。
图片来源于《HBase: The Definitive Guide》
HBase的技术架构如上图,主要的组件或服务包括:Client:
- Client是整个HBase集群的访问入口,负责与HMaster通信,以进行集群管理类操作,或者与HRegionServer通信进行数据读写类操作。
- ZooKeeper:集群中每个节点的状态信息都会注册在ZooKeeper,HMaster通ZooKeeper感知每个HRegionServer的健康状态。另外HBase允许启动多个HMaster,ZooKeeper可保证集群中只有一个HMaser在运行。
- HMaster:负责管理对数据表的CRUD操作,管理HRegionServer的负载均衡,负责新Region的分配;在HRegionServer故障停机时负责失效HRegionServer上的Region迁移。
- HRegionServer:一个节点对应一个HRegionServer。负责接收HMaster分配的Region,负责与Client通信并处理其管理的所有Region相关读/写请求。
- HStore:HStore在HBase中负责数据存储功能,有1个MemStore和0个或更多的StoreFiles。数据先写入内存MemStore,刷写成StoreFile(File的封装),最后持久化到HDFS,当查询某一列的时候只需要调出HFDS相应的block即可。
- HLog:日志管理与回回放,每个进入MemStore的操作都会记录在HLog。
HBase采用LSM作为底层存储结构。LSM相对于RDBMS常采用的B+树有更好的写速率。由于磁盘随机IO的速率比顺序IO的速率慢指数级,所以数据库的存储设计都尽量避免磁盘随机IO。虽然B+树会将同一个节点尽量存储在一个分页上,但是这样只在相对较小数据量的情况有效,大量随机写时节点会趋于分裂,磁盘随机读写概率提升。为了保证写速率,LSM先写在内存,然后再顺序批量落入磁盘。顺序写设计使LSM相对于B+树有更好的海量数据写性能,但是读取的时候需要写合并内存数据和磁盘的历史数据,因此读性能有一定牺牲。但同时,LSM也可以通过将小集合并成大集合(合并),以及Bloom Filter等方式提高一定的读速。
图片来源于《HBase: The Definitive Guide》
HBase与存储相关的结构包括MemStore、HFile、WAL。MemStore是一个能够将数据的随机写转化为顺序写的内存存储结构,数据在写入时会先写入MemStore,直到内存存储容量无法继续存储数据时,再将数据存储转移在磁盘上。HFile便是HBase数据最终写到磁盘上的文件数据结构,即StoreFile的底层保存格式。在HBase中一个StoreFile对应着一个HFile,通常情况下HFile存储在HDFS之上的,因此能够保证数据完整性并提供分布式存储。WAL(Write-Ahead Log)负责提供高并发、持久化的日志存储和回放服务。HBase发生的所有业务操作都会存储在WAL中,以提供灾难恢复。例如MemStore内存数据写入HFlie持久化时如果机器断电,可以通过WAL回放,而数据不会丢失。
— 全文搜索引擎 —
关系数据库以行记录的方式存储有固定格式数据,与之不同的是,搜索引擎会将数据以文档的形式存储,在物理上会是层次化结构或者树形结构。这个做法的好处是非常容易增加半结构化或者结构化数据的处理能力。
目前搜索引擎比较有代表性的数据库有开源Elasticsearch,国内星环科技有自研的搜索产品Scope。在DB Engine的排名中,Elasticsearch常年排名在前十以内,相较于SQL数据库,ES提供了可扩展、近实时性的分布式搜索功能,支持将文本数据分割为多个部分交由集群节点进行存储和备份以提高检索速度并保证数据的完整性,支持自动化的负载均衡和应急处理以确保整个集群处于高可用状态。ES适用于各种对文档等非结构化数据有处理需求的业务,如智能分词、全文检索、相关度排名等。
ES定义了一套专有的存储和管理数据的要素和概念,最主要的为Field、Document、Type和Index。Field是Elasticsearch中最小的数据单位,与关系型数据库中的列相似,是一组具有相同数据类型的数据值的集合。Document类似于关系型数据中行的概念,一个Document包含每一个Field中与之相应的数据值。Type类似数据库中的表级别概念,而Index是Elasticsearch中最大的数据单位,与 SQL的索引不同,ES中index对应SQL中schema的概念。
在物理模型上,Elasticsearch主要的概念包括Cluster(集群)、Node(节点)和Shard(分片)。其中节点指的是一个Elasticsearch的实例或者说Java进程,如果硬件资源比较充足,是可以在一个节点上运行多个实例的。Shard是ES集群进行数据处理的最小单元,是Lucene索引的一个实例,每个Index由一个或多个节点上的Shard共同组成。Shard分为Primary Shard和Replica Shard,每一个Document都会存储在一个Primary Shard中,如果Primary Shard或所在节点发生故障时,Replica Shard可以转为主Shard以保证数据的高可用;而在检索数据时,查询命令可以在备份Shard中进行以减轻主Shard的压力,进而提高了查询性能。
当向Elasticsearch写入数据时,Elasticsearch根据文档标识符ID将文档分配到多个分片上,当查询数据时,Elasticsearch会查询所有的分片并汇总结果。为了避免查询时部分分片查询失败影响结果的准确性,Elasticsearch引入了路由功能。当数据写入时,通过路由将数据写入指定分片。当查询数据时,通过相同的路由指明在哪个分片将数据查出来。
凭借着底层Lucene倒排索引技术,Elasticsearch在查询和搜索文本、日志类数据方面表现非常突出,几乎超过所有关系型数据库和其他基于Lucene改造的产品(如Solr),因此被广泛应用在日志分析、情报分析、知识检索等领域中,尤其是基于Elastic Stack构建的多个行业解决方案。但是2020年Elastic改变了其license模式,限制云厂商直接托管销售Elasticsearch,业内尝试通过一些其他方式(如基于Elasticsearch 5.7版本开发的OpenSearch)来绕过相关的license限制。
不过ES也有几个非常明显的架构不足之处,限制了其进一步拓展应用场景,包括:
- 不支持事务功能仅能支持数据的最终一致性,因此不能用于关键数据的存储和使用
- 分析能力偏弱如复杂的聚合能力偏弱
- 各个分片之间的高可用采用主从复制,可能存在数据脑裂问题
- 单个Node的处理数据容量还有待提升
- ES的安全模块是商业化插件,大量的ES集群缺少合适的安全防护
正是有以上的架构不足之处,也给业内其他搜索引擎一些改进的方向,尤其是ES的安全性问题,目前在国内已经导致数起重大的数据安全泄露事件。星环科技在2017年开始研发ES的国产替代品,并于2019年发布了基于Lucene开发的分布式搜索引擎Scope,采用了全新基于Paxos协议的高可用架构、支持跨数据中心的部署模式、内置原生安全功能、支持单个服务器多个Node实例等方式,极大地提升了搜索引擎的稳定性、可靠性和性能,在国内已经落地多个大型生产集群,单个集群服务器数量超过500节点。
— 小结—
本文介绍了宽表存储和搜索引擎技术的架构、原理、优缺点(现在各项技术发展比较快,可能存在技术描述跟最新技术发展情况不太一致的情况)。那么有了基础的数据存储管理,下一步是通过整合计算,获得所需结果,面对大数据量,如何实现高吞吐、低延迟、高扩展、支持容错,是分布式计算技术的关键,下一篇起,我们将介绍以MapReduce和Spark为代表的分布式计算技术。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。