HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

Apache Kudu 在网易的实践

  • 2021-08-08
  • 本文字数:3179 字

    阅读完需:约 10 分钟

Apache Kudu在网易的实践

本文主要介绍 Apache Kudu 及在网易实时数据采集、维表数据关联、实时数仓 ETL、ABtest 等场景的实践应用。主要内容包括:

  • 系统概述:认识 kudu,理解 Kudu 的系统设计与定位

  • 生产实践:分享网易内部的典型使用场景

  • 遇到的问题:实际使用过程中遇到的问题和问题的排障过程

  • 功能展望:对 Kudu 功能特性的展望

Kudu 定位与架构

Kudu 是一个存储引擎,可以接入 Impala、Presto、Spark 等 Olap 计算引擎进行数据分析,容易融入 Hadoop 社区。Kudu 整合了随机读写和大数据分析能力,具有低延迟的随机读写能力和高吞吐量的批量查询能力。


与 HBase、Casandra 不同,Kudu 要求声明 Schema。Schema 可以为上层计算引擎提供更多元数据,进行计算优化。Kudu 的每个字段有主键、列名和列类型。拿到列类型信息后能够对不同列进行编码和压缩,优化存储空间,减少磁盘开销。Kudu 支持 bitshuffle、运行长度编码、字典编码等列编码方式,这些编码会根据列的类型不同做不同设计。比如对于重复值多、重复值变化不大的数据的压缩率很好。


Kudu 使用列式存储给 Kudu 带来了如下特性:

1. 存储上可以节约空间

2. 可以对查询做更多优化,如将过滤条件下推到 kudu 执行,节约计算资源

3. 支持向量化操作

Kudu 的 Schema 和列存


Kudu 数据存储在 Table 中,Tablet 是 Kudu 的读写单元,Table 内的数据会划分到各个 Tablet 进行管理。


创建 Table 时,需要指定 Table 的分区方式。Kudu 提供了两种类型的分区方式 range partitioning ( 范围分区 ) 、 hash partitioning ( 哈希分区 ),这两种分区方式可以组合使用。分区的目的是把 Table 内的数据预先定义好分散到指定的片数量内,方便 Kudu 集群均匀写入数据和查询数据。范围分区支持查询时快速定位数据,哈希分区可以在写入时避免数据热点,可以适应各个场景下的数据。



Kudu 有管理节点(Master)和数据节点(Tablet Server)。管理节点管理元数据,管理表到分片映射关系、分片在数据节点内的位置的映射关系,Kudu 客户端最终会直接链接数据节点。

 


Kudu 作为分布式系统,为了保障数据可用性和高可用,支持多副本。Kudu 使用 Raft 协议来实现分布式环境下副本之间的数据一致性。Raft 算法数据不依赖其他存储和文件系统,优势在于可以保证服务高可用、服务可用性、一致性的均衡。

Kudu 的 update 设计

Olap 中对 update 的设计会影响到 Olap 性能。update 操作可能引发数据多版本问题和 update 引发的数据 merge 问题。

 



Tablet 是 Kudu 数据读写单元,Tablet 下更细分的数据存储单元是 RowSet。RowSet 有两种, 分别是 MemRowSet 和 DiskRowSet,不同 RowSet 维护了不同组件范围内的数据。内存中的 MemRowSet 在到达一定大小后会刷盘成为 DiskRowSet。




 Kudu 把更新操作当作一条新操作,而不是写一条新日志。更新操作是 Undo/Redo 记录,这些内存中的更新操作会被整合为 DeltaMemstore 持久化。Base 数据、Undo 数据、Redu 数据写在同一个 RowSet 中。这样的存储设计优点是可以在更新时候快速找到数据,缺点是查询时需要确认查询的主键在哪个 RowSet 位置中。

 

Kudu 也使用了 LSM 的结构。Kudu 的 comopaction 有多种:MinorDeltaCompaction、MajorDeltaCompaction、MergingCompaction。



 Kudu 的 update 是一个多版本操作,目的是写入和读取时互相不干扰、不需要读时额外加锁。

小结

Kudu Update 设计特点:

 

• 更新已经 flush 的数据和写入新数据走不通的处理逻辑,原始数据和更新位于同一个 Rowset,不用跨 Rowset 进行 merge

• 通过 base 数据的 RowID 和更新时间戳作为 REDO/UNDO 数据的 key,读取更新高效

