Kafka应用实践--应用、原理、部署、测试、协同Hadoop

Kafka简介

Kafka是基于发布-订阅模式的分布式流媒体系统,是一种高吞吐量的分布式发布订阅消息系统

技术特点:

  1. 海量日志数据处理,对于消息的处理效率非常高,即使是普通的硬件也支持每秒数百万的消息;
  2. 天然支持集群负载均衡,使用zookeeper进行分布式协调管理;
  3. 高性能指标:时间复杂度为O(1),常熟时间复杂度为TB级以上;
  4. 高吞吐量:单机10W/s消息处理,水平扩展;
  5. 数据处理:离线处理,实时处理;
  6. 不支持事务,有一定概率的消息丢失;

功能作用

  1. 解耦:将消息生产阶段和处理阶段拆分开,两个阶段相互独立各自实现自己的处理逻辑,通过Kafka提供的消息写入和消费接口实现对消息的连接处理。降低开发复杂度,提高系统性能;
  2. 高吞吐率:Kakfa通过顺序读写磁盘提供可以和内存随机读写相匹敌的读写速度,灵活的客户端API设计,利用Linux操作系统提供的"零拷贝"特性减少消息网络传输时间,提供端到端的消息压缩传输,对同一主题下的消息采用分区存储,Kafka通过诸多良好的特性利用廉价的机器可以轻松实现高吞吐率;
  3. 高容错、高可用:Kafka允许用户对分区配置多副本,Kafka将副本均匀地分配到各副本之间采用Leader-Follower机制同步消息,只有Leader对外提供读写服务,当Follower中选择一个Leader继续提供读写服务。
  4. 可扩展:理论上Kafka的性能随着Broker的增多而增多,增加一个Broker只需要为新增加的Broker设置一个唯一的编号,编写好配置文件后,Kafka通过zookeeper就能发现新的Broker;
  5. 峰值处理:例如秒杀系统、爆发式集中支付系统、推荐系统等都需要消息队列的介入,这类系统在某个时间点数据会爆发式增长,后台处理系统不能够及时处理峰值请求,如果没有消息队列的接入就会造成后台系统处理不及时,请求数据严重挤压,如此恶性循环最终导致系统崩溃。Kafka的接入能够使数据进行冗余存储,并保证消息顺序读写,相当于给系统接入了一个大的缓冲区,既能接收持续暴增的请求,又能根据后台系统的处理能力提供数据服务,进而提高各业务系统的峰值处理能力

应用场景

  1. 实时数据管道:可靠的传输数据,系统或者应用程序之间构建可靠的用语传输实时数据的管道
  2. 实时流媒体应用:实时对流数据进行转换或处理 spark streaming和storm
  3. 日志收集:收集各种服务的log,通过kafka以统一接口服务的方式开方法给各种consumer,例如hadoop,Hbase,Solr等
  4. 消息系统:解耦生产者和消费者、缓存消息等;
  5. 用户活动跟踪:用来记录web用户或者app用户的的各种信息,如浏览页面、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装到hadoop、数据仓库中做离线分析和挖掘。
  6. 运营指标:记录运营监控数据。包括手机各种分布式应用的数据,生产各种操作的集中反馈,比如警报和报告

原理介绍

     基本概念

  1.  Topic:特指Kafka处理消息源(feed of messages)的不同分类
  2.  Partition:Topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。pratition中的每条消息都会被分配一个有序的id(offset)
  3.  Message:消息,是通信的基本单位,每个produce可以向一个topic(主题)发布一些消息;
  4.  Producers:消息和数据生产者,向Kafka的一个topic发布消息的过程叫做producers;
  5.  Consumers:消息和数据消费者,订阅topics并处理其发布的消息的过程叫做consumers;
  6.  Broker:缓存代理,Kafka集群中的一台或多台服务器统称为Broker;

高吞吐的实现

  1. 磁盘存储顺序读写:磁盘的顺序读写性能比内存随机读写的性能还高
  2. PageCache:Kafka设计中采用页缓存的方式缓存消息,避免了消息丢失的风险
  3. 零拷贝:采用Sendfile技术,通过零拷贝发送数据实现高效数据传输,取消了内核与应用程序缓存之间的传输,数据从磁盘读取出来后,直接从内核缓冲区发送到NIC缓冲区,大大简化了数据传输流程,提高数据传输效率(磁盘-->内核缓冲区-->NIC缓冲区)
  4. 多分区:将主题数据分成多个分区存储,每一个分区对应Consumer的一个处理线程,分区的数量选择要根据使用场景,设置合理的分区树,否则线程启动过多,占用资源无法释放,反而会增加系统负担降低性能
  5. 客户端优化:ACK机制、批量发送、端到端批量数据压缩

