kafka深入理解

JMS:java message service   java 的消息服务

 

传递消息:如果是进程内部直接对象间传参就行

                  进程间就涉及到串行化了(ipc 进程间通信  rpc:远程过程调用)

 

Kafka  高吞吐量的分布式文件系统

 

如果a:有消息发给b 需要socket套接字  直接发送就可以,但这样耦合度很高,

必须保持消息的发送者和消息的接受者必须在线

 

现在的解决方式是找一个中间容器 将a生产的消息 驻留在中间容器中,当 消费者b上线了直接从中间容器中找消息就可以了

 

消息模型(JMS)有俩种方式

1.Queue :队列:P2P也就是点对点的 生产者生产出来的消息只能有一个消费者来消费

例如  : 邮件

2.topic: publish-subscribe 发布订阅模式

消息生产者 :发出的消息 相当于一个topic  消费者(可以有多个)可以订阅这个主题

 

Kafka就是JMS的变形

但是它没有了Queue的概念了

但它里面有 Group的概念了

 

速度快: 每秒上百兆

数据存放在磁盘上,并存有副本,有效防止数据丢失。

 

优点在于可以实时性处理  所以它可以在线处理数据,而不用离线处理数据

 

主题就是存放消息的地方,相当于一个容器

Kafka基于Scala语言来写的

Kafka基于zookeeper

Zk是一个协同服务,在customer和producter之间进行协同

在这里可以看一下kafka的配置文件在kafka的安装目录下有一个conf/zookpeer.properties

 

所以启动kafka必须启动zookeeper

2.启动kafka broke

通过命令zkCli.sh可以看到zk下的一些服务  必须在、/soft/kafka/conf下启动

 

查看kafka进程可以进到bin目录下 用jobs命令

测试kafka 可以用以下命令测试

先启动生产者  把消息放进去

然后启动消费者 消费信息

这里可以先  source 一下环境变量  要不然可能找不到

 

这说明  这个在消费者启动以前消息是驻留在broker上的,

可以启动zk的zkCli.sh查看消息是否驻留在zk上

 

可以查看 这里并没有zk的消息

 

查询某个服务的进程id 用

Ps | grep 服务名

 

到conf/server.properties下修改文件

 

 

 

在kafka中 zookeeper不保存producter的信息

 

 

消息发送到broker,所以broker需要读和写

 

列出所有可用主题

Kafka-topic.sh --list

 

通过主题可以查看主题下的信息

 

 

创建消息

和消费消息 在主题上

 

查看一个进程的id

启动zk的服务

这里可以用zkClient来进入到zookeeper中查看信息

看它里边有没有数据

退出zkClient用命令

quit

 

后边加zk的配置文件路径

 

放在后台运行

 

查看进程

这样就说明启动了

 

下面就可以启动1,和2的broker

首先为每个broker创建配置文件

然后在单个启动每个的broker

用这个命令可以先后台运行

 

 

然后用jobs查看进程

下一步可以创建主题 副本数是三

下一步可以查看主题的工作内容

下一步把消息发送给leder

这里消息发送了 但没有人消费

这里 创建一个消费者来消费

使用消费者消费前可以先source一下环境变量

这里可以测试一下容错性

把leder kill掉

现在再次运行消费者

这里消息还在   leder换成了 别的broker  用消费者还能消费

 

一些概念

Leader:负责读写指定分区的节点,每个leader节点都是随机选择出来的,

Replicas:副本,它是节点列表,存放节点副本(log文件)的节点列表,它不管是leader还是不是leader不管是active还是不是active

Isr:同步复制:

是副本的子集,当前处于活跃状态,还是和leader通信的

 

 从控制台发送消息和从控制台接受消息只是一个kafka的体验 其实没什么作用

 

实际是kafka tool

  它可以导入导出数据:它还可以和外部系统交互、

 

看怎么用:用脚本

Connect-standalone.sh 这里有三个参数

执行最下边的命令就可以把配置文件都启动起来

进到kafka配置中去${kafka}/config

 

这里找到sink出的数据用cat来查看是否成功

这里注意必须启动kafka和zk服务

 