• Key 大小固定,存储和比较效率高

• 不需要查询出主键数据也能获取更新数据

• 在大多数使用场景下能够实现更高效的读取

• 如果返回的结果不要求顺序,直接从 RowSet 中读出数据,不用 merge

• 如果更新较少,REDO 会快速 merge 到 base 数据,这时在读取最新数据时,可以不进行 apply REDO 的操作

生产实践

实时数据采集场景

实时数据分析中,一些用户行为数据有更新的需求。没有引入 Kudu 前,用户行为数据会首先通过流式计算引擎写入 HBase,但 HBase 不能支撑聚合分析。为了支撑分析和查询需求,还需要把 HBase 上的数据通过 Spark 读取后写入其他 OLAP 引擎。使用 Kudu 后,用户行为数据会通过流式计算引擎写入 Kudu,由 Kudu 完成数据更新操作。Kudu 可以支持单点查询,也可以配合计算引擎做数据分析。


维表数据关联应用

有些场景中,日志的事件表还需要和 MySQL 内维度表做关联后进行查询。使用 Kudu,可以利用 NDC 同步工具,将 MySQL 中数据实时同步导入 Kudu,使 Kudu 内数据表和 MySQL 中的表保持数据一致。这时 Kudu 配合计算引擎就可以直接对外提供结果数据,如产生报表和做在线分析等。省去了 MySQL 中维度表和数据合并的一步,大大提升了效率。

 

实时数仓 ETL

Kudu 作为分布式数据存储引擎,可以和 Hadoop 生态更好结合,因此在生产中我们采用了使用 Kudu 替换 Oracle 的做法,提升了扩展性。

 

ABTEST

在我们的 ABTest 业务中有两种日志,行为日志和用户分流日志。



架构升级前,我们采用了比较传统的模式,将用户行为日志和用户分流日志分别写入 HDFS 作为存储的 ODS 层,通过 Spark 做清洗、转换后导入 HDFS 作为存储的 DWD 层,再通过 Spark 进行一步清洗、按照时间或其他纬度做简单聚合后写入 DWS 层。

 

这个架构的问题是数据产出时间比较长,数据延迟在天级别。业务方需要更及时地拿到 ABTest 结果。

 


 架构升级后,使用 Kafka 作为 ODS、DWD 层存储。Flink 在 ODS 层数据的基础上继续做一层整理和过滤,写入 DWD 形成明细表数据;DWD 层在 Flink 中做简单聚合后写入 DWS 层,Kudu 在 DWS 层作为数据存储。

 

Flink 开窗口实时修正实验数据,这一操作在 Kudu 完成;超出了 Flink 时间窗口的数据更新则由离线补数据的操作在 Kudu 中完成修正。

 

架构升级后,数据延迟大大降低,能够让 ABTest 业务方更实时地拿到结果。

我们遇到的问题 

问题 1: 节点负载不均衡

一些大表场景下会有负载不均衡问题。Kudu 不会把 range 下的哈希分片当作一张表,而是把整个表的分片当成了平等的表进行处理。而在真实使用场景中,range 基本是时间字段;需要让 range 的 hash 分片更均匀地分布在各节点上,防止数据倾斜。下图是数据倾斜的情况展示:

 


我们的解决方案是实现了一套优化版本的负载均衡算法,这个算法能够把 range 表当作单独的表做负载均衡,解决了数据倾斜。下图是优化后效果:


问题 2: 表结构设计复杂

问题 3: 没有二级索引,只能通过控制主键顺序和分区键来优化某几种查询模式

问题 4: 创建表时需要根据业务场景专门设计表结构

问题 2-4,对业务方要求比较高,经常需要专人介入引导业务方导入数据。为了解决问题,我们内部设计了二级索引来解决上述问题。二级索引可以满足查询性能的要求,同时减少用户设计表时候的复杂度:

 

  • 通过支持二级索引来优化包含非主键列过滤的查询

  • 支持二级索引能够降低业务设计表结构的复杂度

  

社区对二级索引的支持进度 KUDU-2038:Add b-tree or inverted index on value field

Kudu 功能展望

BloomFilter

BloomFilter 成本较低、效率较高。Join 场景下,小表动态生成 BloomFilter 下推到存储层,防止大表在 Join 层做数据过滤。最近的 Kudu 中已经支持了 BloomFilter 作为过滤条件。

