写点什么

揭秘 Kafka 的硬盘设计方案,快速完成 PB 级数据扩容需求!

  • 2021-01-13
  • 本文字数:4972 字

    阅读完需:约 16 分钟

揭秘Kafka的硬盘设计方案,快速完成PB级数据扩容需求!

疫情期间,腾讯医疗为全国人民提供了及时精准的疫情信息服务。腾讯云 kafka 作为腾讯医疗大数据架构中的关键组件。在面对业务短时间内成倍的数据存储需求的情况下,如何快速响应、快速扩容以支持业务的稳定运行的呢? 本文将从 Kafka 集群底层物理机层面硬盘的设计方案,来讲解面对不同的业务需求场景,如何选择好合适的磁盘方案。


医疗资讯场景


腾讯医疗的使用场景是典型的日志分析系统。Kafka 作为消息中间件,起到了数据聚合、流量削峰的作用。如下图所示 :



日志分析系统架构在医疗的实例中,Kafka 承载着峰值 GB/s 的数据吞吐和大量的数据存储压力。这对底层的硬盘性能提出了很大的要求。比如吞吐/存储能力、快速扩缩容能力等。


所以一般在硬盘方案设计的时候需要综合考虑下列因素:大容量存储高吞吐量的 IO 能力快速扩缩容能力数据的安全性低冗余的存储组建 Kafka 集群,常见的硬盘构建主要包括:单硬盘读写、多目录读写、硬盘阵列(RAID0,RAID10)、逻辑卷(LVM)等方案。下面将深入分析各个方案的优劣势,供读者选择参考。


  1. 硬盘方案概述


硬盘存储方案的设计使用的是现在成熟的工业化方案,并没有特殊的创新。硬盘存储方案的选择更多的是从 Apache Kafka 产品的视角出发,考虑哪种方案更贴合使用者的业务需求。


  1. 选择硬盘介质


工业界的硬盘市场基本是机械硬盘和固态硬盘(SSD)的天下。在超大规模的存储容量场景下,SSD 的价格依旧是它的硬伤。对于 Kafka 这种高 IO 的应用,固态硬盘的损坏率和使用寿命是一个很大的问题。所以,机械硬盘以其便宜的价格及大容量成为了不二之选。


机械硬盘需要解决的两个问题是:如何提高硬盘 IO 能力;在硬盘损坏成为一个常态的情况下,又该如何保持业务系统的稳定。我们先从这两个方面来分析下。


  1. 提高硬盘 IO 能力


一般使用以下指标衡量硬盘的性能:IOPS:每秒读/写次数,单位为次(计数)。存储设备的底层驱动类型决定了不同的 IOPS。吞吐量:每秒的读写数据量,单位为 MB/s。时延:I/O 操作的发送时间到接收确认所经过的时间,单位为秒。Kafka 程序本身通过顺序读写、Page Cache、零拷贝等方案,从应用层面极大的利用了硬盘的性能。但是,一旦硬盘吞吐能力不足,Kafka 集群提供服务的能力将大打折扣。因为 Kafka 的使用场景和运行方式,最关注的性能指标是吞吐量。


在自建集群的场景下,用独立主机挂载单块硬盘的方式是最常用的方案。在单硬盘读写的基础上,提高硬盘吞吐能力的方案主要有如下几种:单硬盘读写 Kafka 的多目录读写 RAID 硬盘阵列方案 Logical Volume Manage(LVM)条带化方案


方案一: 单硬盘读写


单机单硬盘部署是在自建集群当中最常见的一种方案,也是在实践当中用的最多的一种方案。如下图:



单机单硬盘集群部署方案上图是一个由三台节点构成的 Kafka 集群,集群的每个节点挂载一块 SATA/SSD 的数据盘,用来存放 Kafka 的数据。该方案的特点就是思路简单,搭建快捷。很适合自建的小规模集群。


这种方案,当发现硬盘能力不足时,最直接有效的解决思路就是垂直扩容。即提高单盘的 IO 能力,比如将 5400 转/秒的硬盘换为 7400 转/秒的,或者换为 10000 转/秒、甚至 10000 转/秒以上的更高转速。当机械硬盘的能力不足时,直接换为大容量的 SSD。


这种方案的缺点也比较明显。首先,单块的 SSD 吞吐量是有上限的,当 Kafka 流量增大,SSD 也有承受不了的一天,单块硬盘的吞吐将限制 Kafka 集群的吞吐能力。另外 SSD 的价格大约是 SATA 的好几倍。以当前腾讯云上的硬盘价格为例,SSD 价格是高性能云硬盘的 3 倍。


所以,当集群规模持续扩大时,该方案并不是一个长久的选择。


方案二: Kafka 的多目录读写