高可用的实现

  1. 多分区多副本
  2. Leader选举:Controller选举、分区Leader选举

消息传输流程

Producer生产者:向Kafka集群发送消息,在发送消息之前,会对消息进行分类,即Topic

Topic主题:通过对消息指定主题可以将消息分类,消费者可以只关注自己需要的Topic中的消息

Consumer消费者:消费者通过与Kafka集群建立长连接的方式,不断地从集群中拉取消息,然后对这些消息进行处理

消息传输流程

 

 

Kafka服务器消息存储策略

创建一个Topic时,同时可以指定分区(partitions),分区数越多,其吞吐量也越大,但是需要的资源越多,同时也会导致更高的不可用性,Kafka在接收到生产者发送的消息之后,会根据均衡策略将消息存储到不同的分区中。

在每个分区中,消息以顺序存储,最晚接收的消息会最后被消费

与生产者的交互

生产者在向Kafka集群发送消息的时候,可以通过制定分区来发送到制定的分区中

也可以通过指定均匀策略来讲消息发送到不同的分区中

如果不指定,就会采用默认的随机均衡策略,将消息随机的存储到不同的分区中

 

与消费者的交互

在消费者消费时,Kafka使用offset来记录当前消费的位置

在Kafka的设计中,可以有多个不同的group来同时消费同一个topic下消息,如果有两个不同的group同时消费,他们的消息的记录位置offset各不相同,不互相干扰

对于一个group而言,消费者的数量不应该多于分区的数量,因为一个group中,每个分区至多只能绑定一个消费者上,即一个消费者可以消费多个分区,一个分区只能给一个消费者消费。

因此若一个group钟的消费者数量大于分区数量的话,多余的消费者将不会收到任何消息。

安装部署说明

Kafka使用scala编写的运行与jvm虚拟机上的程序,可以运行在Windows也可以运行在linux服务器,新版的Kafka已经内置了zookeeper环境,可以直接安装即可

配置Kafka目录下的config目录

broker.properties配置

##broker标识,id为正数,且全局不得重复
broker.id=1
##日志文件保存的目录
log.dirs=/kafka/logs
##broker需要使用zookeeper保存meata信息,因此broker为zk_client
##此处为zookeeper集群的connectString,后面可以跟上path
##比如hostname:port/chroot/kafka
##需要注意,path的全路径需要有自己来创建(使用zookeeper脚本工具)
zookeeper.connect=hostname1:port1,hostname2:prot2
##用来监听连接的端口,producer或consumer将在此端口建立连接
prot=6667
##指定broker实例绑定的网络接口地址
host.name=
##每个partition的备份个数,默认为1,建议根据实际条件选择
##此处值大意味着消息各个server上同步需要的延迟较高
num.partition=2
##日志文件中每个segment文件的尺寸,默认为1G
##log.segment.bytes=1024*1024*1024
##滚动生成新的segment文件的最大时间
##log.roll.hours=24*7
##segment文件保留的最长时间,超时将被删除
##log.retention.hours=24*7
##partition中buffer中,消息的条数,达到阀值,将触发flush到磁盘
log.flush.interval.message=10000
##消息buffer的时间,达到阀值,将触发flush到磁盘
log.flush.interval.ms=3000
##partition leader等待follower同步消息的追到时间,
##如果超时,leader将follower移除同步列表
replica.lag.time.max.ms=10000
##允许follower落后的最大消息条数,如果达到阀值,将follower移除同步列表
##replica.lag.max.message=4000
##消息的备份的个数
num.replica.fetchers=1

consumer.properties消费者配置,这个配置文件配置开启的消费者

##当前消费者的group名称,需要指定
group.id=
##consumer作为zookeeper client,需要通过zk保存一些meta信息,此处为zk_connectString
zookeeper.connect=hostname1:port,hostname2:port2
##当前consumer的标识,可以设定,也可以有系统生成
consumer.id=
##获取消息的最大尺寸,broker不会像consumer输出大于此值的消息chunk
##每次feth将得到多条消息此值为总大小
fetch.messages.max.bytes=1024*1024
##当consumer消费一定量的消息之后,将会自动向zookeeper提交offset信息
注意offset信息并不是每消费一次消息,就像zk提交一次,而是现在本地保存,并定期提交
auto.commit.enable=true
##自动提交的时间间隔,默认为1分钟
auto.commit.interval.ms=60*1000

producer.properties生产者配置,这个配置文件用于配置开启生产者

