首页 > 其他分享 >Kafka:用于日志处理的分布式消息系统

Kafka:用于日志处理的分布式消息系统

时间:2023-10-14 17:11:52浏览次数:42  
标签:消费者 一个 broker Kafka 消息 日志 分布式

周末躺不平,摆不烂,卷不动,随便读一篇paper吧
原文:Kafka: a Distributed Messaging System for Log Processing
作者:Jay Kreps / Neha Narkhede / Jun Rao
这三尊神就是当初在LinkedIn开发Kafka的大佬

摘要

日志处理已经成为了当下互联网公司数据管道(data pipeline)的重要组成部分。我们引入了Kafka——一个我们设计的用于低延迟的收集、传送大规模日志数据分布式消息系统。我们的系统包含了现存的日志聚合系统和消息系统的idea,并且适用于离线和在线日志消费场景。在Kafka中,我们做了一些现在还不太常见的但实用的设计选择来让我们的系统更加高效、易扩展。根据我们的实验结果,Kafka和当前的两个流行的消息系统相比有着优秀的性能。我们已经将Kafka投入生产一段时间了,它每天都要处理几百GB的新数据。

1. 介绍

在任何具有一定规模的互联网公司都有大量的日志数据被生成,这些数据通常包括:

  1. 用户活动事件,如:登陆、查看页面、点击、点赞、分享、评论以及查询搜索
  2. 每台机器上的操作指标,如:服务调用栈、调用延迟、错误以及系统指标:CPU、内存、网络、磁盘利用率

日志数据长期以来一直是一个用于跟踪用户粘度、系统利用率以及其他指标的分析组件。然而,互联网应用的最新趋势已使这些活动数据成为直接用于网站功能的生产数据管道的一部分,包括:

  1. 搜索相关度
  2. 由在活动流中的流行程度驱动的推荐
  3. 广告投送和报告
  4. 防止滥用行为的安全应用
  5. 聚合用户的状态更新以及动作,给它们的朋友看

这些日志数据的实时应用给数据系统带来了新的挑战,因为它们的规模是真实数据的几倍大,举个例子,搜索、推荐以及广告经常需要计算细粒度的点击率,这不仅仅是为每次用户点击生成日志记录,对于那些用户没点击的数据也要生成。每天,中国移动收集5到8TB的电话记录,Facebook手机大约6TB的用户活动事件。

很多早期的处理这种数据的系统依赖物理的从生产服务器中抓取数据来分析,而近几年,很多专用的分布式日志聚合系统出现了,比如Facebook的Scribe、Yahoo的Data Highway以及Cloudera的Flume。这些系统主要被设计成用于将日志数据加载到数据仓库或Hadoop以用于离线消费,在LinkedIn(一个社交网络网站),我们发现除了传统的离线分析外,我们还需要支持上面提到的大多数实时应用,并且延迟要不超过几秒钟。

我们构建了一个新的用于日志处理的消息系统——Kafka,它具有传统日志聚合系统和消息系统的优点。一方面,Kafka是分布式的,易于扩展,并且提供高吞吐量,另一方面,Kafka提供了一套类似消息系统的API,允许应用实时消费日志事件。Kafka已经开源,并且在LinkedIn投入生产超过6个月,它很好的简化了我们的基础设施,因为我们可以利用一个单独的软件处理全部类型日志数据的离线和在线消费。本篇paper的剩余部分组织如下:

  1. 第二节中我们探讨传统的日志系统和日志聚合系统
  2. 第三节中我们描述Kafka的结构以及它的关键设计原则
  3. 第四节中我们介绍LinkedIn中Kafka的应用
  4. 第五节中我们介绍Kafka的性能结果
  5. 第六节中我们讨论未来的工作以及结论

2. 相关工作

传统的企业级消息系统已经存在很长时间了,它们通常作为处理异步数据流的事件总线这一关键角色。然而,有一些原因使得它们不善于进行日志处理。首先,这些系统总是专注于提供一个丰富的传递保证,举个例子,IBM的Websphere MQ具有事务消息支持,允许程序原子的插入消息到多个队列中;JMS规范允许每一个独立的消息在消费后被确认(ack),这可能会出现消息顺序混乱的情况。这种递送保证对于收集日志数据来说有点过了,举个例子,偶然丢了少量的页面访问事件世界也不会炸了,这些我们不需要的特性增加了这些系统的API和底层实现的复杂性。第二,很多系统并不将高吞吐量作为它们的主要设计约束,比如,JMS没有允许生产者显式在一个请求中批量多条消息的API,这意味着每一个消息都需要一个完整的TCP/IP往返,这不符合我们的业务对吞吐量的需求。第三,这些系统缺乏分布式支持,没有一个简单的方式来分区并存储消息在多台机器上。最后,很多消息系统假设消息立即会被消费,所以,未消费消息的队列总是很小,当允许消息积累时,它们的性能就会显著下降,而在如数据仓库应用的离线消费场景中,偏向周期性的大负载而不是持续消费。

