Kafka简介

Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。它是一个分布式、支持分区的的、多副本,基于zookeeper协调的分布式消息系统。它的最大特性是可以实时的处理大量数据以满足各种需求场景:比如基于Hadoop的批处理系统、低延时的实时系统、storm/Spark流式处理引擎,web/nginx日志,访问日志,消息服务等等。最初由Linkedin公司开发,于2010年贡献给Apache基金会并成为顶级开源项目。

1 简介

1.1 Kafka的特性

高吞吐量、低延迟:Kafka每秒可以处理几十万消息,延迟最低只有几毫秒,每个消息主题topic可以分多个区,消费者组(consumer group)对消息分区(partition)进行消费。
可扩展性:kafka集群支持热扩展。
持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失。
容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)。
高并发:支持数千个客户端同时读写。

1.2 使用场景

日志收集:可以用kafka收集各种服务的日志,通过kafka以统一接口服务的方式开放给各种消费者,如hadoop,Hbase,Solr等。
消息系统:解耦生产者和消费者、缓存消息等。
用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页,搜索,点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常用来记录运营监控数据,包括收集各种分布式应用的数据,比如报警和报告等。
流式处理:比如spark streaming和storm。

1.3 名词解释

Broker:Kafka节点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。

Topic:主题,具有某种相同逻辑意义的一类消息,也是这类消息存放的目录,Kafka集群能够同时负责多个topic的分发。

Partition:分区,topic物理上的分组,一个topic可以分为多个partition,每个partition在逻辑上是一个有序的队列。在物理存储层面来看,每个Partition是一个append log文件,任何被发布到该partition的message都会被追加到log文件的尾部,message在log文件中的位置称为offset,offset唯一标记一条消息。
一个Topic的多个partitions,被分布在kafka集群中的多个server上。每个server(kafka实例)负责partitions中消息的读写操作。此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性.。
基于replicated方案,那么就意味着需要对多个备份进行调度。每个partition都有一个server为”leader”,leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader)。follower只是单调的和leader跟进,同步消息即可。

Producer:消息的生产者。

Consumer: 消息的消费者。

Consumer Group: 顾名思义,Consumer组成的Group。Partition中的每个message只能被同一个组中的某一个Consumer消费,如果一个message被多个consumer消费的话,这些consumer必须属于不同的组。也就是说一个Consumer Group要消费一个Topic的所有Partition的所有message,一个message不能被同一个组内的消费者重复消费。

2 设计思想与实现

Kafka设计的初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力。

2.1 持久性

kafka使用文件存储消息,这就直接决定kafka在性能上严重依赖文件系统的本身特性,且无论任何OS下,对文件系统本身的优化几乎没有可能。文件缓存/直接内存映射等是常用的手段。因为kafka是对日志文件进行append操作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数。

2.2 性能

需要考虑的影响性能点很多,除磁盘IO之外,还需要考虑网络IO,这直接关系到kafka的吞吐量问题,Kafka并没有提供太多高超的技巧。对于producer端,可以将消息buffer起来,当消息的条数达到一定阀值时,批量发送给broker。对于consumer端也是一样,批量fetch多条消息,不过消息量的大小可以通过配置文件来指定。其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略。压缩需要消耗少量的CPU资源,不过对于kafka而言,网络IO更应该需要考虑,可以将任何在网络上传输的消息都经过压缩。kafka支持gzip/snappy等多种压缩方式.

2.3 生产者

负载均衡:producer将会和Topic下所有partition leader保持socket连接,消息由producer直接通过socket发送到broker,中间不会经过任何”路由层”。事实上,消息被路由到哪个partition上,由producer客户端决定。比如可以采用”random”、”key-hash”、”轮询”等方式,如果一个topic中有多个partitions,那么在producer端实现”消息均衡分发”是必要的。

异步发送:将多条消息暂且在客户端buffer起来,并将他们批量的发送到broker,小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。不过这也有一定的隐患,比如说当producer失效时,那些尚未发送的消息将会丢失。

2.4 消费者

consumer端向broker发送”fetch”请求,并告知其获取消息的offset,此后consumer将会获得一定条数的消息。consumer端也可以重置offset来重新消费消息。

在JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端。不过在kafka中,采用了pull方式,即consumer在和broker建立连接之后,主动去pull(或者说fetch)消息。这种模式的优点:首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset),可以良好的控制消息消费的数量。

其他JMS实现,消息消费的位置要由provider保留,以便避免重复发送消息或者将没有消费成功的消息重发等。同时还要控制消息的状态。这就要求JMS broker需要太多额外的工作。在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制。可见kafka broker端是相当轻量级的。当消息被consumer接收之后,consumer可以在本地保存最后消息的offset,并间歇性的向zookeeper注册offset。由此可见,consumer客户端也很轻量级。

2.5 消息传送机制

Kafka中消息传输有几种模式:

(1) at most once:只管发送,发送出去就认为成功,不管消息的到达。

(2) at least once:消息至少发送一次,如果未能接受成功,可能会重发,直到接收成功。消费者fetch消息然后处理,并保存消息的offset。如果消息处理成功之后但是在保存offset时zookeeper异常导致保存操作未能执行成功,会导致下次再次fetch时可能获得上次已经处理过的消息,这就是“at least once”。

通常情况下,at least once是首选模式。

2.6 消息存储格式

在上文提到过,一个Topic可以认为是一类消息,每个Topic被分为多个partition,每个partition在存储层面是append log文件。示意图如下:

这里写图片描述
Kafaka文件存储中,同一个Topic有多个不同的partition, 每个partition为一个目录,partition命名规则为topic名称+有序序号,序号从0开始递增。而每个partition中又会分成多个segment,每个partition(目录)相当于一个巨型文件被分配到多个大小相等的segment。如下图所示:
这里写图片描述

Partition中的每个segment端的生命周期可以由服务器端配置参数决定。
Partition支持顺序读写。先看partition中的segment生成。
这里写图片描述

如图所示, 00000000000000000000.log文件是最早产生的文件,该文件达到1G(因为我们在配置文件里面指定的1G大小,默认情况下是500兆)之后又产生了新的0000000000000672348.log文件,新的消息会往这个新的文件中写入,依次类推。这样保证了只会往文件的末尾追加数据,即顺序写。

顺序读即消费者按顺序进行消费,但只能保证在这个partition中的顺序,而无法保证全局的顺序。举例说明,消费者产生了100条消息,假如只有一个partition,则产生的消息是顺序写入的,消费的时候也可以按照顺序消费。而当partition有多个的时候,单个partition上的消息是有序的,但从全局看是无序的。

Segment的命名规则如下:
这里写图片描述
从上图可以看出,segment文件名是第一条消息的offset,这样消费时根据offset来获取消息也是很容易的,根据二分查找法可以迅速定位消息所在的文件。可以看到每个log文件对应的还有一个index文件,定位到消息所在的文件之后,并不是直接去log文件获取消息,而是去索引文件中查找消息在log文件中的位置。索引文件中存储着大量的元数据,指向对应的数据文件中消息的偏移地址。index文件中并没有为数据文件中的每条消息都建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。
这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中,从而提高消费者读取消息的速度。

3 参考资料

(1)http://kafka.apache.org/documentation.html
(2)https://blog.csdn.net/ychenfeng/article/details/74980531
(3)https://www.cnblogs.com/likehua/p/3999538.html
(4)https://blog.csdn.net/imgxr/article/details/80130878
(5) http://www.cnblogs.com/jun1019/p/6256514.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值