##对于开发者而言,需要通过broker.list指定当前producer需要关注的broker列表
##producer通过和每个broker连接,并获取partitions
##如果某个broker连接失败,将导致此上的partitions无法继续发布消息
##格式:host1:port,host2:port2,其中host:port需要参考broker配置文件
##对于producer而言没有使用zookeeper自动发现broker列表
metadata.broker.list=
##producer接收信息ack的时候,默认为0
##0:producer不会等待broker发送ack
##1:当leader接收到消息之后ack
##2:当所有的follower都同步消息成功后发送ack
requeset.required.acks=0
##producer消息发送的模式,同步或异步
##异步意味着消息将会在本地buffer,并适时批量发送
##默认为sync,建议async
producer.type=sync
##消息序列化类,将消息实体转换成byte[]
serializer.class=kafka.serizlizer.DefaultEncoder
key.serializer.class=${serializer.class}
##partition路由类,消息在发送时将根据实例的方法获得partition索引号
partitioner.class=kafka.producer.DefaultPartitioner

##消息压缩算法,none,gzip,snappy
compression.codec=none
##消息在producer端buffer的条数,仅在producer.type=async下有效
##batch.num.message=200

server.properties Kafka服务器配置,次配置文件用来配置Kafka服务器,基础配置:1 broker.id申明当前Kafka服务器在集群中的唯一ID,需配置为integer,并且集群中的每一个Kafka服务器的id都是唯一的;2 listeners 申明此Kafka服务器需要监听的端口号,默认会使用localhost,远程服务器上运行需要配置,例如:listeners=PLAINTEXT://192.168.180.128:9092,并确保服务器的9092端口能够访问;3 zookeeper.connnect申明Kafka所连接的zookeeper的地址,需配置为zookeeper的地址,高版本的Kafka自带zookeeper,zookeeper.connect=localhost:2181

Docker安装部署Kafka

下载镜像

docker pull wurstmeister/zookeeper

docker pull wurstmeister/kafka

 

启动镜像

docker run -d --name zookeeper --p 2181:2181 -t wurstmeister/zookeeper

docker run -d --name kafka -p 9092:9092 --link zookeeper:zk --e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 --e KAFKA_ADVERTISED_HOST_NAME=localhost -e KAFKA_ADVERTISED_PORT=9092 -e HOST_IP=localhost -e KAFKA_BROKER_ID=1 -e ZK=zk -t wurstmeister/kafka  

 

测试

测试发送消息

docker ps

进入容器内部
docker exec it ${container_id} /bin/bash

进入kafka默认目录
cd opt/kafka_2.11-0.10.1.1/

 

创建主题

bin/kafka-topics.sh --creare --zookeeper zookeeper:2181 --replication-factor 1 --partition 1--topic mykafka

 

运行一个消息生产者,指定topic

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic mykafka

 

打开一个新的ssh,进入相同的目录,运行一个消息消费者,指定topic

bin/kafka-console-consumer.sh --zookeeper zookeeper:2181 --topic mykafka --form-beginning

 

测试发送消息

在生产者框中输入信息,在消费者框中可以接收消息

 

协同Hadoop

SparkStreaming从kafka获取数据

    Spark提供两种方法从kafka拿数据:

        1)Receiver方式:

                a、其实是通过zookeeper连接kafka队列;

               b、kafka中topic的partition数目与spark rdd中partition数目没有关系,增加topic的partition数,不会增加spark的处理并行度,仅仅是增加获取数据的Receiver;

                c、Receiver方式,树据都存储在Spark Executor的内存中,一旦spark停止运行(如机器崩溃),数据将无法恢复,只有则不开启WAL(write ahead log)机制,及预写日志的方式同步将数据写到分布式系统中,虽然可以恢复,但是效率低,每份数据需要复制两份;

    2)Director方式:

             a、这是spark1.3引进的新方法,直接从kafka的broker分区中读数据,跳过zookeeper,也没有receiver;

           b、kafka中topic的partition与spark rdd的partition一一对应,也就是说增加kafka中topic的partition数目,就增加了spark的并行处理度;

              c、该方式不会复制两份数据,因为kafka本身就有高可用,kafka会做数据备份,宕机后,可以利用kafka副本恢复;

 

补充:这种方式数据的offset存在spark的checkpoint中,不然每次重启spark,就会从kafka的最新offset位置读数据,会丢数据;所以,spark需要设置checkpoint,在创建JavaStreamingContext时,建议使用

JavaStreamingContext.getOrCreate(sparkChkDir,newStreamContextFunction());

//第一个参数:checkpoint路径;第二个参数,返回新的JavaStreamingContext;

及如果checkpoint存在就从checkpoint得到sparkStreamingContext,不存在就创建sparkStreamingContext;

转载于:https://my.oschina.net/yangty2017/blog/1806129

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值