最近几年,很多专用的日志聚合系统被构建出来,Facebook使用的系统叫Scribe,每一个前端机器可以使用socket发送日志数据到一系列Scribe机器上,每一个Scribe机器聚合日志条目,周期性导出它们到HDFS或NFS设备上。Yahoo到Data Highway项目有着相似的数据流,一系列机器从客户端聚合事件,推分钟文件(roll out “minute” files),然后将它们添加到HDFS中。Flume是一个由Cloudera开发的相对新的日志聚合器,它支持可扩展的“pipes”和“sinks”,这使得传递日志数据非常灵活(make streaming log data very flexible),它也有很多集成的分布式支持。然而,大多数这种系统都是为了消费离线日志数据设计的,并且通常给客户端暴露了不必要的实现细节(比如“minute files”),另外,它们大多数使用推模型,broker将数据转发到consumer上。在LinkedIn,我们发现拉模型更加适合我们的应用,因为每一个消费者可以用它的最大速率来获取消息,并且可以避免消息推送超过它可以处理的速率。拉模型也让回溯消费者变得容易,我们将在3.2节的末尾讨论这个好处。

Yahoo Research开发了一个新的pub/sub系统,称作——HedWig。HedWig高度可扩展、高可用,提供强持久保证,然而,它主要用于存储数据商店的提交日志。

3. Kafka结构以及设计原则

由于现存系统的限制,我们开发了一个新的基于消息的日志聚合器——Kafka!我们首先介绍Kafka的基本概念,一个特定类型的消息流被定义成一个topic,一个生产者可以向一个topic发送消息,发送的消息被存储在一组被称做broker的机器上,消费者可以从broker订阅某一个或多个topic,通过从broker拉取数据来消费订阅的消息。

消息传递在概念上很简单,我们尝试让Kafka的API一样简单。我们不会展示实际的API,而是放一些样本代码来展示API如何被使用。producer的样本代码在下面,一个消息被定义成只包含字节的载荷,用户可以选择自己喜欢的序列化方式来编码消息,为了高效,用户可以在一个发布请求中发送一个消息集合。

img

为了订阅topic,一个消费者首先创建一个或多个topic的消息流,发送到这个topic上的消息将被均匀的分发到这些订阅流上。Kafka分发消息的细节将在3.2中介绍。每一个消息流提供一个迭代器接口,来获取被生产的消息的连续消息流。消费者迭代每一个流中的消息,处理消息的载荷。不同于传统的迭代器,消息流迭代器永远不会停下,如果当前没有更多消息可以消费,迭代器就会阻塞直到有消息发布到topic中。我们支持点对点到传送模型,为了多个消费者共同消费一个topic中所有消息的单独拷贝,就像发布/订阅模型一样,每一个consumer都会获得它独有的主题的copy。

img来获取连续的消息流

Kafka的总体设计如图1,因为Kafka天生就是分布式的,一个Kafka集群通常包含多个broker,为了负载均衡,一个topic被分割成多个partition,每一个broker存储一个或多个partition。多个生产者和消费者可以同时发布以及获取消息。在3.1节中,我们将介绍broker上的单一分区的布局以及我们的一些让分区访问更高效的设计选择。在3.2小节中,我们将介绍生产者和消费者如何在分布式场景下通过多个broker交互。我们将在3.3小节中讨论Kafka的递送保证。

img

3.1 单一Partition的效率

我们在Kafka中做了一些决策让系统更高效。

简单的存储:Kafka有一个非常简单的存储布局,topic的每一个分区对应一个逻辑日志。物理上,一个日志被实现成一系列大约相同大小的段文件(比如1GB),每次一个生产者发布一条消息到partition(后文称分区)中时,broker只是简单的将消息追加给给最后一个段文件。为了更好的性能,我们只在指定的可配置的数量的消息或指定的时间到达后才会将段文件刷新到磁盘,一个消息只有在它被刷到磁盘上后才会暴露给消费者。

