你们好,我是 kafka, 可能不少人都据说过我,知道我是 2011 年出生在 LinkedIn 的, 从那会儿到如今个人功能愈加强大了。做为一个优秀而又完整的平台,你能够在我上面冗余地存储巨大的数据量,我有一个具备高吞吐量 (数百万 / 秒) 的消息总线,你能够在这上面对通过个人数据进行实时流处理。 若是你认为我就只有上面的这些特色的话,那么你真的是太肤浅了。html
上面虽说的很好,可是并未触及到个人核心,这里我给你几个关键字:分布式,水平可扩展,容错,提交日志。java
上面这些抽象的词语,我会一一解释它们的含义,并告诉大家我是如何工做的。git
心里独白: 原本我是想要以第一人称来写这篇文章的,可是我发现我只能写出上面的了,再多的我就憋不出来了,因而我决定不要为难本身,仍是用用第三人称写吧 (写做的功底仍然须要锻炼)github
分布式系统由多个运行的计算机系统组成,全部这些计算机在一个集群中一块儿工做,对终端用户来说只是一个单一节点。 redis
kafka也是分布式的,由于它在不一样的节点(又被称为broker)上存储,接受以及发送消息,这样作的好处是具备很高的可扩展性和容错性。sql
在这以前,先看看什么是垂直可扩展,好比你有一个传统的数据库服务器,它开始过分负载,解决这个问题的办法就是给服务器加配置(cpu,内存,SSD),这就叫作垂直扩展。可是这种方式存在两个巨大的劣势数据库
水平可扩展就是经过添加更多的机器来解决一样的问题,添加新机器不须要停机,并且集群中也不会对机器的数量有任何的限制。问题在于并不是全部系统都支持水平可伸缩性,由于它们不是设计用于集群中(集群中工做更加复杂)。apache
非分布式系统中容易最致命的问题就是单点失败,若是你惟一的服务器挂掉了,那么我相信你会很崩溃。数组
而分布式系统的设计方式就是能够以配置的方式来允许失败。在5个节点的kafka集群中,你仍然能够继续工做即便其中两个节点挂掉了。 须要注意的是,容错与性能直接相关,你的系统容错程度越高,性能就越差。缓存
提交日志(也被称为预写日志或者事物日志)是仅支持附加的持久有序数据结构,你没法修改或者删除记录,它从左往右读而且保证日志的顺序。
是的,从不少方面来说,这个数据结构就是kafka的核心。这个数据结构的记录是有序的,而有序的数据能够确保咱们的处理流程。这两个在分布式系统中都是及其重要的问题。
kafka实际上将全部消息存储到磁盘并在数据结构中对它们进行排序,以便利用顺序磁盘读取。
这两点有着巨大的优点, 由于数据大小与性能彻底分离。不管你的服务器上有100KB仍是100TB的数据,Kafka都具备相同的性能
应用程序(producer)发送消息(record)到kafka服务器(broker),这些消息会被其余应用程序(consumer)所处理,这些消息存储在主题(topic)中,而且消费者订阅该主题以接收新消息。是否是感受很像你平时写的代码——生产者消费者模式。
随着主题变得很是大,它们会分红更小的分区(partition),以得到更好的性能和可伸缩性(好比存储了用户相互发送的消息,你能够根据用户名的第一个字母来进行拆分)。Kafka保证分区内的全部消息都按照它们的顺序排序,区分特定消息的方式是经过其偏移量(offset),你能够将其视为普通数组索引,即为分区中的每一个新消息递增的序列号。
kafka遵照着愚蠢的broker和聪明的consumer的准则。这意味着kafka不会跟踪消费者读取了哪些记录并删除它们,而是会将它们存储必定的时间(好比1天,以log.retention开头的来决定日志保留时间),直到达到某个阈值。消费者本身轮询kafka的新消息而且告诉它本身想要读取哪些记录。这容许它们按照本身的意愿递增/递减它们所处的偏移量,从而可以重放和从新处理事件。
须要注意的是消费者是属于消费者组的,消费者组有一个或多个消费者。为了不两个进程读取一样的消息两次,每一个partition只能被一个消费者组中的一个消费者访问。
正如我以前提到的,kafka其实是将全部记录存储到硬盘而不在RAM中保存任何内容。你想知道这个如何作出这个选择的,其实这背后有不少优化使得这个方案可行。
全部这些优化都使Kafka可以以接近网络的速度传递消息。
咱们来谈谈Kafka如何实现容错以及它如何在节点之间分配数据。
为了使得一个borker挂掉的时候,数据还能得以保留,分区(partition)数据在多个broker中复制。
在任什么时候候,一个broker拥有一个partition,应用程序读取/写入都要经过这个节点,这个节点叫作----partition leader。它将收到的数据复制到N个其余broker,这些接收数据的broker叫作follower,follower也存储数据,一旦leader节点死掉的时候,它们就准备竞争上岗成为leader。
这能够保证你成功发布的消息不会丢失,经过选择更改复制因子,你能够根据数据的重要性来交换性能以得到更强的持久性保证
对生产者/消费者对分区的写/读请求,它们须要知道分区的leader是哪个,对吧?这个信息确定是能够获取到的,Kafka使用zookeeper来存储这些元数据。
Zookeeper是一个分布式键值存储。它针对读取进行了高度优化,但写入速度较慢。它最经常使用于存储元数据和处理群集的机制(心跳,分发更新/配置等)。
它容许服务的客户(Kafka broker)订阅并在发生变动后发送给他们,这就是Kafka如何知道什么时候切换分区领导者。ZooKeeper自己维护了一个集群,因此它就有很高的容错性,固然它也应该具备,毕竟Kafka很大程度上是依赖于它的。
zookeeper用于存储全部的元数据信息,包括但不限于以下几项:
那么produer/consumer是如何知道谁是partition leader的呢?
生产者和消费者之前经常直接链接ZooKeeper来获取这些信息,可是Kafka从0.8和0.9版本开始移除了这种强耦合关系。客户端直接从kafka broker直接获取这些元数据,而让kafka broker从zookeeper那里获取这些元数据。
更多zookeeper的讲解能够参考:漫画:什么是ZooKeeper?
在Kafka中,流处理器是指从输入主题获取连续数据流,对此输入执行某些处理并生成数据流以输出到其余主题(或者外部服务,数据库,容器等等).
什么是数据流呢?首先,数据流是无边界数据集的抽象表示。无边界意味着无限和持续增加。无边界数据集之因此是无限的,是由于随着时间推移,新的记录会不断加入进来。好比信用卡交易,股票交易等事件均可以用来表示数据流
咱们可使用producer/consumer的API直接进行简单处理,可是对于更加复杂的转换好比将流链接到一块儿,kafka提供了集成Stream API库
这个API是在你本身的代码中使用的,它并非运行在broker上,它的工做原理和consumer API相似,可帮助你在多个应用程序(相似于消费者组)上扩展流处理工做。
流的无状态处理是肯定性处理,其不依赖于任何外部条件,对于任何给定的数据,将始终生成与其余任何内容无关的相同输出。举个例子,咱们要作一个简单的数据转换----"zhangsan" ---> "Hello,zhangsan"
重要的是要认识到流和表实质上是同样的,流能够被解释称为表,表也能够被解释称为流.
流能够解释为数据的一系列更新,聚合后得结果就是表的最终结果,这项技术被称为事件溯源(Event Sourcing)
若是你了解数据库备份同步,你就会知道它们得技术实现被称为流式复制----将对表的每一个更改都发送报副本服务器.好比redis中的AOF以及Mysql中的binlog
Kafka流能够用相同的方式解释 - 当累积造成最终状态时的事件。此类流聚合保存在本地RocksDB中(默认状况下),被称为KTable。
能够将表视为流中每一个键的最新值的快照。以流记录能够生成表同样,表更新能够生成更改日志流。
咱们在java中经常使用的一些操做好比map()或者filter()是没有状态的,它不会要求你保留任何原始数据。可是现实中,大多数的操做都是有状态的(好比count()),由于就须要你存储当前累计的状态。
在流处理器上维护状态的问题是流处理器可能会失败!你须要在哪里保持这种状态才能容错?
一种简单的方法是简单地将全部状态存储在远程数据库中,并经过网络链接到该存储,这样作的问题是大量的网络带宽会使得你的应用程序变慢。一个更微妙但重要的问题是你的流处理做业的正常运行时间将与远程数据库紧密耦合,而且做业将不是自包含的(其余team更改数据库可能会破坏你的处理)。
那么什么是更好的办法呢? 回想一下表和流的二元性。这容许咱们将流转换为与咱们的处理位于同一位置的表。它还为咱们提供了一种处理容错的机制 - 经过将流存储在Kafka broker中。
流处理器能够将其状态保持在本地表(例如RocksDB)中,该表将从输入流(可能在某些任意转换以后)更新。当进程失败时,它能够经过重放流来恢复其数据。
你甚至能够将远程数据库做为流的生产者,有效地广播用于在本地重建表的更改日志。
一般,咱们不得不使用JVM语言编写流处理,由于这是惟一的官方Kafka Streams API客户端。 2018年4月,KSQL做为一项新特性被发布,它容许你使用熟悉的相似SQL的语言编写简单的stream jobs。你安装了KSQL服务器并经过CLI以交互方式查询以及管理。它使用相同的抽象(KStream和KTable),保证了Streams API的相同优势(可伸缩性,容错性),并大大简化了流的工做。
这听起来可能不是不少,但在实践中对于测试内容更有用,甚至容许开发以外的人(例如产品全部者)使用流处理,能够看看Confluent提供的这篇关于ksql的使用
正如咱们已经介绍的那样,Kafka容许你经过集中式介质获取大量消息并存储它们,而没必要担忧性能或数据丢失等问题。 这意味着它很是适合用做系统架构的核心,充当链接不一样应用程序的集中式媒体。Kafka能够成为事件驱动架构的中心部分,使你能够真正地将应用程序彼此分离.
Apache Kafka是一个分布式流媒体平台,天天可处理数万亿个事件。Kafka提供低延迟,高吞吐量,容错的发布和订阅管道,并可以处理事件流。咱们回顾了它的基本语义(生产者,代理,消费者,主题),了解了它的一些优化(pagecache),经过复制数据了解了它的容错能力,并介绍了它不断增加的强大流媒体功能。Kafka已经在全球数千家公司中大量采用,其中包括财富500强企业中的三分之一。随着Kafka的积极开发和最近发布的第一个主要版本1.0(2017年11月1日),有预测这个流媒体平台将会与关系数据库同样,是数据平台的重要核心。我但愿这篇介绍能帮助你熟悉Apache Kafka。
tech.meituan.com/2015/01/13/… shiyueqi.github.io/2017/04/27/… kafka.apache.org/documentati… docs.confluent.io/current/