灵活分区哈希

Kudu 每个 range 的 hash bucket 数量是固定的。考虑到时间和业务增长,在项目实施前期阶段要给 Kudu 哈希桶数量设置略大,但是数据量较小的场景下过大的分片个数对资源是一种浪费,社区也不推荐 hash bucket 设置得比较大。期望后续 Kudu 可以更灵活地适配 hash bucket 数。

 > KUDU-2671:Change hash number for range partitioning

多行事务

Kudu 暂时不能支持多行事务。目前更新主键需要业务自己实现逻辑检测。

> KUDU-2612:Implement multi-row transactions

Flexible Schema

一些业务场景下业务没有唯一主键,但只希望利用 Kudu 的大批量写入、聚合分析查询的特性。接入业务时 Kudu 对 Schema 的要求比较高,一些业务场景无法支持。

> KUDU-1879:Support table without a primary key


本文转载自:Datafuntalk(ID:datafuntalk)

原文链接:Apache Kudu在网易的实践

2021-08-08 07:003866

评论

发布
暂无评论
发现更多内容

Mac免费实用的读写软件Tuxera NTFS2023

茶色酒

Tuxera NTFS2023\ Tuxera NTFS2023

易观千帆 | 2022年12月银行APP月活跃用户规模盘点

易观分析

金融 手机银行 用户

组合多个动画效果 —— Flutter 交错动画(Staggered Animation)简介

岛上码农

flutter ios 前端 动画 安卓开发

CRC工业精密电器清洁剂,硬核技术护航清洁产业发展

科技热闻

云原生数据交付平台Kuda在AI场景下的模型分发实践

Geek_c4ea78

机器学习 开源 Kubernetes 容器 云原生

C++实现惰性求值

SkyFire

c++ 函数式编程 模板元编程

使用启科QuPot+Runtime+QuSaaS进行量子应用开发及部署-调用AWS Braket计算后端

启科量子开发者官方号

量子计算 Amazon Braket

基于Spring Cache实现Caffeine、jimDB多级缓存实战

京东科技开发者

spring 缓存 接口 系统 企业号 1 月 PK 榜

架构实战营4.5 常见存储系统随堂练习

西山薄凉

「架构实战营」

接口测试这件小事

石臻臻的杂货铺

接口测试

可以手动磨皮的p图软件portraiture2023

茶色酒

Portraiture2023

5 个 JavaScript 代码优化技巧

devpoint

JavaScript 前端开发 JS代码优化 扩展运算符

SimMIM:更简单的掩码图像建模

Zilliz

Tokio 中 hang 死所有 worker 的方法

Databend

Gartner:流程挖掘市场发展空间巨大,2022年预计市场规模将超10亿美元

九科Ninetech

性能提升 40 倍!我们用 Rust 重写了自己的项目

Peefy

rust 编程语言 #go Python.

架构实战营模块四作业

西山薄凉

「架构实战营」

镜像拉取节省 90% 以上,快手基于 Dragonfly 的超大规模分发实践

OpenAnolis小助手

开源 架构 快手 龙蜥技术 容器云平台

在spring boot3中使用native image

程序那些事

spring 程序那些事 spring boot3

软件测试/测试开发 | Appium 用例录制

测试人

软件测试 自动化测试 测试开发 测试用例 appium

基于 SLO 告警(Part 1):基础概念

Grafana 爱好者

可观测性 SRE SLO

电商秒杀系统架构设计

π

架构实战营

架构训练营模块五作业

张Dave

Java高手速成 | JSP MVC模式项目案例

TiAmo

mvc java; jsp

佛萨奇2.0上链DApp开发|佛萨奇链上开发技术

薇電13242772558

dapp

委派模式——从SLF4J说起

vivo互联网技术

Java slf4j 委派模式

【必看知识】PCB设计中焊盘的设计标准

华秋PCB

工具 PCB PCB设计

技术管理者如何发掘写代码之外的能力?

石云升

极客时间 1月月更 技术领导力实战笔记

架构实战营4.6 千万学生管理系统存储设计

西山薄凉

「架构实战营」

真相了!TCP连接原来是这么被墙干掉的!

程序员小毕

程序员 后端 网络协议 架构师 tcpip

镭速-跨国车企数据高速、安全跨境传输解决方案

镭速

Apache Kudu在网易的实践_语言 & 开发_DataFunTalk_InfoQ精选文章