沉淀再出发:kafka初探
沉淀再出发:kafka初探
一、前言
从我们接触大数据开始,可能绕在耳边的词汇里面出现的次数越来越多的就包括kfaka了。kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力。kafka是一个分布式消息队列,具有高性能、持久化、多副本备份、横向扩展能力。生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。一般在架构设计中起到解耦、削峰、异步处理的作用。
二、kafka的使用
2.1、安装jre和zookeeper
在安装kafka之前我们需要安装jre和zookeeper,有了这两个环境,kafaka才能运行,对于java的安装,大家可以参考我以前的拙作,对于在Windows中安装zookeeper,我这里简单介绍一下。
我们从这个地方下载zookeeper,我们这里使用:http://mirrors.hust.edu.cn/apache/zookeeper/ ,最好下载稳定版本的。
之后我们将其解压到某个目录之下,进行相应的配置,就可以使用了,因此zookeeper也是开箱即用的。
将"zoo_sample.cfg"重命名为"zoo.cfg"并修改其中的内容,新建一个存储数据的文件夹,将路径进行修改:
这里我们要注意,如果我们的路径写成下面的样子,我们会发现运行之后,并不能正确的找到目录,而是在根目录下面创建了一个文件夹:
究其本质原因还是目录的写法有问题,系统把'\'当成了转义字符了!!!!!!
正确的写法应该是:
这样运行的时候就能正常找到目录了:
设置环境变量:
然后运行,可以发现已经成功启动了:
2.2、安装kfaka
首先我们在官网上下载kfaka,然后安装即可:
下载完成后,我们同样的解压,配置相应的参数,加入环境变量中:
打开server.properties,修改日志目录,我们自己创建一个文件夹即可:
对于连接,默认就是本地的:
同样加入环境变量中:
2.3、运行kfaka
- E:\kfaka_setup\kafka_2.-2.0.>.\bin\windows\kafka-server-start.bat .\config\server.properties
注意这里在Windows中,需要从bin目录下的windows目录运行程序:
2.4、创建topic
新启cmd,输入如下命令:
- kafka-topics.bat --create --zookeeper localhost: --replication-factor --partitions --topic zyr_test
2.5、创建生产者(producer)和消费者(consumer)
生产者:
- kafka-console-producer.bat --broker-list localhost: --topic zyr_test
消费者:
- kafka-console-consumer.bat --bootstrap-server localhost: --topic zyr_test --from-beginning
于是整个运行的流程是这样的:
其实这里面还有很多需要设置的东西,比如一些文件的配置等等,通过这些配置可以搭建我们的集群环境。
三、kafka的本质
3.1、那么什么是kafka?
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。
Kafka的特性:
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。
- 可扩展性:kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
Kafka的使用场景:
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 流式处理:比如spark streaming和storm
- 事件源
kafka对外使用topic的概念,生产者往topic里写消息,消费者从读消息。为了做到水平扩展,一个topic实际是由多个partition组成的,遇到瓶颈时,可以通过增加partition的数量来进行横向扩容,单个parition内是保证消息有序,每新写一条消息,kafka就是在对应的文件append写,所以性能非常高。 Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉去指定Topic的消息,然后进行业务处理。图中有两个topic,topic 0有两个partition,topic 1有一个partition,三副本备份。关于broker、topics、partitions的一些元信息用zk来存,监控和路由也都会用到zk。
3.2、专有名词的含义
- .producer:
- 消息生产者,发布消息到 kafka 集群的终端或服务。
- .broker:
- kafka 集群中包含的服务器。
- .topic:
- 每条发布到 kafka 集群的消息属于的类别,即 kafka 是面向 topic 的。
- .partition:
- partition 是物理上的概念,每个 topic 包含一个或多个 partition。kafka 分配的单位是 partition。
- .consumer:
- 从 kafka 集群中消费消息的终端或服务。
- .Consumer group:
- high-level consumer API 中,每个 consumer 都属于一个 consumer group,每条消息只能被 consumer group 中的一个 Consumer 消费,但可以被多个 consumer group 消费。
- .replica:
- partition 的副本,保障 partition 的高可用。
- .leader:
- replica 中的一个角色, producer 和 consumer 只跟 leader 交互。
- .follower:
- replica 中的一个角色,从 leader 中复制数据。
- .controller:
- kafka 集群中的其中一个服务器,用来进行 leader election 以及 各种 failover。
- .zookeeper:
- kafka 通过 zookeeper 来存储集群的 meta 信息。
3.3、生产者
创建一条记录,记录中一个要指定对应的topic和value,key和partition可选。 先序列化,然后按照topic和partition放进对应的发送队列中。kafka produce都是批量请求,会积攒一批,然后一起发送,不是调send()就进行立刻进行网络发包。
如果partition没填,key有填:按照key进行哈希,相同key去一个partition。(如果扩展了partition的数量那么就不能保证了);
如果partition没填,key没填:round-robin来选partition;
这些要发往同一个partition的请求按照配置,攒一波,然后由一个单独的线程一次性发过去。
当存在多副本的情况下,会尽量把多个副本,分配到不同的broker上。kafka会为partition选出一个leader,之后所有该partition的请求,实际操作的都是leader,然后再同步到其他的follower。当一个broker挂掉后,所有leader在该broker上的partition都会重新选举,选出一个leader,这里不像分布式文件存储系统那样会自动进行复制保持副本数。
然后这里涉及到两个细节:怎么分配partition,怎么选leader。关于partition的分配,还有leader的选举,总得有个执行者。在kafka中,这个执行者就叫controller。kafka使用zk在broker中选出一个controller,用于partition分配和leader选举。
partition的分配:
- 将所有Broker(假设共n个Broker)和待分配的Partition排序
- 将第i个Partition分配到第(i mod n)个Broker上 (这个就是leader)
- 将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上
- . producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader
- . producer 将消息发送给该 leader
- . leader 将消息写入本地 log
- . followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK
- . leader 收到所有 ISR 中的 replica 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset) 并向 producer 发送 ACK
3.4、broker 保存消息
存储策略:无论消息是否被消费,kafka 都会保留所有消息。有两种策略可以删除旧数据:
- . 基于时间:log.retention.hours=
- . 基于大小:log.retention.bytes=
需要注意的是,因为Kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高 Kafka 性能无关。
创建 topic
- . controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被创建,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。
- . controller从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个 partition:
- 2.1 从分配给该 partition 的所有 replica(称为AR)中任选一个可用的 broker 作为新的 leader,并将AR设置为新的 ISR
- 2.2 将新的 leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state
- . controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest
删除 topic:
- . controller 在 zooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被删除,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。
- . 若 delete.topic.enable=false,结束;否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire,controller 通过回调向对应的 broker 发送 StopReplicaRequest。
3.5、消费者
订阅topic是以一个消费组来订阅的,一个消费组里面可以有多个消费者。同一个消费组中的两个消费者,不会同时消费一个partition。换句话来说,就是一个partition,只能被消费组里的一个消费者消费,但是可以同时被多个消费组消费。因此,如果消费组内的消费者如果比partition多的话,那么就会有个别消费者一直空闲。
consumer API
kafka 提供了两套 consumer API:
- . The high-level Consumer API
- . The SimpleConsumer API
其中 high-level consumer API 提供了一个从 kafka 消费数据的高层抽象,而 SimpleConsumer API 则需要开发人员更多地关注细节。high-level consumer API 提供了 consumer group 的语义,一个消息只能被 group 内的一个 consumer 所消费,且 consumer 消费消息时不关注 offset,最后一个 offset 由 zookeeper 保存。使用 high-level consumer API 可以是多线程的应用,应当注意:
- . 如果消费线程大于 patition 数量,则有些线程将收不到消息
- . 如果 patition 数量大于线程数,则有些线程多收到多个 patition 的消息
- . 如果一个线程消费多个 patition,则无法保证你收到的消息的顺序,而一个 patition 内的消息是有序的
The SimpleConsumer API:如果想要对 patition 有更多的控制权,那就应该使用 SimpleConsumer API,比如:
- . 多次读取一个消息
- . 只消费一个 patition 中的部分消息
- . 使用事务来保证一个消息仅被消费一次
但是使用此 API 时,partition、offset、broker、leader 等不再透明,需要自己去管理。需要做大量的额外工作:
- . 必须在应用程序中跟踪 offset,从而确定下一条应该消费哪条消息
- . 应用程序需要通过程序获知每个 Partition 的 leader 是谁
- . 需要处理 leader 的变更
使用 SimpleConsumer API 的一般流程如下:
- . 查找到一个“活着”的 broker,并且找出每个 partition 的 leader
- . 找出每个 partition 的 follower
- . 定义好请求,该请求应该能描述应用程序需要哪些数据
- . fetch 数据
- . 识别 leader 的变化,并对之作出必要的响应
consumer group
kafka 的分配单位是 patition。每个 consumer 都属于一个 group,一个 partition 只能被同一个 group 内的一个 consumer 所消费(也就保障了一个消息只能被 group 内的一个 consuemr 所消费),但是多个 group 可以同时消费这个 partition。kafka 的设计目标之一就是同时实现离线处理和实时处理,根据这一特性,可以使用 spark/Storm 这些实时处理系统对消息在线处理,同时使用 Hadoop 批处理系统进行离线处理,还可以将数据备份到另一个数据中心,只需要保证这三者属于不同的 consumer group。
消费方式
consumer 采用 pull 模式从 broker 中读取数据。push 模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适当的速率消费消息。对于 Kafka 而言,pull 模式更合适,它可简化 broker 的设计,consumer 可自主控制消费消息的速率,同时 consumer 可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。
consumer delivery guarantee
如果将 consumer 设置为 autocommit,consumer 一旦读到数据立即自动 commit。如果只讨论这一读取消息的过程,那 Kafka 确保了 Exactly once。但实际使用中应用程序并非在 consumer 读取完数据就结束了,而是要进行进一步处理,而数据处理与 commit 的顺序在很大程度上决定了consumer delivery guarantee:
- .读完消息先 commit 再处理消息。这种模式下,如果 consumer 在 commit 后还没来得及处理消息就 crash 了,下次重新开始工作后就无法读到刚刚已提交而未处理的消息,这就对应于 At most once
- .读完消息先处理再 commit。 这种模式下,如果在处理完消息之后 commit 之前 consumer crash 了,下次重新开始工作时还会处理刚刚未 commit 的消息,实际上该消息已经被处理过了。这就对应于 At least once。
- .如果一定要做到 Exactly once,就需要协调 offset 和实际操作的输出。
经典的做法是引入两阶段提交。如果能让 offset 和操作输入存在同一个地方,会更简洁和通用。这种方式可能更好,因为许多输出系统可能不支持两阶段提交。比如,consumer 拿到数据后可能把数据放到 HDFS,如果把最新的 offset 和数据本身一起写到 HDFS,那就可以保证数据的输出和 offset 的更新要么都完成,要么都不完成,间接实现 Exactly once。(目前就 high-level API而言,offset 是存于Zookeeper 中的,无法存于HDFS,而SimpleConsuemr API的 offset 是由自己去维护的,可以将之存于 HDFS 中)总之,Kafka 默认保证 At least once,并且允许通过设置 producer 异步提交来实现 At most once。而 Exactly once 要求与外部存储系统协作,幸运的是 kafka 提供的 offset 可以非常直接非常容易得使用这种方式。
consumer rebalance
当有 consumer 加入或退出、以及 partition 的改变(如 broker 加入或退出)时会触发 rebalance。consumer rebalance算法如下:
- . 将目标 topic 下的所有 partirtion 排序,存于PT
- . 对某 consumer group 下所有 consumer 排序,存于 CG,第 i 个consumer 记为 Ci
- . N=size(PT)/size(CG),向上取整
- . 解除 Ci 对原来分配的 partition 的消费权(i从0开始)
- . 将第i*N到(i+)*N-1个 partition 分配给 Ci
在 0.8.*版本,每个 consumer 都只负责调整自己所消费的 partition,为了保证整个consumer group 的一致性,当一个 consumer 触发了 rebalance 时,该 consumer group 内的其它所有其它 consumer 也应该同时触发 rebalance。这会导致以下几个问题:
- 1.Herd effect:任何 broker 或者 consumer 的增减都会触发所有的 consumer 的 rebalance
- 2.Split Brain:每个 consumer 分别单独通过 zookeeper 判断哪些 broker 和 consumer 宕机了,那么不同 consumer 在同一时刻从 zookeeper 看到的 view 就可能不一样,这是由 zookeeper 的特性决定的,这就会造成不正确的 reblance 尝试。
- 3. 调整结果不可控:所有的 consumer 都并不知道其它 consumer 的 rebalance 是否成功,这可能会导致 kafka 工作在一个不正确的状态。
基于以上问题,kafka 设计者考虑在0.9.*版本开始使用中心 coordinator 来控制 consumer rebalance,然后又从简便性和验证要求两方面考虑,计划在 consumer 客户端实现分配方案。
3.6、消息投递语义
kafka支持3种消息投递语义:
- At most once:最多一次,消息可能会丢失,但不会重复
- 先获取数据,再commit offset,最后进行业务处理。
- 、生产者生产消息异常,不管,生产下一个消息,消息就丢了
- 、消费者处理消息,先更新offset,再做业务处理,做业务处理失败,消费者重启,消息就丢了
- At least once:最少一次,消息不会丢失,可能会重复
- 先获取数据,再进行业务处理,业务处理成功后commit offset。
- 、生产者生产消息异常,消息是否成功写入不确定,重做,可能写入重复的消息
- 、消费者处理消息,业务处理成功后,更新offset失败,消费者重启的话,会重复消费
- Exactly once:只且一次,消息不丢失不重复,只且消费一次(.11中实现,仅限于下游也是kafka)
- 首先要保证消息不丢,再去保证不重复。
- 生产者重做导致重复写入消息----生产保证幂等性
- 消费者重复消费---消灭重复消费,或者业务接口保证幂等性重复消费也没问题
- 由于业务接口是否幂等,不是kafka能保证的,所以kafka这里提供的exactly once是有限制的,消费者的下游也必须是kafka。
四、总结
通过对kfaka的学习,我们更加的明白了生产者和消费者这个模型,也就是发布订阅模型,对我们以后的学习和使用有着重要的意义。
参考文献:https://www.jianshu.com/p/d3e963ff8b70
https://www.cnblogs.com/xifenglou/p/7251112.html
沉淀再出发:kafka初探的更多相关文章
- 沉淀再出发:OpenStack初探
沉淀再出发:OpenStack初探 一.前言 OpenStack是IaaS的一种平台,通过各种虚拟化来提供服务.我们主要看一下OpenStack的基本概念和相应的使用方式. 二.OpenStack的框 ...
- 沉淀再出发:ELK使用初探
沉淀再出发:ELK使用初探 一.前言 ELK是Elasticsearch.Logstash.Kibana的简称,这三者是核心套件,但并非全部. 最近ElasticSearch可以说是非常火的一款开源软 ...
- 沉淀再出发:dubbo的基本原理和应用实例
沉淀再出发:dubbo的基本原理和应用实例 一.前言 阿里开发的dubbo作为服务治理的工具,在分布式开发中有着重要的意义,这里我们主要专注于dubbo的架构,基本原理以及在Windows下面开发出来 ...
- 沉淀再出发:jvm的本质
沉淀再出发:jvm的本质 一.前言 关于jvm,使用的地方实在是太多了,从字面意思上我们都能明白这也是一个虚拟机,那么其他的虚拟机都会用来运行别的操作系统的,而jvm却是实现了可以在不用的操作系统之上 ...
- 沉淀再出发:再谈java的多线程机制
沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...
- 沉淀再出发:用python画各种图表
沉淀再出发:用python画各种图表 一.前言 最近需要用python来做一些统计和画图,因此做一些笔记. 二.python画各种图表 2.1.使用turtle来画图 import turtle as ...
- 沉淀再出发:在python3中导入自定义的包
沉淀再出发:在python3中导入自定义的包 一.前言 在python中如果要使用自己的定义的包,还是有一些需要注意的事项的,这里简单记录一下. 二.在python3中导入自定义的包 2.1.什么是模 ...
- 沉淀再出发:java中的equals()辨析
沉淀再出发:java中的equals()辨析 一.前言 关于java中的equals,我们可能非常奇怪,在Object中定义了这个函数,其他的很多类中都重载了它,导致了我们对于辨析其中的内涵有了混淆, ...
- 沉淀再出发:web服务器和应用服务器之间的区别和联系
沉淀再出发:web服务器和应用服务器之间的区别和联系 一.前言 关于后端,我们一般有三种服务器(当然还有文件服务器等),Web服务器,应用程序服务器和数据库服务器,其中前面两个的概念已经非常模糊了,但 ...
随机推荐
- 安装Postgresql之后,创建用户 配置rails
登录 sudo su - postgres psql 1 创建Postgresql新用户,devpg是用户名,密码也是devpg, 不是超级管理员,拥有创建数据库权限,登录权限,继承拥有角色权限 cr ...
- 去掉img标签周围的空白
我们在页面布局的时候,明明已经去掉了所有标签的margin和padding,img标签周围依然会有空白,解决方法有以下几种: 1.给img标签设浮动: img{ float:left; } 2.将im ...
- Jquery Ajax 复杂json对象提交到WebService
在ajax的已不请求中,常常返回json对象.可以利用json.net给我们提供的api达到快速开发. 例子: using System;using System.Collections;using ...
- Virtualbox/Vagrant安装
它们分别是什么? VirtualBox: 号称是最强的免费虚拟机软件和VM类似. 不仅具有丰富的特色,而且性能也很优异. Vagrant: 是一个基于Ruby的工具,用于创建和部署虚拟化开发环境. 使 ...
- veloctiy入门
什么是velocity? velocity是一个基于Java的模板引擎.你可以使用它来预定义模板,并且对模板进行数据渲染,从而动态生成相应的文本.它如同JSP一样经常被使用在MVC分层架构当中,充当V ...
- (二)Apache服务器的下载与安装
PHP的运行必然少不了服务器的支持,何为服务器?通俗讲就是在一台计算机上,安装个服务器软件,这台计算机便可以称之为服务器,服务器软件和计算机本身的操作系统是两码事,计算机自身的操作系统可以为linux ...
- 初级Linux学习指南
1 学习书籍 1.1 入门书籍 <Linux系统命令及Shell脚本实践指南> 学习建议:该书所有章节详读一遍,同时结合实际操作,学习方法因人而异,作者本人学习该书时,每天上班前和下班后学 ...
- Java8实战Lambda和Stram API学习
public class Trader{ private String name; private String city; public Trader(String n, St ...
- 最简单应用的时间日期选择插件---My97DatePicker
最简单的应用:http://www.my97.net/dp/demo/resource/2.1.asp
- golang产生guid
labix.org/v2/mgo/bson 包虽然是MongoDB的golang实现,其中产生唯一ID的算法是独立的,不依赖MongoDB, 提炼这部分的代码如下: package main im ...