下一步也可以启动一个消费者来查看消息

 

查看一下端口号;

这个连接器可以持续处理数据

可以一直向文件追加数据然后 输出文件一直在输出

 

 

Flum的数据沉到kafka中

可以读取kafka中的消息然后沉到hdfs上去

 

首先进到flume中去,然后touch了一个kafka的source

编辑kafka source为如下内容:

下面看一下hdfs

这里可以新建一个主题

下面测试一下

上边应该是a2

这时需要向主题中发送消息

这上边的主题应该改成test2

然后直接去hdfs上查看是否有数据

 

以上是kafka作为源头

 

下面是kafka作为sink

这是一个flume sink实现它可以发布消息到kafka topic

 

 

这里可以启用一个军刀

然后启动消费者来看它的数据

 

 

Kafka作为channl通道

 

 

 

在我们的server.properties配置文件下的内容是有我们的

Broker.id= 指定我们的broker的id

Listener= 指定我们的端口号

Log.dris= 指定我们的log本地目录

Zookeeper.connect= 指定我们的zk连接

 

启动kafka用命令kafka-server-start.sh 指定配置文件

创建主题  kafka-topic.sh –create –zookeeper v100:2181 –replication–factor 3 –partitions 1 –topic mytopic      这里主要是有指定我们的zk服务器,然后给定副本数,给定分区数,然后用—topic给定我们的主题.

查看主题aa下的详细信息  kafka-topic.sh –describe–zookeeper v100:2181 –topic aa

查看我们可用的主题  kafka-topic.sh –list 这样不行必须得指定zk

应该写成 kafka-topic.sh –list –zookeeper v100:2181

发布消息可以不用指定我们的zookeeper  消息直接发布到了broker但要指定topic 因为发布消息是发布到哪个主题上的

消费消息必须得指定我们的zookeeper,因为zk中注册了我们的broker的详细信息消费消息也需要指定主题,因为这里的主题是我们暂存消息的,然后还得加参数—form-beginning从开始消费数据

 

启动zk的服务器

Zookeer-server-start.sh 指定zk的配置文件就可以启动了

这里的kafka服务器其实就是我们的broker服务器

 

 

Kafka tool                    kafka工具

导入导出数据:

参数1:config/connect-standalone.properties 这里配置的是kafka的连接配置bootstrap.servers=localhost:9092

参 数 2:connect-file-source.properties   file=test.txt topic=connect-test 这里主要配置了这俩个信息 包含有我们的源头文件是哪个test.txt  然后指定我们的主题是谁 connect-tests

参 数 3:connect-file-sink.properties    file=test.sink.txt topics=connect-test这里主要配置了这俩个信息 包含有我们的sink文件是哪个test.sink.txt 然后指定我们的主题connect-test

bin/connect-standalone.shconfig/connect-standalone.properties connector1.properties[connector2.properties ...]

这个连接器可以持续的处理数据

 

 

Kafka的系统学习

 

 

Kafka消息的组织原理

1.       磁盘的重认识

当需要从磁盘读取数据时,要确定读的数据在哪个磁道,哪个扇区:

  1. 首先必须找到柱面,即磁头需要移动对准相应的磁道,这个过程叫做寻道,所耗费的时间叫寻道时间
  2. 然后目标扇区旋转到磁头下,这个过程耗费的时间叫做旋转时间

一个访问磁盘(读/写)完成过程由三个动作完成

a.       寻道(时间):磁头移动定位到指定磁道

b.       旋转延迟(时间):等待指定扇区从磁头下旋转经过

c.       数据传输(时间):数据在磁盘、内存与网络之间的实际传输

由于存储介质的特性,磁盘本身存取就比主存慢,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分之一甚至几千分之一

 

根据数据的局部性原理,有以下俩种方法

a.  预读或者提前读

b.  合并写--多个逻辑上的写操作合并成一个大的物理写操作中;

即采用磁盘顺序读写(就在当前磁道)(不需要寻道时间,只需要很少的旋转时间),比随见写操作大好多倍

         磁盘震裂:就是将多个磁盘合并成一个磁盘,比如每个磁盘有2t,一共5块磁盘,如果使用了磁盘震裂技术的话,我们的磁盘就有10t

 