与典型的消息系统不同,存储在Kafka中的消息没有明确的消息ID,取而代之的是,每一个消息可以通过它在日志中的逻辑offset被寻址,这避免了维护用于将message id映射到实际消息位置的辅助的,搜索密集的随机访问索引结构。我们的消息id是递增的,但不是连续的,为了计算下一条消息的id,我们必须用当前消息的id加上当前消息的长度,从现在开始,我们会交替的使用消息id和offset这两个术语。

消费者总是从一个特定的分区顺序的消费消息,如果一个消费者确认(ack)一个特定的消息offset,这意味着消费者已经接受到了该分区该offset之前的所有消息。消费者会提交异步的拉请求到borker,以为程序准备好要消费的数据缓冲区。每一个拉请求包含消费开始的消息offset,以及一个可接受的拉取字节数,每一个broker在内存中存储一个offset但排序集合,broker通过搜索offset列表来定位请求的消息所在的段文件,并将数据快发送给消费者。在消费者收到消息之后,它计算出下一个消息的偏移量,并在下一次请求中使用它。Kafka日志的布局以及内存中的索引结构在图2中描述,每一个方块展示了消息的offset。

img

高效的传输:我们非常消息的向Kafka传入和传出数据。之前,我们已经展示了生产者可以在一个请求中提交一个消息集合,即使端的消费者API每次迭代一条消息,在底层,每一个消费者的拉请求都获取至多到一个确切大小的多条消息,通常是几百KB。

另一个非常规的选择是,避免显式的在Kafka层面的内存中缓存消息,我们依赖底层的文件系统的page cache。避免双缓冲有两个主要好处——消息只在page cache中被缓存,即使broker进程重启缓存也还是热的;另外因为kafka没有在进程中缓存消息,所以对于GC只有很小的损耗,这让在基于VM的语言中的高效实现成为可能,最后,因为生产者和消费者只会顺序的访问段文件,消费者总是落后于生产者一小点儿,常规的操作系统缓存的启发式方法将非常有效(特别是write-through缓存和read-ahead)我们发现生产和消费都具有和数据大小相关的先行性能,最大可达几TB的数据。

另外,我们优化消费者的网络访问。Kafka是一个多消费者的系统,一个消息可能被不同的消费者程序消费多次,一个典型的从本地文件发送字节到远端套接字的方式引入如下几步:

  1. 从存储介质读数据到OS page cache
  2. 从page cache复制数据到应用buffer
  3. 复制应用buffer到另一个kernel buffer
  4. 发送kernel buffer到socket

这引入了4次数据复制以及2次系统调用,在Linux和其它Unix操作系统中,有sendfileAPI,可以直接从一个文件通道将数据传输到socket通道,这通常会避免在2和3步中引入的2次拷贝和1次系统调用。Kafka利用sendfileAPI高效的从broker传送日志段文件的字节到消费者。

无状态的broker:不像其它消息系统,Kafka中,每一个消费者消费了多少不存在于broker中,而是在消费者自己那里。这种设计减少了大量的复杂性和broker上的开销。然而,这让删除消息变得很棘手,因为broker不知道是否所有订阅者都已经消费了消息。Kafka通过使用基于时间的SLA做保留策略。一个消息若已经在broker上保留超过指定时间周期,它就会被自动删除,通常是7天。这个解决办法在实践中很棒。大多数消费者,包括离线的,都会在一天、一小时或实时的完成消费,Kafka不会因为很大的数据大小而降低性能的事实让这种持久保存可以实现。

这个设计有一个重要的好处,消费者可以任意回退到一个老的offset,并且重新消费数据。这违反了队列的常见约定,但提供了一个对很多消费者至关重要的特性。比如,如果消费者的应用逻辑中有一个异常,应用可以在错误被修复后重放特定的消息,这对于将ETL数据加载到我们的数据仓库或Hadoop系统尤为重要。另一个例子,消费过的数据可能周期性的被刷新到一个持久层中(比如一个全文检索器),如果消费者crash,未刷入的数据丢失了,在这种情况下,消费者可以检查最小的未刷新消息offset,并在重启时从那个offset重新消费。我们发现让消费者支持重放在拉模型中比推模型中更简单。

3.2 分布式协作

现在我们描述了生产者和消费者在分布式场景中的行为,每一个生产者可以投递一条消息到任意一个随机选择的分区或者通过分区key或一个分区函数选择。我们将要关注消费者如何与broker交互。

