通过将TiDB与Hive和HDFS结合,提升大数据性能

2021-08-17 互联网

工业:知识共享

作者:胡梦宇(知乎平台工程师)

Transcreator:冉黄编辑:汤姆政府高级官员

通过将TiDB与Hive和HDFS结合,提升大数据性能

中国最大的知识共享平台,注册用户超过2.2亿,网站上的答案超过3.1亿条。2021年3月,我们在纽约证券交易所上市价值约53亿美元。

随着业务的发展,我们希望改善基础设施。我们水平扩展Apache Hive Metastore从MySQL迁移到TiDB,一个分布式SQL数据库,并决定将TiDB应用到其他大数据应用程序中。迁移之后,大型查询的执行时间从30-40秒降低到6-7秒.我们被它的力量震撼了蒂德

在本文中,我将向您展示TiDB如何提高大数据体系结构性能的两个示例。你将看到我们如何使用TiDB在Hive中为大型查询构建一个实时警报系统,并在HDFS中加速NameNode RPC请求。

Hive中的大型查询警报

Apache Hive是一个数据仓库,提供数据查询和分析功能。在知虎,我们使用Hive进行提取、转换和加载(ETL)任务和特别查询。

我们的痛点

对于ETL任务,SQL语句是相当稳定的,而特别的查询通常包含不稳定的SQL语句。优化特别的查询很重要;否则可能导致MapReduce任务扫描数据过多,导致任务执行速度变慢,对HDFS造成巨大压力。因此整个集群是不稳定的。

当用户试图查询季度或年度数据时,这个问题经常会出现。当Hive执行此类查询时,集群经常会出现资源不足的情况。如果没有足够的资源,ETL任务就会卡住,报告也会延迟。

一个大型查询报警系统

为了解决这个问题,我们开发了一个系统来实时提醒用户有关大型查询的信息。当用户向配置单元发送SQL语句时,系统:

  1. 解析执行计划,将执行计划转换为Hive需要扫描的表路径和分区路径。
  2. 聚合所有分区路径并计算要扫描的数据的大小。
  3. 确定数据大小是否超过阈值。如果有,系统会提醒用户。

获取HDFS路径

解析每个SQL语句后,我们使用Hive server的钩子机制将审计日志输出到Kafka。日志格式如下:

“操作”“查询”“用户”“hdfs”“时间”“2021-07-12 15:43:16.022”“知识产权”"127.0.0.1"“hiveServerIp”"127.0.0.1"“inputPartitionSize”2“sql”"select count(*) from test_table where pdate in (' 2011-07-01 ',' 2011-07-02 ')"“hookType”“预执行钩”“currentDatabase”“默认”“会话ID”“5 e18ff6e - 421 d - 4868 - a522 fc3d342c3551”“queryId”“hive_20210712154316_fb366800 - 2 cc9 - 4 - ba3 - 83 a7 - 815 c97431063”“可输入列表”“test_table”“输出列表”“输入路径”“/ user / hdfs /表/ default.db / test_table / 2021-07-01”“/user/hdfs/tables/default.db/test_table/2021-07-02”“应用程序所有者”“humengyu”

注意以下字段:

领域 描述
操作 SQL类型;例如,QUERY, DROP。
使用者 发送SQL语句的用户组。
sql SQL语句。
inputPaths 要扫描的HDFS路径。
app.owner 发送SQL语句的人。

计算分区大小

为了计算分区大小,我们需要知道每个目录的大小inputPaths. 我们决定解析HDFSfsimage并计算每个Hive目录的大小,然后将结果保存到TiDB中。

因为其他应用程序也使用fsimage,我们不仅保存了Hive目录,还保存了整个HDFS目录,总计有数百亿条记录。TiDB是存储和索引大量数据的极佳选择。

实时警报

系统计算出数据大小后,决定是否向用户发送实时警报,让用户知道可能存在的风险。在报警过程中:

  1. Hive服务器会将审计日志实时发送给Kafka。
  2. Flink使用来自Kafka的数据,并通过Kafka表源将Kafka视为流式表。
  3. Flink使用JDBC Lookup Table Source将TiDB视为一个维度表。
  4. Flink计算每个SQL查询扫描的数据大小,并决定是否发送警报。

报警过程

报警过程

最后,如果用户写了一条SQL语句,扫描了太多的数据,他们会收到这样的警告:

一个大型SQL查询警报

一个大型SQL查询警报

加速NameNode RPC请求

除了为大型查询发送警报外,我们还使用TiDB来提高NameNode的性能。

NameNode性能问题

过去,许多用户抱怨Hive查询需要几分钟甚至几个小时。我们调查了这个问题,发现问题在于远程过程调用(RPC)。当蜂巢呼叫getInputSummary方法,它将获得全局锁。在释放锁之前,其他查询无法访问数据。如果配置单元执行大型查询,则调用此方法可能需要很长时间。因此,其他查询线程必须等待。

我们读了Hive的源代码,发现Hive可以执行多个getInputSummary方法同时进行。(在内部,此方法称为HDFSgetContentSummary方法。)我们移除了全局锁,并用类似线程池的方法替换它。现在getContentSummary可以以高并发性执行。

然而,出现了另一个问题。HDFS的getContentSummary方法类似于文件系统磁盘使用情况()手术。getContentSummary以高并发方式执行,主节点性能可能会显著降低。因为其他计算引擎也使用这种方法,所以优化它很重要。

缓存ContentSummary

2019年初,知乎将文件系统拆分为HDFS Federation使用基于路由器的Federation.在这个体系结构中,我们引入了一个名为路由器将请求转发给NameNode。

我们解决NameNode性能问题的方法是在路由器层为HDFS内容摘要添加缓存。具体地说,我们每天使用生成所有目录的内容摘要fsimage并将缓存存储在TiDB中。

当客户端发送请求时,HDFS尝试在缓存中查找数据。如果找不到请求的数据,它将从NameNode获取数据并更新缓存。缺点是,由于父目录无法检测子目录中的更改,因此只能缓存叶目录。在这种实现中,很少有请求转到NameNode,因此NameNode性能不受影响。

这种解决方案很方便,因为我们在构建Hive大型查询报警系统时已经生成了内容摘要。在我们将缓存保存在TiDB中并为所请求的路径创建索引之后,普通计算机的延迟getContentSummary请求从几分钟减少到不到10毫秒。

我们未来的计划

得益于TiDB存储大量数据的横向可扩展性和加速查询的索引功能,我们成功地存储了HDFS元数据以满足智湖的业务需求。

作为一个混合的事务和分析(HTAP)数据库,TiDB有很多可以挖掘的潜力。例如,我们可以实时缓存HDFS文件元数据,并从EditLog订阅文件更改。通过合并文件更改fsimage在TiDB中,我们可以生成NameNode的低延迟快照,并使用它们进行在线分析。

展望未来,TiDB将继续在智湖的基础设施建设中发挥重要作用,并支持我们的高速增长。我们期待着在我们的大数据架构中应用它。

准备好开始使用TiDB了吗?