当集群的压力持续增大,单块的硬盘满足不了需求或者基于成本考虑,不想使用 SSD 了,该怎么办呢? Apache Kafka 官方在 0.8 开始,提供了多目录读写的能力。将 log.dir 属性变为 log.dirs。官方解释如下:


A comma-separated list of one or more directories in which Kafka data is stored. Each new partition that is created will be placed in the directory which currently has the fewest partitions


简单说,就是支持配置多个日志文件夹,文件夹之间用逗号隔开,这样做在实际项目中有非常大的好处,即支持多硬盘的读写能力。在 server.properties 配置文件添加如上配置:


log.dirs=/data,/data1,/data2


添加了这个配置后,有什么效果呢,看下图:



如上图,假设有一个有 9 个分区 1 个副本的 topicA。这 9 个分区会平均分布在节点 1,2,3 上。假设节点 1 上分配了 0、1、2 三个分区。那么 Kafka 会将这三个分区的数据目录分别放在/data、/data1、/data2 三个目录下。partition 的数据目录分别为: /data/topicA-0、/data1/topicA-1、/data2/topicA-2。至于为什么会均匀分布就不详细展开了,有兴趣同学可以去参阅相关资料。


此时当 Kafka 往这三个分区写入数据的时候 ,就可以利用到三块硬盘的 IO 能力。其实这是一个很好用的方案。但是多目录读写方案也有一些情况是不能处理的。


我们来看下这种情况:因为业务特点不同,有的业务会出现数据冷热明显的问题。可能出现有的 partition 的量很大,有的 partition 量很小。这就有可能出现单个 Partion 的量达到了硬盘的 IO 瓶颈,此时就又回到了单硬盘的方案遇到的问题。


所以当业务有这种场景的时候,多目录的方案可能会有一些局限。


方案三: RAID 磁盘阵列


RAID 就是磁盘阵列,由很多块独立的硬盘组合成一个容量巨大的硬盘组,利用多个硬盘产生加成效果提升整个硬盘 IO 能力。典型代表有 RAID0、RAID1、RAID5、RAID10 等。由于篇幅原因,就不展开解释 RAID 的相关知识。有兴趣的可以查阅相关资料。简单比对一下以上方案的优劣势:



  1. RAID10 方案


使用 RAID 方案的原因就是为了解决单硬盘 IO 瓶颈的问题。经过以上方案比对,我们以 RAID10 为例,展开说明 RAID 做了什么,以及应该选择哪种 RAID 方案。先看下图:



上图中单机用四块盘组成 RAID10,即先用两块盘组成一块 RAID1 的虚拟盘,再用两块虚拟盘构建成一块虚拟的 RAID0 盘,并挂载到/data 目录下。理论上来看,假设单盘吞吐量是 100MB,那四块盘组成的 RAID10 阵列的吞吐就是 200MB,且每份数据在底层存储,是双副本的。


这里 RAID1 的作用是,即使底层有一块数据盘损坏,系统会自动读写另外一块备份盘的数据。此时系统还是能够正常使用的。RAID0 的作用是并行 IO,提高整体的 IO 能力。从理论上讲,三块硬盘的并行操作使同一时间内硬盘读写速度提升了 3 倍。但由于总线带宽等多种因素的影响,实际的提升速率肯定会低于理论值。但是,大量数据并行传输与串行传输比较,提速效果显著显然毋庸置疑。


这里需要注意一点的是,单纯从 IO 能力,从多块盘的 IO 能力相加的角度来看,RAID0 并不比多目录方案的 IO 能力强。RAID0 的优点在于,单块虚拟盘的 IO 能力比单块物理硬盘的强,单块虚拟盘容量比单块物理硬盘容量大。这两个特性是可以解决数据冷热明显、数据倾斜的情况的。


  1. 直接用 RAID0 可以吗?


细心的同学可能会发现这么一个问题?假设我们有 1 个分区 2 个副本的 topicB。两个副本分布在节点 1 和节点 2。此时当生产一条数据 messageA 时,messageA 会在集群里面存储 4 份。即节点 1 和节点 2 各存两份数据(RAID1 双副本)。如下图:



既然节点 1 和节点 2 都有 Kafka 的 Replication 副本了。为什么要在硬盘多冗余一份副本呢?这不是很浪费。是的。从数学的角度来看,是这样子没错。


我们来假设一个场景,假设我们直接用 RAID0。此时一个数据盘坏掉了,Kafka 集群会自动把影响到的 Partition 分区迁移到其他可用的机器上。如果刚好是 leader,则进行 leader 切换。看起来好像没问题。


但是假设刚好影响的 Parition 量比较大,将其切换到其他机器,会导致其他机器的压力增大,则很可能会影响到其他 Partition 的使用。这里是一个影响集群安全的重大隐患。


