SparkES 多维分析引擎设计

本文探讨了Elasticsearch在全文检索及高效列式存储方面的优势,并指出了其在SQL支持、水平扩展等方面存在的不足。介绍了如何利用Spark的计算能力与Elasticsearch形成互补,特别是在构建即席多维查询系统时的解决方案。

设计动机

ElasticSearch 毫秒级的查询响应时间还是很惊艳的。其优点有:

  1. 优秀的全文检索能力
  2. 高效的列式存储与查询能力
  3. 数据分布式存储(Shard 分片)

其列式存储可以有效的支持高效的聚合类查询,譬如groupBy等操作,分布式存储则提升了处理的数据规模。

相应的也存在一些缺点:

  1. 缺乏优秀的SQL支持
  2. 缺乏水平扩展的Reduce(Merge)能力,现阶段的实现局限在单机
  3. JSON格式的查询语言,缺乏编程能力,难以实现非常复杂的数据加工,自定义函数(类似Hive的UDF等)

Spark 作为一个计算引擎,可以克服ES存在的这些缺点:

  1. 良好的SQL支持
  2. 强大的计算引擎,可以进行分布式Reduce
  3. 支持自定义编程(采用原生API或者编写UDF等函数对SQL做增强)

所以在构建即席多维查询系统时,Spark 可以和ES取得良好的互补效果。通过ES的列式存储特性,我们可以非常快的过滤出数据,
并且支持全文检索,之后这些过滤后的数据从各个Shard 进入Spark,Spark分布式的进行Reduce/Merge操作,并且做一些更高层的工作,最后输出给用户。

通常而言,结构化的数据结构可以有效提升数据的查询速度,但是会对数据的构建产生一定的吞吐影响。ES强大的Query能力取决于数据结构化的存储(索引文件),为了解决这个问题,我们可以通过Spark Streaming
有效的对接各个数据源(Kafka/文件系统)等,将数据规范化后批量导入到ES的各个Shard。Spark Streaming 基于以下两点可以实现为ES快速导入数据。

  1. Spark RDD 的Partition 能够良好的契合ES的Shard的概念。能够实现一一对应。避免经过ES的二次分发
  2. Spark Streaming 批处理的模式 和 Lucene(ES的底层存储引擎)的Segment对应的非常好。一次批处理意味着新生成一个文件,
    我们可以有效的控制生成文件的大小,频度等。

架构设计

下面是架构设计图:

1063603-8b7c006fb3422d8e.png
spark-es-4.png

整个系统大概分成四个部分。分别是:

  1. API层
  2. Spark 计算引擎层
  3. ES 存储层
  4. ES 索引构建层

API 层

API 层主要是做多查询协议的支持,比如可以支持SQL,JSON等形态的查询语句。并且可是做一些启发式查询优化。从而决定将查询请求是直接转发给后端的ES来完成,还是走Spark 计算引擎。也就是上图提到的 Query Optimize,根据条件决定是否需要短路掉 Spark Compute。

Spark 计算引擎层

前面我们提到了ES的三个缺陷,而Spark 可以有效的解决这个问题。对于一个普通的SQL语句,我们可以把 where 条件的语句,部分group 等相关的语句下沉到ES引擎进行执行,之后可能汇总了较多的数据,然后放到Spark中进行合并和加工,最后转发给用户。相对应的,Spark 的初始的RDD 类似和Kafka的对接,每个Kafka 的partition对应RDD的一个partiton,每个ES的Shard 也对应RDD的一个partition。

ES 存储层

ES的Shard 数量在索引构建时就需要确定,确定后无法进行更改。这样单个索引里的Shard 会越来越大从而影响单Shard的查询速度。但因为上层有了 Spark Compute层,所以我们可以通过添加Index的方式来扩大Shard的数目,然后查询时查询所有分片数据,由Spark完成数据的合并工作。

ES 索引构建层

数据的结构化必然带来了构建的困难。所以有了Spark Streaming层作为数据的构建层。这里你有两种选择:

  1. 通过ES原生的bulk API 完成索引的构建
  2. 然Spark 直接对接到 ES的每个Shard,直接针对该Shard 进行索引,可有效替身索引的吞吐量。
