Kafka线上集群部署方案怎么做?
这篇文章,我将从操作系统、磁盘、磁盘容量和带宽等方面讨论一下,生产环境中 Kafka 集群方案怎么做。
操作系统
首先我们要看看把 Kafka 安装到什么系统上,以及知道为什么。
目前常见的操作系统有 3 种:Linux、Windows 和 macOS。可以说部署到 Linux 上的生产环境是最多的,当然部署到另外系统上的也有。
如果考虑操作系统和 Kafka 的适配性,显然 Linux 系统要比其他两个特别是 Windows 更加适合部署 Kafka。虽然这个结论可能是你意料之中的,但你知道为什么吗?主要的原因是在下面这三个方面上,Linux 表现得更胜一筹:
- I/O 模型的使用
- 数据网络传输效率
- 社区支持度
I/O 模型的使用
首先来看 I/O 模型,I/O 模型描述了计算机系统中进行输入(Input)和输出(Output)操作的方式。
常见的 I/O 模型有 5 种类型:阻塞式 I/O、非阻塞式 I/O、I/O 多路复用、信号驱动 I/O 和 异步 I/O。每种 I/O 模型都有各自典型的使用场景,比如 Go 语言中 select 配合 default 关键字就可以实现两种模式,就对应前两种模型;而 Linux 中那点系统调用 select 函数就属于 I/O 多路复用模型;大名鼎鼎的 epoll 系统调用则介于第三种和第四种模型之间;至于第五种模型,很少有 Linux 系统支持,反而 Windows 系统提供了一个叫 IOCP 线程模型属于这一种。
我们不需要了解每一种模型,只需要知道后一种模型比前一种模型高级,比如 epoll 就比 select 好。
Kafka 客户端底层使用了 Java 的 selector,selector 在 Linux 上的实现机制是 epoll,而在 Windows 平台上的实现机制是 select。因此,把 Kafka 部署在 Linux 上更具优势,能够获得更高的 I/O 性能。
数据网络传输效率
其次就是网络传输效率的不同。Kafka 的生产者和消费者的消息都是通过网络传输的,而消息保存是磁盘的。故 Kafka 需要在磁盘和网络间进行大量的数据传输,这之间就会涉及到数据拷贝的问题。如果你经常使用 Linux,肯定听说过 零拷贝技术,就是当数据在磁盘和网络间进行传输时避免昂贵的内核态数据拷贝从而达到快速的数据传输。Linux 平台实现了这样的零拷贝机制,虽然 Windows 也实现了,但令人遗憾的是 Windows 平台必须要等到 Java 8 的 60 更新才能使用这个机制。故,在 Linux 部署 Kafka 能够享受零拷贝技术锁带来的快速传输数据特性。
社区支持度
最后是社区支持度。Kafka 社区对 Windows 平台上发现的 Kafka Bug 不做任何承诺,虽然口头上保证尽力去解决。因此,Windows 平台上部署 Kafka 只适合个人测试或用于功能验证,千万不要应用于生产环境。
磁盘
如果要对各种资源对 Kafka 的性能影响排个队,那磁盘无疑是在前列的。在磁盘上的选择,通常有两种:普通的机械磁盘和固态硬盘。前者成本低且容量大,但易损坏;后者性能优势大,不过单价贵。这里的建议是选择普通机械硬盘即可,理由见下。
Kafka 大量使用磁盘不假,但 Kafka 日志设计结构和理念的特性决定了,它使用的方式大多是顺序读写操作,一定程度上规避了机械硬盘最大的劣势,即随机读写操作慢。也正是因为这一点,SSD 似乎也没有太大的性能优势。从性价比上来说,机械硬盘物美价廉,而它因易损坏造成的可靠性差等缺点,又由 Kafka 在软件层面提供了机制来保证,故使用机械硬盘是很划算的。
Kafka通过副本机制、持久性日志、ISR(In-Sync Replicas)等软件层面的设计来提高可靠性,确保在硬盘故障等情况下数据的持久性和可用性。
而关于磁盘选择另一个经常讨论的话题:到底是否应该使用磁盘列阵(RAID)。使用 RAID 的两个主要优势在于:
- 提供冗余的磁盘存储空间
- 提供负载均衡
以上两个优势对于任何一个分布式系统都很有吸引力。但对于 Kafka 来说,一方面 Kafka 实现了自己的冗余机制来提供高可靠性;另一方面通过分区的概念,Kafka 也能在软件层面实现负载均衡。所以,RAID 的优势就不太明显了。这里并不是说 RAID 不好,实际上还是有很多大厂把 Kafka 的底层存储交给 RAID 的,只是 Kafka 在存储这方面提供了越来越便捷的高可靠方案。因此在线上环境使用RAID似乎变得不是那么重要了。
综合上述考量,建议是:
- 追求性价比的公司可以不搭建 RAID,使用普通磁盘组成存储空间即可。
- 使用机械磁盘完全能够胜任 Kafka 线上环境。
磁盘容量
Kafka 需要将消息保存到底层的磁盘上,这些消息默认会保存一段时间然后自动被删除。虽然这段时间是可以配置的,但你应该如何结合自身业务场景好存储需求来规划 Kafka 集群的存储容量呢?下面将通过一个例子来说明对于这种问题,该如何思考。
假设现在有个业务每天要向 Kafka 集群发送 1 亿条消息,每条消息需要保存两份以防止数据丢失,另外消息默认保存两周时间现在假设消息的平均大小是 1 KB,那么 Kafka 集群需要为这个业务预留多少磁盘空间呢?
我们来计算一下:每天 1 亿条消息,保存两份且保存两周时间,那么总的空间大小就是 1 亿 * 1 KB * 14 * 2 / 1000 / 1000 / 1000 = 2.8 TB。一般情况下, Kafka 集群除了保存信息数据还要保存其他类型的数据,比如索引数据等,故我们需要再为其他类型的数据预留出 10 % 的空间,大约是 3 TB。Kafka 支持数据压缩,假如压缩比是 0.75,那么最后需要规划的存储空间就是 0.75 * * 3 = 2.25 TB。
综上,在我们规划磁盘容量时,需要考虑的元素有:
- 新增消息数
- 消息留存时间
- 平均消息大小
- 备份数
- 是否启用压缩
带宽
对于 Kafka 这种通过网络大量进行数据传输的框架而言,带宽特别容易成为瓶颈,如果还涉及到跨机房传输,那么情况就更糟糕了。
下面我以一般公司网络的标准配置:千兆网络,来举一个实际的例子,来说明一下如何进行带宽资源的规划。
与其说是带宽资源的规划,其实真正要规划的是所需的 Kafka 服务器的数量。假如你公司的机房环境是千兆网络,即 1 Gbps 等于 10 亿个二进制位。现在有个业务,目前是在一小时内处理 1 TB 的业务数据,那你需要多少台 Kafka 服务器来完成这个业务呢?
由于带宽是 1Gbps,即每秒处理 1 Gb 的数据,假设每台 Kafka 服务器都是安装在专属的机器上,也就是每台 Kafka 集群上没有部署其他服务,但真实环境中不建议这么做,总要为其他应用或进程留一些资源,所以通常情况下只能假设 Kafka 会用到 70% 的带宽资源。
根据查阅资料,超过 70% 的阈值就有网络丢包的可能性了,故 70% 的设定是一个比较合理的值,也就是说单台Kafka服务器最多也就能使用大约 700Mb 的带宽资源。
你以为这就完了?并不是,这只是它能使用的最大带宽资源,你不能让Kafka服务器常规性使用这么多资源,故通常要再额外预留出2/3的资源,即单台服务器使用带宽 700Mb / 3 ≈ 240Mbps。需要注意的是,这里的2/3其实是相当保守的,你可以结合你自己机器的使用情况酌情减少此值。
现在知道了,单台服务器部署 Kafka 每秒可以处理 240Mb 数据。根据需求 1 小时处理 1TB 数据,转换一下就是每秒处理 2330Mb 的数据,除以 240,约等于 10 台服务器。服务还需要额外复制两份,那么总的台数还要乘以 3,即 30 台。
用这种方法评估线上环境的服务器台数是比较合理的,而且这个方法能够随着你业务需求的变化而动态调整。
小结
所谓 “兵马未动粮草先行”。与其盲目上线一套 Kafka 环境然后费力调整,不如在一开始就思考好实际场景下业务所需的集群环境。
在考量部署方案的时候需要通盘考虑,不能仅仅从单个维度上去评估。下面对今天的重点做一个总结:
因素 | 考量点 | 建议 |
---|---|---|
操作系统 | 操作系统 I/O 模型、数据网络传输效率、社区支持度 | 将 kafka 部署在 Linux 系统上 |
磁盘 | 磁盘 I/O 性能 | 普通环境使用机械磁盘,不需要搭建 RAID |
磁盘容量 | 根据消息数、留存时间预估磁盘容量、消息大小、是否备份、是否压缩 | 实际中建议预留 20% ~ 30% 的磁盘空间 |
带宽 | 根据实际带宽资源和业务 SLA 预估服务器数量 | 对于千兆网络,建议每台服务器按照 700Mbps 来计算,避免大流量下的丢包。 |