这里kafka的特性是在单个分区中只能使用单个磁盘,所以使用磁盘震裂技术后可以使某个磁盘上的数据可以很大,

当然磁盘震裂的坏处是:如果我们有5个磁盘我们可以有5个并发的去读,读写并发度是5,但是磁盘震裂后,我们的读写并发读是1

 

注意:在kafka中最重要的一个思想就是,在磁盘中顺序写比随机写会快很多

 

一般的将数据从文件传到套接字的路径:

A.      操作系统将数据从磁盘读到内核空间的页缓存中

B.      应用将数据从内核空间读到用户空间的缓存中

C.      应用将数据写回内存空间的套接字缓存中

D.      操作系统将数据从套接字缓存写到网卡缓存中,以便将数据经网络发出

 

这样做明显是低效的,这里有四次拷贝,俩次系统调用,如果使用sendfile,俩次拷贝可以被避免;允许操作系统将数据直接从页缓存发送到网络上,优化后,只有最后一步将数据拷贝到网卡缓存中是需要的

 

Kafka写入的原理:

生产: 网络 à  pagecache à 磁盘

消费: 磁盘 à  网络

这里为甚么kafka生产的时候要经过pagecache呢,kafka的终极目标是生产一次消费多次,我生产一次数据后我放到pagecache这样一个缓存当中,消费者就可以从pagecache中读,而不用从磁盘中读,虽然磁盘的顺序读也很快但也比不上我们的在缓存中的快,如果pagecache满了后再放到磁盘

 

到这里kafka的俩个知识点:

A.      Kafka的顺序写远比随机读写快很多

B.      Kafka零数据拷贝,它不用拷贝到用户空间中

 

Kafka消息的删除原理

从最久的日志段开始删除(按日志段为单位进行删除),然后逐步向前推进,知道某个日志段不满足条件为止,删除条件

A.      满足给定的条件predicate(配置项log.retention.{ms,minutes,hours}(消息驻留的时间)和log.retenton.bytes(kafka中的消息的最大字节数)指定)时间一旦超过就认为是无效消息就会删除

B.      不是当前激活的日志端(kafka要保证当前目录下有一个日志段,如果就剩一个的话,即使时间超过也不会删除)

 

C.      大小不能小雨日志段的最小大小(配置项log.segment.bytes)也就是说我们的日志比我们设置的日志大小小的话,超过时间也不能被删除

 

Kafka的选主机制

1.       Leader选举算法非常多,大数据领域下常用的有以下俩种

A . ZAB(zookeeper使用);

B . Raft;

 

 

Kafka Server Reactor设计模型-认识java nio

 

Java NIO由以下几个核心部分组成

1.       Channels;

2.       Buffers;

3.       Selectors;

 

Channel(通道)和 java中的stream一样,用于传输数据的数据流,数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中

 

Selector允许单线程处理多个Channel,使用Selector,首先得向Selector注册Channel,然后调动它的select()方法。此方法会一直阻塞到某个注册的Channel有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子如新连接进来,数据接收等。

 

认识Linux epoll模型

1.epoll是一种IO多路复用技术,在linux内核中广泛使用,常见的三种IO多路复用技术为select模型、poll模型、epoll模型

 

Select模型需要轮询所有的套接字查看是否有事件发生

Poll模型和select模型原理一样,但是修正了select模型最大套接字限制的缺点:

Epoll模型修改主动轮询为被动通知,当有事件发生时,被动接收通知。所以epoll模型注册套接字后,主程序可以做其它事情,当事情发生时,接收到通知后再去处理。修正select模型的三个缺点

 

Kafka Socketserver是基于java nio开发的,采用了Reactor的模式,kafka Reactor的模式包含三种角色:

Acceptor

Processor

Handler

 

Kafka Reacator包含了一个Acceptor负责接收客户端请求,N个Processor线程负责读写数据(为每个Connection创建一个Processor去单独处理,每个Processor中均引用独立的Selector),M个Handler来处理业务逻辑。在Acceptor和Processor,Processor和Handler之间都有队列来缓冲请求

