Kafka集群搭建
Kafka初识
Kafka使用背景
在我们大量使用分布式数据库、分布式计算集群的时候,是否会遇到这样的一些问题:
我们想分析下用户行为(pageviews),以便我们设计出更好的广告位
我想对用户的搜索关键词进行统计,分析出当前的流行趋势
有些数据,存储数据库浪费,直接存储硬盘效率又低
这些场景都有一个共同点:
数据是由上游模块产生,上游模块,使用上游模块的数据计算、统计、分析,这个时候就可以使用消息系统,尤其是分布式消息系统!
Kafka的定义
What is Kafka:它是一个分布式消息系统,由linkedin使用scala编写,用作LinkedIn的活动流(Activity Stream)和运营数据处理管道(Pipeline)的基础。具有高水平扩展和高吞吐量。
Kafka和其他主流分布式消息系统的对比
定义解释:
Java 和 scala都是运行在JVM上的语言。
erlang和最近比较火的和go语言一样是从代码级别就支持高并发的一种语言,所以RabbitMQ天生就有很高的并发性能,但是 有RabbitMQ严格按照AMQP进行实现,受到了很多限制。kafka的设计目标是高吞吐量,所以kafka自己设计了一套高性能但是不通用的协议,他也是仿照AMQP( Advanced Message Queuing Protocol 高级消息队列协议)设计的。
事物的概念:在数据库中,多个操作一起提交,要么操作全部成功,要么全部失败。举个例子, 在转账的时候付款和收款,就是一个事物的例子,你给一个人转账,你转成功,并且对方正常行收到款项后,这个操作才算成功,有一方失败,那么这个操作就是失败的。
对应消在息队列中,就是多条消息一起发送,要么全部成功,要么全部失败。3个中只有ActiveMQ支持,这个是因为,RabbitMQ和Kafka为了更高的性能,而放弃了对事物的支持 。
集群:多台服务器组成的整体叫做集群,这个整体对生产者和消费者来说,是透明的。其实对消费系统组成的集群添加一台服务器减少一台服务器对生产者和消费者都是无感之的。
负载均衡,对消息系统来说负载均衡是大量的生产者和消费者向消息系统发出请求消息,系统必须均衡这些请求使得每一台服务器的请求达到平衡,而不是大量的请求,落到某一台或几台,使得这几台服务器高负荷或超负荷工作,严重情况下会停止服务或宕机。
动态扩容是很多公司要求的技术之一,不支持动态扩容就意味着停止服务,这对很多公司来说是不可以接受的。
注:
阿里巴巴的Metal,RocketMQ都有Kafka的影子,他们要么改造了Kafka或者借鉴了Kafka,最后Kafka的动态扩容是通过Zookeeper来实现的。
Zookeeper是一种在分布式系统中被广泛用来作为:分布式状态管理、分布式协调管理、分布式配置管理、和分布式锁服务的集群。kafka增加和减少服务器都会在Zookeeper节点上触发相应的事件kafka系统会捕获这些事件,进行新一轮的负载均衡,客户端也会捕获这些事件来进行新一轮的处理。
Kafka相关概念
AMQP协议
Advanced Message Queuing Protocol (高级消息队列协议)
The Advanced Message Queuing Protocol (AMQP):是一个标准开放的应用层的消息中间件(Message Oriented Middleware)协议。AMQP定义了通过网络发送的字节流的数据格式。因此兼容性非常好,任何实现AMQP协议的程序都可以和与AMQP协议兼容的其他程序交互,可以很容易做到跨语言,跨平台。
上面说的3种比较流行的消息队列协议,要么支持AMQP协议,要么借鉴了AMQP协议的思想进行了开发、实现、设计。
一些基本的概念
消费者:(Consumer):从消息队列中请求消息的客户端应用程序
生产者:(Producer) :向broker发布消息的应用程序
AMQP服务端(broker):用来接收生产者发送的消息并将这些消息路由给服务器中的队列,便于fafka将生产者发送的消息,动态的添加到磁盘并给每一条消息一个偏移量,所以对于kafka一个broker就是一个应用程序的实例
kafka支持的客户端语言:Kafka客户端支持当前大部分主流语言,包括:C、C++、Erlang、Java、.net、perl、PHP、Python、Ruby、Go、Javascript
可以使用以上任何一种语言和kafka服务器进行通信(即辨析自己的consumer从kafka集群订阅消息也可以自己写producer程序)
Kafka架构
生产者生产消息、kafka集群、消费者获取消息这样一种架构
kafka集群中的消息,是通过Topic(主题)来进行组织的
一些基本的概念:
主题(Topic):一个主题类似新闻中的体育、娱乐、教育等分类概念,在实际工程中通常一个业务一个主题。
分区(Partition):一个Topic中的消息数据按照多个分区组织,分区是kafka消息队列组织的最小单位,一个分区可以看作是一个FIFO( First Input First Output的缩写,先入先出队列)的队列。
kafka分区是提高kafka性能的关键所在,当你发现你的集群性能不高时,常用手段就是增加Topic的分区,分区里面的消息是按照从新到老的顺序进行组织,消费者从队列头订阅消息,生产者从队列尾添加消息。
备份(Replication):为了保证分布式可靠性,kafka0.8开始对每个分区的数据进行备份(不同的Broker上),防止其中一个Broker宕机造成分区上的数据不可用。
kafka0.7是一个很大的改变:1、增加了备份2、增加了控制借点概念,增加了集群领导者选举 。
kafka集群搭建,没有太多可以说的东西,几乎就是照葫芦画瓢。有什么地方不懂或是报错,可以评论,博主会做些修改,若有急需解决问题的,也可直接联系博主,不忙的情况下,博主帮忙解决
环境说明
工具:
虚拟机 vmware
操作系统 红帽7(red hat 7)
zookeeper 3.4.5
kafka 0.9
环境拟定:三节点,主机分别叫node1,node2,node3,ip分别对应:192.168.163.131、192.168.163.130、192.168.163..132
1、下载
博主也是从别人那拿过来的,稍后博主会上传连接给出下载地址。
kafka的0.9版本。
2、安装
安装没什么好说的,tar -zxvf 文件名,解压归档就完事,然而还是上个图。
3、配置文件配置
3.1、基于OS的环境配置
为了简化后续操作,建议把安装目录下的bin目录放进path里面。
[root@node1 bin]# vi /etc/profile
3.2、外部zookeeper集群安装以及启动
3.3、kafka配置
${kafka_home}/config/server.properties
-
# Licensed to the Apache Software Foundation (ASF) under one or more
-
# contributor license agreements. See the NOTICE file distributed with
-
# this work for additional information regarding copyright ownership.
-
# The ASF licenses this file to You under the Apache License, Version 2.0
-
# (the "License"); you may not use this file except in compliance with
-
# the License. You may obtain a copy of the License at
-
#
-
# http://www.apache.org/licenses/LICENSE-2.0
-
#
-
# Unless required by applicable law or agreed to in writing, software
-
# distributed under the License is distributed on an "AS IS" BASIS,
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
# See the License for the specific language governing permissions and
-
# limitations under the License.
-
# see kafka.server.KafkaConfig for additional details and defaults
-
############################# Server Basics #############################
-
# The id of the broker. This must be set to a unique integer for each broker.
-
broker.id=1
-
############################# Socket Server Settings #############################
-
listeners=PLAINTEXT://192.168.163.131:9092
-
# The port the socket server listens on
-
port=9092
-
# Hostname the broker will bind to. If not set, the server will bind to all interfaces
-
host.name=localhost
-
# Hostname the broker will advertise to producers and consumers. If not set, it uses the
-
# value for "host.name" if configured. Otherwise, it will use the value returned from
-
# java.net.InetAddress.getCanonicalHostName().
-
#advertised.host.name=<hostname routable by clients>
-
# The port to publish to ZooKeeper for clients to use. If this is not set,
-
# it will publish the same port that the broker binds to.
-
#advertised.port=<port accessible by clients>
-
# The number of threads handling network requests
-
num.network.threads=3
-
# The number of threads doing disk I/O
-
num.io.threads=8
-
# The send buffer (SO_SNDBUF) used by the socket server
-
socket.send.buffer.bytes=102400
-
# The receive buffer (SO_RCVBUF) used by the socket server
-
socket.receive.buffer.bytes=102400
-
# The maximum size of a request that the socket server will accept (protection against OOM)
-
socket.request.max.bytes=104857600
-
############################# Log Basics #############################
-
# A comma seperated list of directories under which to store log files
-
log.dirs=/tmp/kafka-logs
-
# The default number of log partitions per topic. More partitions allow greater
-
# parallelism for consumption, but this will also result in more files across
-
# the brokers.
-
num.partitions=3
-
# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
-
# This value is recommended to be increased for installations with data dirs located in RAID array.
-
num.recovery.threads.per.data.dir=1
-
############################# Log Flush Policy #############################
-
# Messages are immediately written to the filesystem but by default we only fsync() to sync
-
# the OS cache lazily. The following configurations control the flush of data to disk.
-
# There are a few important trade-offs here:
-
# 1. Durability: Unflushed data may be lost if you are not using replication.
-
# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.
-
# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to exceessive seeks.
-
# The settings below allow one to configure the flush policy to flush data after a period of time or
-
# every N messages (or both). This can be done globally and overridden on a per-topic basis.
-
# The number of messages to accept before forcing a flush of data to disk
-
#log.flush.interval.messages=10000
-
# The maximum amount of time a message can sit in a log before we force a flush
-
#log.flush.interval.ms=1000
-
############################# Log Retention Policy #############################
-
# The following configurations control the disposal of log segments. The policy can
-
# be set to delete segments after a period of time, or after a given size has accumulated.
-
# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens
-
# from the end of the log.
-
# The minimum age of a log file to be eligible for deletion
-
log.retention.hours=168
-
# A size-based retention policy for logs. Segments are pruned from the log as long as the remaining
-
# segments don't drop below log.retention.bytes.
-
#log.retention.bytes=1073741824
-
# The maximum size of a log segment file. When this size is reached a new log segment will be created.
-
log.segment.bytes=1073741824
-
default.replication.factor=3
-
# The interval at which log segments are checked to see if they can be deleted according
-
# to the retention policies
-
log.retention.check.interval.ms=300000
-
############################# Zookeeper #############################
-
# Zookeeper connection string (see zookeeper docs for details).
-
# This is a comma separated host:port pairs, each corresponding to a zk
-
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
-
# You can also append an optional chroot string to the urls to specify the
-
# root directory for all kafka znodes.
-
zookeeper.connect=192.168.163.130:2181,192.168.163.131:2181,192.168.163.132:2181
-
# Timeout in ms for connecting to zookeeper
-
zookeeper.connection.timeout.ms=6000
==============================================================================================================
解析:
1、使用默认配置就好,注意五个个选项,brokerid、num.partitions、default.replication.factor、zookeeper.connect、zookeeper.connection.timeout.ms
2、brokerid,当前节点的id号,唯一标识,建议给顺序数字,方便管理
3、num.partitions,控制设定几个分区,default.replication.factor,控制设定几个备份。
这里博主有三个节点,所以各给了3。同学们也可根据自身实际情况以及自身需求给定
4、zookeeper.connect指定外部zk源的各个节点。若无特殊指定,外部zk集群默认端口2181
5、zookeeper.connection.timeout.ms根据自身网络情况设定,通常默认就好
==============================================================================================================
3.4将配置好的一份server.properties分发给各个节点
记得修改brokerid选项。
4、启动
各个节点均启动
kafka-server-start.sh /usr/local/kafka_2.11-0.9.0.1/config/server.properties > /usr/local/kafka_2.11-0.9.0.1/logs/logs & //启动线程并写入日志
返回进程号,即开启进程,详细信息给进入自定义的日志路径内查看
5、验证
思路:以下给出几条kafka指令。创建一个topic,一个节点作为生产者,两个节点作为消费者分别看看能否接收数据,进行验证
创建及查看topic
-
kafka-topics.sh -list -zookeeper 192.168.163.130:2181,192.168.163.131:2181,192.168.163.132:2181 查看所有topic
-
kafka-topics.sh --create --zookeeper 192.168.163.130:2181,192.168.163.131:2181,192.168.163.132:2181 --replication-factor 3 --partitions 3 --topic xxx (rf参数副本数,par参数分区数,xxx是topic的名称)创建topic
开启生产者以及消费者
-
kafka-console-producer.sh --broker-list 192.168.163.130:9092,192.168.163.131:9092,192.168.163.132:9092 --topic test 生产者
-
kafka-console-consumer.sh --zookeeper 192.168.163.130:2181,192.168.163.131:2181,192.168.163.132:2181 --topic test --from-beginning 消费者
如图,是博主之前建立的topic
node1开启生产者:
node2、node3开启消费者,查看队列:
消费者均收到生产者消息,即为成功,这里博主之前的消息未清理,其他多余消息请忽略
6、常见问题解决
6.1、问题描述,启动过一次以后,修改brokerID,再启动,无法成功
这是由于kafka日志系统无法写入导致的,每次写入日志文件时候,会在日志文件同目录下,生成相关几个文件。其中meta.properties会记录之前brokerID,若是再启动,日志会与kafka的brokerID进行比对,若是一致才准许写入指定的log文件,若是不一致则报错,线程停止
7 Kafka常用命令
以下是kafka常用命令行总结:
1.查看topic的详细信息
./kafka-topics.sh -zookeeper 127.0.0.1:2181 -describe -topic testKJ1
2、为topic增加副本
./kafka-reassign-partitions.sh -zookeeper 127.0.0.1:2181 -reassignment-json-file json/partitions-to-move.json -execute
3、创建topic
./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic testKJ1
4、为topic增加partition
./bin/kafka-topics.sh –zookeeper 127.0.0.1:2181 –alter –partitions 20 –topic testKJ1
5、kafka生产者客户端命令
./kafka-console-producer.sh --broker-list localhost:9092 --topic testKJ1
6、kafka消费者客户端命令
./kafka-console-consumer.sh -zookeeper localhost:2181 --from-beginning --topic testKJ1
7、kafka服务启动
./kafka-server-start.sh -daemon ../config/server.properties
8、下线broker
./kafka-run-class.sh kafka.admin.ShutdownBroker --zookeeper 127.0.0.1:2181 --broker #brokerId# --num.retries 3 --retry.interval.ms 60
shutdown broker
9、删除topic
./kafka-run-class.sh kafka.admin.DeleteTopicCommand --topic testKJ1 --zookeeper 127.0.0.1:2181
./kafka-topics.sh --zookeeper localhost:2181 --delete --topic testKJ1
10、查看consumer组内消费的offset
./kafka-run-class.sh kafka.tools.ConsumerOffsetChecker --zookeeper localhost:2181 --group test --topic testKJ1