01 Kafka的简单介绍

本文深入探讨Kafka如何实现高吞吐量和低延迟,解析其利用操作系统页缓存、零拷贝技术、追加写入及消息持久化策略。同时,介绍Kafka的负载均衡、故障转移机制及伸缩性原理,涵盖Broker、Topic、Partition等核心概念。

kafka在设计之初就考虑的问题

  • 吞吐量/延时
  • 消息持久化
  • 负载均衡和持久化
  • 伸缩性

先说吞吐量问题:

kafka是如何做到高吞吐量和低延时的呢?

kafka的写入操作是很快的,这主要得益于它对磁盘的使用方法不同。虽然kafka会持久化所有数据到磁盘,但本质上每次写入操作其实都只是把数据写入到操作系统的页缓存中,然后由操作系统自行决定什么时候把页缓存中的数据写回磁盘。

先说kafka是咋实现的,kafka依靠下列4点达到了高吞吐量、低延时的设计目标:

  • 大量使用操作系统页缓存,内存操作速度快且命中率高。

  • kafka不直接参与物理I/O操作,而是交给最擅长此事的操作系统来完成。

  • 采用追加写入的方式,摒弃了缓慢的磁盘随机读写操作。

  • 使用以sendfile为代表的的零拷贝技术加强网络间的数据传输效率。

前三个都是使用页缓存的好处,页缓存是在内存中分配的,所以写入消息很快。使得kafka不必直接与底层文件系统打交道。另外采用追加的方式写入,避免了磁盘随机写操作。

零拷贝:

简而言之,就是避免让CPU做大量的数据拷贝技术,采用不使用CPU时间的技术进行系统内核缓冲区之间的数据拷贝。

只使用DMA技术

​ 从上图中可以看出,共产生了四次数据拷贝,即使使用了DMA来处理了与硬件的通讯,CPU仍然需要处理两次数据拷贝,与此同时,在用户态与内核态也发生了多次上下文切换,无疑也加重了CPU负担。

让数据传输不需要经过user space

我们减少拷贝次数的一种方法是调用mmap()来代替read调用:

buf = mmap(diskfd, len);
write(sockfd, buf, len);

​ 应用程序调用mmap(),磁盘上的数据会通过DMA被拷贝的内核缓冲区,接着操作系统会把这段内核缓冲区与应用程序共享,这样就不需要把内核缓冲区的内容往用户空间拷贝。应用程序再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态,最后,socket缓冲区再把数据发到网卡去。

在这里插入图片描述

sendfile

使用sendfile不仅减少了数据拷贝的次数,还减少了上下文切换,数据传送始终只发生在kernel space。下图为使用DMA的sendfile零拷贝技术图。

在这里插入图片描述

零拷贝部分参考作者以及链接:

作者:卡巴拉的树
链接:https://www.jianshu.com/p/fad3339e3448

再说 消息持久化

kafka是要持久化消息的,而且要将消息持久化到磁盘上的。

先说这样做的好处(为什么要持久化)?:

  • 解耦消息发送与消息消费:通过将消息持久化使得生产者不再需要直接和消费者方耦合,它只是简单地把消息生产出来并交由kafka服务器保存起来即可。
  • 实现灵活的消息处理(便于消息重演):很多kafka下游子系统(消费方)都会有这样的需求——对于已经处理过的消息可能在未来的某个时间点重新处理一次,即所谓的消息重演(message replay)

那么kafka持久化是咋做的呢?

对比一下:

​ 普通的系统实现持久化时可能先尽量使用内存,当内存资源耗尽时,再一次性地把数据 “刷盘”;kafka则反其道行之,所有数据都会立即被写入到文件系统的持久化日志中,之后kafka服务器才会返回结果给客户端,通知客户端消息写入成功。 这样做即实时保存了数据,又减少了kafka程序对于内存的消耗,从而将节省出的内存留给页缓存使用,进一步提升整体性能。

这里解释下: kafka在吞吐量中说使用页缓存,持久化又说尽量减少对内存的消耗,这是咋回事?

总的来说,Kafka不会保持尽可能多的内容在内存空间,而是尽可能把内容直接写入到磁盘。所有的数据都及时的以追加的方式写入到文件系统的持久化日志中,而不必要把内存中的内容刷新到磁盘中。

再来看看 负载均衡和故障转移

kafka作为一个完备的分布式系统,肯定也是要满足负载均衡和故障转移处理操作的。

负载均衡:kafka的负载均衡是通过智能化的分区领导者选举来实现的。可以在集群中的所有机器上以均等的机会分散各个partition的leader,从而整体上实现了负载均衡。【后面进行补充】

故障转移(使用zookeeper):即当服务器意外中止时,整个集群能够快速检测到他失效了,并立即将该服务器上的应用或服务转移到其他机器上。kafka使用的是会话机制来解决的。每台kafka服务器启动后会以会话的形式把自己注册到zookeeper服务器上,一旦该服务器运转出现问题,与zookeeper的会话便不能维持从而超时失效,此时kafka会选举出一台新的服务器赖万全代替这台服务器继续提供服务。

最后看看 伸缩性

伸缩性指的是: 向分布式系统系统中增加额外的计算资源时提升吞吐量的能力。

如果服务器是无状态的,状态的保存和管理交给专门的协调服务来做,比如 zookeeper ,那么整个集群的服务器之间就不需要再进行繁重的状态共享,这极大地降低了维护复杂度。

Kafka 正式采用了这一思想——每台kafka的服务器上的状态统一交由Zookeeper保管。而扩展kafka集群就很容易:启动一台新的kafka服务器即可

需要说明说明的一点是,kafka服务器并不是所有状态都不保存,他只是保存了很轻量级的内部状态,所以整个集群间维护状态一致性的代价很低。