队列的作用有俩个:

1.      缓冲

2.      解耦

 

 

Acceptor的主要职责是监听客户端的连接请求,并建立和客户端的数据传输通道,然后为这个客户端指定一个Processor,它的工作就到此结束,这样它就可以去影响下一个客户端的连接请求了

 

Processor的主要职责是负责从客户端读取数据和将响应返回给客户端,它本身不处理具体的业务逻辑,每个Processor都有一个Selector,用来监听多个客户端,因此可以非阻塞地处理多个客户端的读写请求,Processor将数据放入RequestChannel的RequestQueue中和从ResponseQueue读取响应

 

Handler(Kafka.server.KafkaRequestHandler,kafka.server.KafkaApis)的职责是从RequestChannel中的RequestQueue取出Request,处理以后再将Response添加到RequestChannel中的ResponseQueue中

 

Kafka生产者编程模型

1.       同步生产模型

这里的发送成功确认是向我们的kafka集群确认,如果没有收到确认的话,那就一直发送,知道到达我们设置的最大次数,此时就结束了

如果在重发过程中有一次收到了确认消息,它就会发送下一条消息,当前这条消息就认为发送成功

 

2.       异步生产模型

同步生成模型和异步生产模型的对比

同步生产模型:

1.      低消息丢失率

2.      高消息重复率(由于网络原因,回复确认未收到)

3.      高延迟

 

异步生产模型:

1.      低延迟

2.      高发送性能

3.      高消息丢失率(无确认机制,发送端队列满)

 

在生产者的代码中,我们同步需要设定我们的ack确认机制,但是在我们的异步中,不可以设置,当然,你设置了也没有用

 

Java客户端参数调优

1.      message.send.max.retries:发送失败重试次数

2.      retry.backoff.ms:未接到确认,认为发送失败的时间

3.      producer.type:同步发送或者异步发送

4.      batch.num.messages:异步发送时,累计最大消息数;

5.      queue.buffering.max.ms:异步发送时,累计最大时间

 

这些配置可以从kafka的配置中查看

 

Kafka消息处理和集群维护

1.      Kafka Offset Minotor介绍

在生产环境需要集群高可用,所以需要对Kafka集群进行监控。Kafka OffsetMonitor可以监控Kafka集群的以下几项:

  1. Kafka集群当前存活的broker集合
  2. Kafka集群当前活动topic集合
  3. 消费者组列表
  4. Kafka集群当前consumenr按消费的offset lag 数(即当前topic当前分区目前有多少消息积压而没有及时消费)

  

 

kafka的再一次了解

脚本分析

1.       zookeeper-server-start.sh(这个命令需要zokeeper的配置文件)

USAGE: zookeeper-server-start.sh [-daemon]zookeeper.properties

2.       kafka-server-start.sh  (kafka服务器,其实是broker服务器,需要跟kafka的配置信息)

kafka-server-start.sh [-daemon]server.properties [--override property=value]*

在这个脚本中有调用了kafka-run-class.sh这个脚本

3.       kafka-topics.sh (这个命令都需要加入zk的参数,而没有broker的事情)

创建、删除、修改、描述主题

--create 需要加zookeeper参数

--delete

--describe 描述主题的详细信息

--list  需要加zookeeper参数

--zookeeper host1:port,host2:port,host3:port

所以说这个kafka-topics.sh 这个脚本是在和zk做交互,通过zk来查询到对应的broker,然后放到broker的路劲下,因为我们的主题是在broker路径下的

4.       kafka-console-producer.sh

从标准输入读取数据,发布消息到kafka中

--broker-list                                  //HOST:PORT1,HOST2:PORT2

--topic                                             //加主题,生产的消息发往那个主

5.       kafka-console-consumer.sh

从kafka中读取数据,输出到我们的标准输出中

--topic<tname>                                      //指定主题

--zookeeper..              //指定zk因为需要读取我们的topic的消息

--from-beginning           //从开始读取消息

kafka tool

导入导出数据:

$> connect-standalone.shconfig/ connect-standalone.properties