Kafka具有消费者组的概念,每一个消费者组包含一个或多个消费者,共同消费一系列订阅的topic,举个例子,每一个消息只会被传送到组内的一个消费者上。不同的消费者组独立的消费订阅消息的整个集合,并且消费者组之间不需要协作。同一个消费者组的消费者可以在不同进程或不同机器上,我们的目标是均匀的在消费之间分割在broker上存储的消息,而不需要引入过多的协作开销。

我们的第一个决策是让topic中的一个分区作为最小的并行单元。这意味着在任何时间,在一个分区上的所有消息只能被一个消费者组中的一个消费者消费,如果我们允许多个消费者同时消费一个单一分区,那么我们就必须协调谁消费了哪些消息,这需要锁以及状态维护的开销。相反,在我们的设计中,消费进程只需要在消费者重平衡负载时协调,这甚至是很少见的。为了负载真正的均衡,我们需要比每个组中的消费者个数多得多的分区,我们可以轻易的通过为一个topic分区做到这一点。

标签:消费者,一个,broker,Kafka,消息,日志,分布式
From: https://www.cnblogs.com/lilpig/p/17764156.html

相关文章

  • 【Django | 开发】面试招聘网站(增加csv,excel导出&企业域账号集成&日志管理功能)
    ......
  • 手把手教你分析IIS日志——IP访问次数,URI访问统计等
    配置IIS网站的日志下载日志分析工具https://gitee.com/tangdd369098655/open-network-disk解压打开选择文件指定分析规则(还可以自己写规则哦~~)运行规则进行分析今天就写到这里啦~小伙伴们,( ̄ω ̄( ̄ω ̄〃( ̄ω ̄〃)ゝ我们明天再见啦~~大家要天天开心哦欢迎大家指出文章需......
  • Redis分布式锁实现一直到Redis相关操作总结
    FreeRedis实现源码///<summary>///开启分布式锁,若超时返回null///</summary>///<paramname="name">锁名称</param>///<paramname="timeoutSeconds">超时(秒)</param>///<paramname="autoDelay">自动延长锁超时时......
  • Vector多行日志读取,解析
    官方记录:https://github.com/vectordotdev/vector/issues/2137目前只支持file、docker[sources.multiline_logs]type="file"include=["/opt/multiline.log"] [sources.multiline_logs.multiline] start_pattern='^<\d+>' mode=......
  • kafka 消费报错
    具体报错信息Traceback(mostrecentcalllast):File"/root/kafkatomysql.py",line166,in<module>consumer.commit()File"/usr/local/python3.9/lib/python3.9/site-packages/kafka/consumer/group.py",line527,incommitself._coo......
  • VictoriaLogs 要凭什么革了各家日志存储的命
    如果大家对时序指标的存储方案有些了解,那大概率会听过VictoriaMetrics,VictoriaMetrics号称Prometheus的升级版,在性能和成本方面也确实做得很好,如果是夜莺新用户,我都是推荐直接使用VictoriaMetrics来作为存储。前几天Victoria发布了VictoriaLogs,号称比ElasticSearch大幅......
  • Linux 日志文件查找命令
    Linux日志文件查找技巧一、tail命令简介下面列出一些常用的参数:-f:实时监控文件内容变化;-n:指定输出文件末尾的行数,默认为10行;-q:不显示文件名;-s:指定输出每行间隔的时间(秒数);-c:指定输出末尾的字节数;-v:显示详细的输出信息。使用示例查看文件file.txt......
  • 博学谷学习记录 自我总结 用心分享 | Kafka刨析
    基本概念Kafka 体系架构Kafka体系架构包括若干Producer、若干Broker、若干Consumer,以及一个 ZooKeeper 集群。在Kafka中还有两个特别重要的概念—主题(Topic)与分区(Partition)。Kafka中的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题(发送到Kafka集群......
  • xcode15在appstore上显示的更新日志-机翻
    swiftmacrosupportbringsinlineexpansionsandbreakpointdebugginginthesourceeditorGitstaginghelpscraftyournextcommitwithoutleavingyourcodeStringcatalogsstreamlinelocalizationwithasingleplacetoviewandeditstringsBookmarkshe......
  • Hadoop2伪分布式安装、分布式安装
    最近有观看我主讲的《Hadoop基础与演练》课程的同学问到Hadoop环境到底应该怎么安装。Hadoop的安装其实非常的简单,网上有很多教程,官网也有示例。但是可能部分同学对于linux不太熟悉,导致安装的时候会遇到各种问题,打击学习激情。本文就来详细的讲解一下如何配置Hadoop2的伪分布式环......