在一个成千上万台的大集群内,硬盘损坏是一件常事。这样就会造成分区迁移、leader 切换的过程变得相对频繁。但这点看起来不是特别大的问题,因为数据可以正常访问,也不会丢失。


但是如果客户对 leader 切换比较敏感,就会很快的感知到服务端的波动。作为服务提供商,还是希望给用户提供稳定的服务。如果发生上述情况,用户可能会觉得服务不够稳定,以至于影响厂商口碑。


由于工业发展,机械硬盘的价格持续下降,大容量的机械硬盘价格其实是极低的。所以在思考成本和稳定性的平衡中,可以考虑多付出成本,保证服务的稳定。


如果是 RAID10,坏了一块硬盘,此时系统还能正常运行。因为硬盘都有损坏告警,假设驻场更换的周期是 24 小时,则只需保证在 24 小时内,同一块 RAID1 的另一块硬盘不损坏,即可保证系统正常稳定无波动的运行。


下面分享个小技巧,先来看下面这张图:



单机不同批次硬盘部署示意图图中的硬盘为什么是不同颜色的呢?其实在做 RAID1 的时候,两块硬盘最好不要是同一个批次的。因为同一个批次硬盘具备相同的制作流程,考虑到可能会具备相同的磁盘寿命等因素,在一定程度上可能会增大两块硬盘同时损坏的概率。


到这里,似乎挺完美的了。我们再加一个因子:


假设开始规划的单机容量是 8TB,业务发展需要单机容量变为 10TB。那此时应该怎么办呢?


因为 Raid0 是不能动态扩展的。此时怎么办呢,貌似只有更换整个硬盘了。下面来看一下 LVM 方案。


方案四: LVM 逻辑卷条带化


LVM 逻辑卷的条带化原理和 RAID1 很像。都是条带化的进行数据读写。都有并行读写的能力。在实测过程中,两种方案的并行读写性能是差不多的。LVM 相对于 RAID10 的好处在于,它提供了动态扩容硬盘的能力。LVM 条带化的扩容是依赖以 lvmextend 命令实现的。扩容有一个条件:条带化的 lvm 扩容需要每个硬盘扩容大小一样的容量。如果每个硬盘容量不一样,条带化的 lvextend 会失败。


举个例子:例如当前有三块盘容量 1T,剩余空间 200GB 的盘,加入两块空间 1T 的盘,此时因为做了条带化,因为扩容需要从每块盘平均分出相等的空间来扩容,所以每块盘最多只能分出 200GB 的空间,五块盘共 1000GB 空间来扩容。此时,新加的盘就有 800GB 的空间没法利用。


如上所述,在用物理机挂载物理盘部署 Kafka 集群的的场景下,LVM 的动态扩容能力看起来没有实际用处。


我们换个场景,随着云服务时代到来。当我们在云上购买虚拟机,购买云上网盘来搭建集群的时候,LVM 的作用就凸显出来了,请看下图:



如图所示,每台 CVM 上挂三块云硬盘,三块云硬盘通过 LVM 条带化组建成一块逻辑硬盘,挂载到/data 目录下。云硬盘的特点是底层多副本,可在线扩容。这两个特点和 LVM 很搭。为什么呢?


云硬盘底层自带多副本,就不需要再做 Raid1 避免数据损坏、系统波动了。在线扩容,是指可以动态的对单块硬盘进行扩容。此时 lvm 的动态扩容能力就凸显出来了。如下图:



举个例子:假设集群一开始的时候规划每台机器只需要 600GB 的容量。此时,我们可以每台机器购买 6 块 100GB 的云硬盘,构建 LVM 条带化。挂载到/data 目录下,这样即可以利用条带化的并行写入能力,也可以得到所需的 600GB 容量。当业务发展一段时间,忽然发现,600GB 不够用了,每台 Broker 需要 1.2TB。此时我们通过控制台在线扩容硬盘容量,将每台 broker 的云硬盘扩容到 1.2TB,然后通过 lvextend 命令扩容/data 的容量,即可。


腾讯云上,单块云硬盘允许的最大容量为 16TB,单机允许最多挂载 20 块硬盘。所以,按照上述思路,一台机器理论的容量是 16*20=320TB。这对于单台机器来讲,基本是一个超大的容量了。


当然,上述毕竟是理论值。实践肯定达不到这么理想的状态。但是提供了一个思路。另外在提升条带化 IO 能力、估算挂盘的数量,都与 LVM 条带化时设置的 IO SIZE 有关。IO SIZE 取决于业务单条数据的长度和数据量。这个值并没有一个推荐的值,需要根据用户自身业务特点去评估。


如上所述,如果是部署在云上的 Kafka,LVM 是一种比 Raid10 更适合的方案。


总结