config/ connect-file-source.propertiesconfig/ connect-file-sink.properties

参数1:connect-standalone.propertieskafka连接进程的配置

参数2:connect-file-source.properties    [file=test.txt topic=connect-test]

参数3:connect-file-sink.properties      [file=test.sink.txt topics=connect-test]

运行这个命令需要启动我们的zk和broker

这个kafka tool可以支持持续服务,数据不断的向test.txt中追加,然后我们的test.sink.txt也会有数据不断的追加进去

 

在zk中存储了我们kafka中的信息,包含kafka的broker信息,topic信息,consumer信息,这里broker中有一个ids信息,这个是我们kafka存储在那个节点上,端口是多少等一些详细的信息,

 

 

Topic只是一个逻辑的概念。每个Topic都包含一个或多个Partition,不同Partition可位于不同节点。同时Partition在物理上对应一个本地文件夹,每个Partition包含一个或多个Segment,每个Segment包含一个数据文件和一个与之对应的索引文件。在逻辑上,可以把一个Partition当作一个非常长的数组,可通过这个“数组”的索引(offset)去访问其数据。

一方面,由于不同Partition可位于不同机器,因此可以充分利用集群优势,实现机器间的并行处理。另一方面,由于Partition在物理上对应一个文件夹,即使多个Partition位于同一个节点,也可通过配置让同一节点上的不同Partition置于不同的disk drive上,从而实现磁盘间的并行处理,充分发挥多磁盘的优势。

利用多磁盘的具体方法是,将不同磁盘mount到不同目录,然后在server.properties中,将log.dirs设置为多目录(用逗号分隔)。Kafka会自动将所有Partition尽可能均匀分配到不同目录也即不同目录(也即不同disk)上。

注:虽然物理上最小单位是Segment,但Kafka并不提供同一Partition内不同Segment间的并行处理。因为对于写而言,每次只会写Partition内的一个Segment,而对于读而言,也只会顺序读取同一Partition内的不同Segment。

Partition是最小并发粒度

如同《Kafka设计解析(四)- Kafka Consumer设计解析》一文所述,多Consumer消费同一个Topic时,同一条消息只会被同一Consumer Group内的一个Consumer所消费。而数据并非按消息为单位分配,而是以Partition为单位分配,也即同一个Partition的数据只会被一个Consumer所消费(在不考虑Rebalance的前提下)。

如果Consumer的个数多于Partition的个数,那么会有部分Consumer无法消费该Topic的任何数据,也即当Consumer个数超过Partition后,增加Consumer并不能增加并行度。

简而言之,Partition个数决定了可能的最大并行度。如下图所示,由于Topic 2只包含3个Partition,故group2中的Consumer 3、Consumer 4、Consumer 5 可分别消费1个Partition的数据,而Consumer 6消费不到Topic 2的任何数据。 

 

Kafka使用基于TCP的二进制协议。该协议定义了所有API的请求及响应消息。所有消息都是有长度限制的,并且由后面描述的基本类型组成。

客户端启动的socket连接,并且写入请求的消息序列和读回相应的响应消息。连接和断开时均不需要握手消息。如果保持你保持长连接,那么TCP协议本身将会节省很多TCP握手时间,但如果真的重新建立连接,那么代价也相当小。

客户可能需要维持到多个broker的连接,因为数据是被分区的,而客户端需要和存储这些分区的broker服务器进行通讯。当然,一般而言,不需要为单个服务端和单个客户端间维护多个连接(即连接池技术)。

服务器的保证单一的TCP连接中,请求将被顺序处理,响应也将按该顺序返回。为保证broker的处理请求的顺序,单个连接同时也只会处理一个请求指令。请注意,客户端可以(也应该)使用非阻塞IO实现请求流水线,从而实现更高的吞吐量。也就是说,客户可以在等待上次请求应答的同时发送下个请求,因为待完成的请求将会在底层操作系统套接字缓冲区进行缓冲。除非特别说明,所有的请求是由客户端启动,并从服务器获取到相应的响应消息。

服务器能够配置请求大小的最大限制,超过这个限制将导致socket连接被断开。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值