Kafka基本原理详解(超详细!)
⽬录
⼀、概念理解
Kafka是最初由Linkedin公司开发,是⼀个分布式、⽀持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最⼤的特性就是可以实时的处理⼤量数据以满⾜各种需求场景:⽐如基于hadoop的批处理系统、低延迟的实时系统、
storm/Spark流式处理引擎,web/nginx⽇志、访问⽇志,消息服务等等,⽤scala语⾔编写,Linkedin于2010年贡献给了Apache基⾦会并成为顶级开源 项⽬。
(1)产⽣背景
当今社会各种应⽤系统诸如商业、社交、搜索、浏览等像信息⼯⼚⼀样不断的⽣产出各种信息,在⼤数据时代,我们⾯临如下⼏个挑战:
1. 如何收集这些巨⼤的信息
2. 如何分析它
group by的用法及原理详解3. 如何及时做到如上两点
以上⼏个挑战形成了⼀个业务需求模型,即⽣产者⽣产(produce)各种信息,消费者消费(consume)(处理分析)这些信息,⽽在⽣产者与消费者之间,需要⼀个沟通两者的桥梁-消息系统。从⼀个微观层⾯来说,这种需求也可理解为不同的系统之间如何传递消息。
Kafka诞⽣
Kafka由 linked-in 开源
kafka-即是解决上述这类问题的⼀个框架,它实现了⽣产者和消费者之间的⽆缝连接。
kafka-⾼产出的分布式消息系统(A high-throughput distributed messaging system)
(2)Kafka的特性
⾼吞吐量、低延迟:kafka每秒可以处理⼏⼗万条消息,它的延迟最低只有⼏毫秒
可扩展性:kafka集⽀持热扩展
持久性、可靠性:消息被持久化到本地磁盘,并且⽀持数据备份防⽌数据丢失
容错性:允许集中节点失败(若副本数量为n,则允许n-1个节点失败)
⾼并发:⽀持数千个客户端同时读写
(3)Kafka场景应⽤
⽇志收集:⼀个公司可以⽤Kafka可以收集各种服务的log,通过kafka以统⼀接⼝服务的⽅式开放给各种consumer,例如hadoop、Hbase、Solr等。
消息系统:解耦和⽣产者和消费者、缓存消息等。
⽤户活动跟踪:Kafka经常被⽤来记录web⽤户或者app⽤户的各种活动,如浏览⽹页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常⽤来记录运营监控数据。包括收集各种分布式应⽤的数据,⽣产各种操作的集中反馈,⽐如报警和报告。
流式处理:⽐如spark streaming和storm
事件源
(4)Kafka⼀些重要设计思想
Consumergroup:各个consumer可以组成⼀个组,每个消息只能被组中的⼀个consumer消费,如果⼀个消息可以被多个consumer消费的话,那么这些consumer必须在不同的组。
消息状态:在Kafka中,消息的状态被保存在consumer中,broker不会关⼼哪个消息被消费了被谁消费了,只记录⼀个offset值(指向partition中下⼀个要被消费的消息位置),这就意味着如果consumer处理不好的话,broker上的⼀个消息可能会被消费多次。
消息持久化:Kafka中会把消息持久化到本地⽂件系统中,并且保持极⾼的效率。
消息有效期:Kafka会长久保留其中的消息,以便consumer可以多次消费,当然其中很多细节是可配置的。
批量发送:Kafka⽀持以消息集合为单位进⾏批量发送,以提⾼push效率。
push-and-pull :Kafka中的Producer和consumer采⽤的是push-and-pull模式,即Producer只管向broker push消息,consumer 只管从broker pull消息,两者对消息的⽣产和消费是异步的。
Kafka集中broker之间的关系:不是主从关系,各个broker在集中地位⼀样,我们可以随意的增加或删除任何⼀个broker节点。
负载均衡⽅⾯: Kafka提供了⼀个 metadata API来管理broker之间的负载(对Kafka0.8.x⽽⾔,对于0.7.x主要靠zookeeper来实现负载均衡)。
同步异步:Producer采⽤异步push⽅式,极⼤提⾼Kafka系统的吞吐率(可以通过参数控制是采⽤同步还是异步⽅式)。
分区机制partition:Kafka的broker端⽀持消息分区,Producer可以决定把消息发到哪个分区,在⼀个分区中消息的顺序就是Producer发送消息的顺序,⼀个主题中可以有多个分区,具体分区的数量是可配置的。分区的意义很重⼤,后⾯的内容会逐渐体现。
离线数据装载:Kafka由于对可拓展的数据持久化的⽀持,它也⾮常适合向Hadoop或者数据仓库中进⾏数据装载。
插件⽀持:现在不少活跃的社区已经开发出不少插件来拓展Kafka的功能,如⽤来配合Storm、Hadoop、flume相关的插件。
⼆、消息队列通信的模式
(1)点对点模式
如上图所⽰,点对点模式通常是基于拉取或者轮询的消息传送模型,这个模型的特点是发送到队列的消息被⼀个且只有⼀个消费者进⾏处理。⽣产者将消息放⼊消息队列后,由消费者主动的去拉取消息进⾏消费。点对点模型的的优点是消费者拉取消息的频率可以由⾃⼰控制。但是消息队列是否有消息需要消费,在消费者端⽆法感知,所以在消费者端需要额外的线程去监控。
(2)发布订阅模式
如上图所⽰,发布订阅模式是⼀个基于消息送的消息传送模型,改模型可以有多种不同的订阅者。⽣产者将消息放⼊消息队列后,队列会将消息推送给订阅过该类消息的消费者(类似)。由于是消费者被动接收推送,所以⽆需感知消息队列是否有待消费的消息!但是consumer1、consumer2、consumer3由于机器性能不⼀样,所以处理消息的能⼒也会不⼀样,但消息队列却⽆法感知消费者消费的速度!所以推送的速度成了发布订阅模模式的⼀个问题!假设三个消费者处理速度分别是8M/s、5M/s、2M/s,如果队列推送的速度为
5M/s,则consumer3⽆法承受!如果队列推送的速度为2M/s,则consumer1、consumer2会出现资源的极⼤浪费!
三、Kafka的架构原理
上⾯简单的介绍了为什么需要消息队列以及消息队列通信的两种模式,下⾯主⾓介绍Kafka。Kafka是⼀种⾼吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的⽹站中的所有动作流数据,具有⾼性能、持久化、多副本备份、横向扩展能⼒。。
(1)基础架构与名词解释
Producer:Producer即⽣产者,消息的产⽣者,是消息的⼊⼝。
Broker:Broker是kafka实例,每个服务器上有⼀个或多个kafka的实例,我们姑且认为每个broker对应⼀台服务器。每个kafka集内的broker都有⼀个不重复的编号,如图中的broker-0、broker-1等……
Topic:消息的主题,可以理解为消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。
Partition:Topic的分区,每个topic可以有多个分区,分区的作⽤是做负载,提⾼kafka的吞吐量。同⼀个topic在不同的分区的数据是不重复的,partition的表现形式就是⼀个⼀个的⽂件夹!
Replication:每⼀个分区都有多个副本,副本的作⽤是做备胎。当主分区(Leader)故障的时候会选择⼀个备胎(Follower)上位,成为Leader。在kafka中默认副本的最⼤数量是10个,且副本的数量不能⼤于Broker的数量,follower和leader绝对是在不同的机器,同⼀机器对同⼀个分区也只可能存放⼀个副本(包括⾃⼰)。
Message:每⼀条发送的消息主体。
Consumer:消费者,即消息的消费⽅,是消息的出⼝。
Consumer Group:我们可以将多个消费组组成⼀个消费者组,在kafka的设计中同⼀个分区的数据只能被消费者组中的某⼀个消费者消费。同⼀个消费者组的消费者可以消费同⼀个topic的不同分区的数据,这也是为了提⾼kafka的吞吐量!
Zookeeper:kafka集依赖zookeeper来保存集的的元信息,来保证系统的可⽤性。
(2)⼯作流程分析
(1)发送数据
我们看上⾯的架构图中,producer就是⽣产者,是数据的⼊⼝。注意看图中的红⾊箭头,Producer在写⼊数据的时候永远的leader,不会直接将数据写⼊follower!那leader怎么呢?写⼊的流程⼜是什么样的呢?我们看下图:
发送的流程就在图中已经说明了,就不单独在⽂字列出来了!需要注意的⼀点是,消息写⼊leader后,follower是主动的去leader进⾏同步的!producer采⽤push模式将数据发布到broker,每条消息追加到分区中,顺序写⼊磁盘,所以保证同⼀分区内的数据是有序的!写⼊⽰意图如下:
上⾯说到数据会写⼊到不同的分区,那kafka为什么要做分区呢?相信⼤家应该也能猜到,分区的主要⽬的是:
1. ⽅便扩展:因为⼀个topic可以有多个partition,所以我们可以通过扩展机器去轻松的应对⽇益增长的数据量。
2. 提⾼并发:以partition为读写单位,可以多个消费者同时消费数据,提⾼了消息的处理效率。
熟悉负载均衡的朋友应该知道,当我们向某个服务器发送请求的时候,服务端可能会对请求做⼀个负载,将流量分发到不同的服务器,那在kafka中,如果某个topic有多个partition,producer⼜怎么知道该将数据发往哪个partition呢?kafka中有⼏个原则:
1. partition在写⼊的时候可以指定需要写⼊的partition,如果有指定,则写⼊对应的partition。
2. 如果没有指定partition,但是设置了数据的key,则会根据key的值hash出⼀个partition。
3. 如果既没指定partition,⼜没有设置key,则会轮询选出⼀个partition。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。