本文分析了常见的几种方案的使用场景和优劣。总结发现其实并没有一套完美的通用方案。而磁盘阵列也不是一个大力推荐的方案,自建集群的业务场景简单,单硬盘方案和多目录读写方案基本可以解决很多问题。而在业务场景复杂、规模大的物理机集群,RAID0 和 RAID10 都是可以考虑的方案。如果是部署在云上 CVM 主机的集群,LVM 方案是一个较好的选项。


综上所述,运营一个合适的 Apache Kafka 集群,需要根据业务特点、成本、数据可靠性、现有资源、所处环境等因素来考虑和权衡合适的硬盘方案。


头图:Unsplash

作者:许文强

原文:https://mp.weixin.qq.com/s/m1BzUynhDidXH3iDHt9wBg

原文:揭秘 Kafka 的硬盘设计方案,快速完成 PB 级数据扩容需求!

来源:腾讯云中间件 - 微信公众号 [ID:gh_6ea1bc2dd5fd]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-01-13 22:032291

评论

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

新思科技:数字赋能,安全先行

InfoQ_434670063458

测试开发 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

霍格沃兹测试开发学社

Dubbo 中 Zookeeper 注册中心原理分析

vivo互联网技术

zookeeper dubbo

利器 | AppCrawler 自动遍历测试工具实践(一)

霍格沃兹测试开发学社

如何又快又好实现Catalog系统搜索能力?火山引擎DataLeap这样做

字节跳动数据平台

大数据 数据治理 数据研发 企业号 2 月 PK 榜

如何快速完成API设计,mock数据给到前端?

不想敲代码

APi设计 apipost API调试

泛娱乐社交出海解决方案技术实践

网易智企

即时通讯IM 音视频通话

“一键”模型迁移,性能翻倍,多语言AltDiffusion推理速度超快

OneFlow

人工智能 深度学习

不愧是阿里内部都在强力进阶学习springboot实战派文档,这细节讲解,神了!

架构师之道

Java 面试 架构师 springboot

云小课|创建DDS只读节点,轻松应对业务高峰

华为云开发者联盟

数据库 后端 华为云 企业号 2 月 PK 榜 华为云开发者联盟

Kratos微服务工程Bazel构建指南

微服务 CMS Kratos Monorepo bazel

升哲科技荣获2022年度华夏建设科学技术奖二等奖

SENSORO

巧用Golang泛型,简化代码编写

百度Geek说

Go golang 企业号 2 月 PK 榜

泛娱乐社交出海解决方案技术实践

网易云信

即时通讯IM 音视频技术

云原生场景下实现编译加速

京东科技开发者

Java golang 缓存 编译 企业号 2 月 PK 榜

SpringBoot 如何保证接口安全?老鸟们都是这么玩的!

程序知音

Java spring 架构

下一代编解码技术Ali266在视频超高清领域的应用展望

阿里云CloudImagine

云计算 Ali266 超高清

测试开发 | AppCrawler 自动遍历测试实践(二):定制化配置

霍格沃兹测试开发学社

八股文的天花板,没到35k的Java开发都值得好好读一读

程序知音

java面试 后端技术 八股文 Java面试八股文 Java构架师

上新啦|请查收StarRocks 2.5 LTS 版本特性介绍

StarRocks

数据库 大数据

对话 BitSail Contributor | 梁奋杰:保持耐心,享受创造

字节跳动数据平台

GitHub 开源 数据引擎

系统运维 SysOM profiling 在云上环境的应用观测实践 | 龙蜥技术

OpenAnolis小助手

开源 cpu 系统运维 profiling 龙蜥技术

Dubbo 中 Zookeeper 注册中心原理分析

小小怪下士

Java zookeeper dubbo

开源机器学习软件对AI的发展意味着什么?

OneFlow

人工智能 深度学习 开源

关于 NGINX Kubernetes Gateway,你需要知道的 5 件事

NGINX开源社区

nginx NGINX Ingress Controller NGINX Kubernetes Gateway 企业号 2 月 PK 榜

打通对账的最后一公里——对账管理平台

元年技术洞察

数字化转型 对账 对账系统 方舟平台

优化器-RBO 的规则转化

KaiwuDB

RBO 数据库优化器

还在用 OpenFeign?来试试 SpringBoot3 中的这个新玩意!

江南一点雨

spring springboot

Getaverse 1月总结 | 节点数突破6200+

Geek_Web3

#区块链# 元宇宙 web3

一文带你掌握物联网Mqtt网关搭建背后的技术原理

华为云开发者联盟

后端 物联网 华为云 企业号 2 月 PK 榜 华为云开发者联盟

JavaScript使用URL用来解析处理URL

ModStart

揭秘Kafka的硬盘设计方案,快速完成PB级数据扩容需求!_语言 & 开发_腾讯云中间件_InfoQ精选文章