在大数据存储与检索场景中,**Elasticsearch(ES)** 和 **HBase** 是两种非常流行但定位完全不同的存储系统。选择哪一个取决于你的业务需求、数据模型、查询模式和性能要求。 下面我将从多个维度进行详尽对比,并给出选型建议,最后提供代码示例说明如何使用它们。 --- ## ✅ 一、核心定位对比 | 特性 | Elasticsearch (ES) | HBase | |------|---------------------|--------| | 类型 | 分布式搜索与分析引擎 | 分布式列式数据库(NoSQL) | | 底层存储 | 基于 Lucene 的倒排索引 | 基于 HDFS 的 LSM-Tree 存储 | | 数据模型 | JSON 文档(类似 MongoDB) | 行键 + 列族 + 时间戳的稀疏表 | | 查询能力 | 支持全文检索、聚合、模糊匹配、高亮等 | 支持按 RowKey 查找、范围扫描,不支持复杂查询 | | 实时性 | 近实时(NRT,延迟约 1s) | 强实时(ms 级别读写) | | 扩展性 | 水平扩展好,适合中小规模集群 | 超大规模扩展,PB 级别常见 | | CAP 定位 | AP(可用性和分区容忍) | CP(一致性和分区容忍) | --- ## ✅ 二、适用场景对比 ### 🟢 选择 **Elasticsearch** 如果你有以下需求: - ✅ 全文搜索:日志、文档、商品、用户信息搜索 - ✅ 结构化 + 非结构化数据混合查询 - ✅ 多维聚合分析(如统计访问量、趋势图) - ✅ 快速响应前端查询(Kibana 可视化) - ✅ 日志收集与监控系统(ELK 架构标配) 📌 典型应用: - 日志系统(Logstash + ES + Kibana) - 商品搜索引擎 - 用户行为分析平台 --- ### 🟢 选择 **HBase** 如果你有以下需求: - ✅ 海量数据存储(TB/PB 级别) - ✅ 高吞吐写入(每秒百万级写入) - ✅ 单条记录快速随机读取(通过 RowKey) - ✅ 强一致性保证 - ✅ 与 Hadoop/Spark 生态无缝集成 - ✅ 数据生命周期长(冷热数据分离) 📌 典型应用: - 实时风控系统 - 用户画像宽表存储 - 消息历史记录(如 IM 消息) - 推荐系统的特征存储 --- ## ✅ 三、性能对比(典型值) | 指标 | Elasticsearch | HBase | |------|---------------|-------| | 写入速度 | 中等(~几万条/秒) | 极高(~几十万~百万条/秒) | | 读取延迟 | ~10ms~100ms(受 refresh 影响) | ~1ms~10ms | | 查询灵活性 | 极强(布尔查询、分词、聚合) | 极弱(仅 RowKey 和 Scan) | | 存储成本 | 较高(副本多、索引大) | 较低(压缩率高、HDFS 存储) | | 运维复杂度 | 中等(需调优 JVM、分片) | 高(依赖 ZooKeeper、HDFS) | --- ## ✅ 四、架构集成能力 | 集成项 | ES | HBase | |-------|----|------| | 与 Kafka 集成 | ✅ Flink/Kafka Connect 可写入 | ✅ 常用于流式摄入 | | 与 Spark 集成 | ✅ spark-elasticsearch 插件 | ✅ 原生支持 RDD/DF | | 与 Hive 集成 | ⚠️ 外部表方式支持 | ✅ Hive on HBase | | 与 Flink 集成 | ✅ 支持 sink | ✅ 支持 | --- ## ✅ 五、代码示例对比 ### 示例:插入并查询一条用户登录日志 #### 🔹 使用 **Elasticsearch**(Python + elasticsearch-py) ```python from elasticsearch import Elasticsearch # 连接 ES es = Elasticsearch(["http://localhost:9200"]) # 插入文档 doc = { "user_id": "U123456", "action": "login", "ip": "192.168.1.100", "timestamp": "2025-04-05T10:00:00Z" } es.index(index="user_logs", body=doc, id=None) # 查询:查找某个用户的登录记录 res = es.search( index="user_logs", body={ "query": { "bool": { "must": [ {"match": {"user_id": "U123456"}}, {"range": {"timestamp": {"gte": "2025-04-05"}}} ] } } } ) for hit in res['hits']['hits']: print(hit['_source']) ``` > ✔️ 支持灵活查询、分词、聚合。 --- #### 🔹 使用 **HBase**(Python + happybase) ```python import happybase # 连接 HBase Thrift Server connection = happybase.Connection('localhost') table = connection.table('user_logs') # 构造 RowKey(通常设计为可排序的字符串) row_key = b'U123456_20250405100000' # user_id + timestamp # 插入数据 table.put(row_key, { b'info:action': b'login', b'info:ip': b'192.168.1.100' }) # 查询单条记录 data = table.row(row_key) if data: print(data[b'info:action'].decode(), data[b'info:ip'].decode()) # 扫描某个范围(前缀扫描) for key, data in table.scan(row_prefix=b'U123456_'): print(key, data) connection.close() ``` > ⚠️ 注意:不能直接做 `"WHERE action='login'"` 查询,必须靠 RowKey 设计! --- ## ✅ 六、是否可以同时使用? ✅ **是的!很多企业采用 ES + HBase 联合架构:** ``` 数据源 → Kafka → Flink ├→ HBase(持久化原始数据,高吞吐) └→ Elasticsearch(构建索引,支持搜索) ``` - HBase:作为“事实存储”,长期保存所有数据 - ES:作为“查询加速层”,提供快速检索能力 📌 优势: - 数据不丢失(HBase 保障) - 查询快(ES 保障) - 解耦存储与索引 --- ## ✅ 七、选型决策树 ```text 你的数据需要全文搜索 or 复杂查询? ├─ 是 → 选 Elasticsearch └─ 否 └─ 数据量是否超 TB?写入是否极高? ├─ 是 → 选 HBase └─ 否 └─ 是否已有 Hadoop 生态? ├─ 是 → HBase 更合适 └─ 否 → 可考虑 ES 或其他数据库(如 ClickHouse、MongoDB) ``` --- ## ✅ 总结表格:最终选型建议 | 场景 | 推荐系统 | |------|----------| | 日志搜索、监控、告警 | ✅ Elasticsearch | | 商品搜索、内容检索 | ✅ Elasticsearch | | 用户画像宽表(百亿行) | ✅ HBase | | 实时风控规则判断 | ✅ HBase(+ Redis 缓存热点) | | 需要聚合统计 + 可视化 | ✅ Elasticsearch | | 与 Spark/Flink 批处理强相关 | ✅ HBase | | 小规模项目,追求开发效率 | ✅ Elasticsearch | | 超大规模数据,强调稳定性与一致性 | ✅ HBase | ---
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值