------------------------------------------------------ 一条优美的分割线--------------------------------------------------------

来看看kafka的基本概念和术语

目前kafka最新的版本是 2.4。

broker、topic、partition、offset、replica、leader和follower

下面是Kafka的大致架构图:

生产者    ---------->      kafka集群 ----------------> 消费者

​                               ↑

​                        zookeeper服务器

Kafka服务器官方称呼为: broker。

先来说说Kafka的消息格式是啥样的?

消息由三部分组成: 消息头部、key 和 value

消息头: 包括CRC码、消息版本、属性、时间戳、键长度和消息体长度等信息。

Key: 消息键, 对消息做partition时使用,即决定消息被保存在某个topic下的那个partition。

Value: 消息体,保存实际的消息数据。

Timestamp: 消息发送时间戳。

kafka的Topic和Partition 到底是个什么东西?

Topic(主题): topic代表了一类消息,也可以认为消息被发送到的地方。 比如业务A使用一个topic, 业务B使用另外一个topic。 相当于 柴鸡蛋和茶叶蛋这样简单分下。

Partition(分区)🚦 一个Topic可以由多个partition组成,而kafka的partition是不可修改的有序消息序列。分区是物理层面的,用户是看不到的,用户不用管这些消息怎么取出来的,之所以做分区,主要是为了提高系统的吞吐量。

在这里插入图片描述

offset

一个(生产的)消息的写入offset位移值, 一个是消费者端的消费位移offset。他俩是不同的概念。

消费该partition的消费者位移会随着消费进度不断前移,不过终究不可能超过该分区的最新一条消息的位移

kafka的一条消息其实就是一个三元组: <topic, partition, offset> 三元组(tuple),通过该元组值能够在kafka集群中找到唯一对应的那条消息。

replica

kafka的冗余机制,备份多份日志,这些备份日志在kafka中被称为副本(replica),他们存在就是为了 防止数据丢失的。

leader和follower

leader提供对外服务,follower与leader保持同步,follower存在的目的就是用来充当leader的候补。

ISR(同步副本集合)

kafka为partition动态维护了一个replica集合,该集合中的所有replica保存的消息日志都与leader replica 保持同步状态。

记住,只有这个集合(ISR)中的replica才能被选为leader,也只有这个集合中的所有replica都接受到了同一条消息,Kafka才会将消息置于 “已提交” 状态,即认为这条消息发送成功。
【这里不要与producer端搞混,producer端的参数acks设置 0、all/-1 、1的情况,会在后面的文章补充。】

参考 kafka实战 p19

kafka使用场景

  • 消息传输
  • 网站行为日志跟踪
  • 日志收集
  • 流式处理
### Kafka与数数科技(ThinkingData)的关系分析 #### 背景介绍 Kafka 是一款分布式流处理平台,主要用于高吞吐量的消息传递和事件驱动架构。而数数科技(ThinkingData),是一家专注于数据分析解决方案的企业,其核心产品 ThinkingAnalytics (TA) 提供了一套完整的用户行为数据采集、存储和分析工具链。 两者虽然定位不同,但在实际应用场景中可以形成互补关系。以下是关于两者的集成方式及其使用场景的具体说明: --- #### 数据流动与集成机制 在现代企业级应用中,通常会采用 Kafka 作为中间件来实现数据的高效流转。数数科技的产品可以通过以下两种主要方式进行集成: 1. **通过 Kafka 进行数据采集** - 数数科技支持将用户的埋点数据或其他业务系统的日志数据发送到 Kafka 中[^2]。 - 此种模式下,Kafka 成为了一个高性能的数据缓冲区,能够有效应对大规模并发写入的需求。 2. **从 Kafka 导入至 TA 平台** - 思考数据提供了灵活的数据接入接口,允许开发者配置 Kafka Topic 的订阅规则,从而将 Kafka 中的数据导入到 TA 平台进行进一步加工和可视化展示[^3]。 - 在此过程中,Kafka 承担了消息队列的角色,保障了数据传输的一致性和可靠性。 --- #### 技术实现细节 下面是一个典型的 Kafka 和数数科技集成的技术流程图解及代码示例: ##### 流程概述 - 用户端的行为数据被收集并通过 SDK 发送到 Kafka 队列; - Kafka 将接收到的数据分发给下游消费者,其中包括数数科技的服务组件; - 数数科技对原始数据进行清洗、转换并存入自身的数据库引擎以备后续查询操作。 ##### 示例代码 假设我们需要设置一个简单Kafka 生产者程序向指定 topic 推送模拟的日志记录,则可以用如下 Python 实现: ```python from kafka import KafkaProducer import json producer = KafkaProducer(bootstrap_servers='localhost:9092', value_serializer=lambda v: json.dumps(v).encode('utf-8')) def send_log_event(event_data): producer.send('thinkingdata_topic', event_data) # Example usage event_example = {"userId": "user_123", "eventType": "page_view", "timestamp": "2023-07-01T12:00:00Z"} send_log_event(event_example) ``` 对于消费侧而言,在数数科技内部则可能运行着类似的逻辑去拉取上述推送过来的信息包,并完成必要的解析步骤后再入库保存起来待用作报表生成依据等功能用途之上。 --- #### 应用案例探讨 基于以上技术框架的实际落地实例包括但不限于以下几个方面: - 实时营销活动效果追踪:借助于快速响应特性使得品牌方能够在第一时间了解到广告投放所带来的转化率变化情况进而调整策略方向达到最优ROI目标值范围之内; - 游戏行业精细化运营决策支撑体系建立——通过对玩家在线时间分布规律总结提炼找出最佳促销时机窗口期安排等等措施提升整体收益水平的同时也增强了用户体验满意度指数得分表现良好态势持续发展下去的话未来前景十分广阔值得期待! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值