1. 为什么使用消息队列?
解耦: 解耦数据的处理过程。
冗余:有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
扩展性:因为消息队列解耦了处理过程。 所以增大消息入队和处理的频率是很容易的。 只要另外增加处理过程即可。 不需要改变代码,不需要调节参数。
峰值处理能力:
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
可恢复性:
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
顺序保证:
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka能保证一个Partition内的消息的有序性。
异步通信:
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
缓冲:(不懂)在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。
用于数据流:(不懂)
在一个分布式系统里,要得到一个关于用户操作会用多长时间及其原因的总体印象,是个巨大的挑战。消息系列通过消息被处理的频率,来方便的辅助确定那些表现不佳的处理过程或领域,这些地方的数据流都不够优化。
2.为什么使用kafka
支持多个生产者
不管客户端使用单个主题还是多个主题。所以它很适合用来从多个前端系统收集数据, 并以统一的格式对外提供数据。
|
多个消费者
除了支持多个生产者外, kafka支持多个消费者从一个单独的消息流上读取数据。而且消费者之间互不影响。 这与其他队列系统不同,其他队列系统的消息一旦被一个客户端读取,其他客户端无法再读取它,另外,多个消费者可以组成一个群组,他们共享一个消息流,并保证整个群组对每个给定的消息只处理一次。 |
基于磁盘的数据存储
Kafka 不仅支持多个消费者,还允许消费者非实时地读取消息,这要归功于 Kafka 的数据 保留特性。消息被提交到磁盘,根据设置的保留规则进行保存。每个主题可以设置单独的 保留规则,以便满足不同消费者的需求,各个主题可以保留不同数量的消息。消费者可能 会因为处理速度慢或突发的流量高峰导致无陆及时读取消息,而持久化数据可以保证数据 不会丢失。消费者可以在进行应用程序维护时离线一小段时间,而无需担心消息丢失或堵 塞在生产者端。 消费者可以被关闭,但消息会继续保留在 Kafka 里。消费者可以从上次中 断的地方继续处理消息。 |
伸缩性
为了能够轻松处理大量数据, Kafka 从一开始就被设计成一个具有灵活伸缩性的系统。用 户在开发阶段可以先使用单个 broker,再扩展到包含 3 个 broker 的小型开发集群,然后随着数据盐不断增长,部署到生产环境的集群可能包含上百个 broker。对在线集群进行扩展丝毫不影响整体系统的可用性。也就是说, 一个包含多个 broker 的集群,即使个别 broker失效,仍然可以持续地为客户提供服务。要提高集群的容错能力,需要配置较高的复制系数 |
高性能
上面提到的所有特性,让 Kafka 成为了一个高性能的发布与订阅消息系统。通过横向扩展 生产者、消费者和 broker, Kafka 可以轻松处理巨大的消息流。在处理大量数据的同时, 它还能保证亚秒级的消息延迟。 |
3.相关概念介绍
3.1分区
Kaflca 通过分区来实现数据冗余和伸缩性。
分区可以分布在不同的服务器上,也就是说, 一个主题可以横跨多个服务器,以此来提供比
单个服务器更强大的性能。
我们通常会使用流这个词来描述 Kaflca 这类系统的数据
3.2生产者
一般情况下,一个消息会被发布到一个特定的主题上。生产者在默认情况下把消息均衡地分布到
主题的所有分区上,而并不关心特定消息会被写到哪个分区。不过,在某些情况下,生产
者会把消息直接写到指定的分区。这通常是通过消息键和分区器来实现的,分区器为键生成一个散列值,并将其映射到指定的分区上。这样可以保证包含同一个键的消息会被写到同一个分区上。生产者也可以使用自定义的分区器,根据不同的业务规则将消息映射到分区
3.3消费者
消费者订阅一个或多个主题,并按照消息生成的顺序读取它们。消费者通过检查消息的偏移盘来区
分已经读取过的消息。 偏移量是另一种元数据,它是一个不断递增的整数值,在创建消息时, Kafka 会把它添加到消息里。在给定的分区里,每个悄息的偏移量都是唯一的。消费者把每个分区最后读取的悄息偏移量保存在 Zookeeper 或 Kafka 上,如果悄费者关闭或重启,它的读取状态不会丢失。
3.4消费者的群组关系
消费者是消费者群组的一部分,也就是说,会有一个或多个消费者共同读取一个主题 。 胖组保证每个分区只能被一个消费者使用 。图 1-6 所示的群组中,有 3 个消费者同时读取一个主题。其中的两个消费者各自读取一个分区,另外一个消费者读取其他两个分区。消费者与分区之间的映射通常被称为悄费者对分区的所有权关系 。
3.5broker
一个独立的kafka服务器被称为broker. broker 接收来自 生产者的消息,为消息设置偏移
量,并提交消息到磁盘保存。 broker 为消费者提供服务,对读取分区的请求作出响应,返
回已经提交到磁盘上的消息。根据特定的硬件及其性能特征,单个 broker 可以轻松处理数
千个分区以及每秒百万级的消息量。
broker 是集群的组成部分。每个集群都有一个 broker 同时充当了集群控制器的角色(自动
从集群的活跃成员中选举出来)。控制器负责管理工作,包括将分区分配给 broker 和监控
broker. 在集群中, 一个分区从属于一个 broker, i亥 broker 被称为分区的首领 。一个分 区
可以分配给多个 broker,这个时候会发生分区复制(见图 1-7 )。这种复制机制为分区提供
了消息冗余,如果有一个 broker 失效,其他 broker 可以接管领导权。不过,相关的消费者
和生产者都要重新连接到新的首领。第 6 章将详细介绍集群的操作,包括分区复制。
保留消息(在一定期限内)是 Kafka 的一个重要特性。 Kafka broker 默认的消息保留策略
是这样的:要么保留一段时间(比如 7 天),要么保留到消息达到一定大小的字节数(比
如 lGB )。当消息数量达到这些上限时,旧消息就会过期井被删除,所以在任何时刻, 可
用消息的总量都不会超过配置参数所指定的大小。主题可以配置自己的保留策略,可以将
悄息保留到不再使用它们为止。例如,用于跟踪用户活动的数据可能需要保留几天,而应
用程序的度量指标可能只需要保留几个小时。可以通过配置把主题当作紧凑型日志, 只有
最后一个带有特定键的消息会被保留下来。这种情况对于变更日志类型的数据来说比较适
用,因为人们只关心最后时刻发生的那个变更。
broker的消息复制
4.环境搭建
总体环境
虚拟机centos 64
jdk usr/java
下载地址
https://pan.baidu.com/s/18IicPYf7W0j-sHBXvfKyyg?errno=0&errmsg=Auth%20Login%20Sucess&&bduss=&ssnerror=0&traceid=
|
zookeeper
usr/local/zookeepercluster/zookeeper1
usr/local/zookeepercluster/zookeeper2
usr/local/zookeepercluster/zookeeper3
下载地址:
https://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/ |
4.1zookeeper集群搭建
构建一个这样的目录/usr/local/zookeepercluster/zookeeper1
cp -r zookeeper1/ zookeeper2
cp -r zookeeper1/ zookeeper3
4.1.1配置zookeeper data/myid
[root@localhost zookeepercluster]# cd zookeeper1 [root@localhost zookeeper1]# mkdir data [root@localhost zookeeper1]# cd data [root@localhost data]# echo 1>>myid |
2和3也按照这个配置. id分别是2和3
4.1.2配置zoo.cfg
zookeeper1 zookeeper2 (2881是投票端口, 3881是选举端口) |
4.1.3创建快捷启动zookeepercluster/start.sh
./zookeeper1/bin/zkServer.sh start ./zookeeper2/bin/zkServer.sh start ./zookeeper3/bin/zkServer.sh start |
4.1.4创建快捷关闭shutdown.sh
./zookeeper1/bin/zkServer.sh stop ./zookeeper2/bin/zkServer.sh stop ./zookeeper3/bin/zkServer.sh stop |
4.1.5启动集群
[root@localhost zookeepercluster]# ./start.sh
4.1.6查看集群状态
[root@localhost zookeepercluster]# zookeeper1/bin/zkServer.sh status
显示结果
JMX enabled by default Using config: /usr/local/zookeepercluster/zookeeper1/bin/../conf/zoo.cfg Mode: follower |
4.1.7zookeeper的日志配置
附:Zookeeper默认会将控制台信息输出到启动路径下的zookeeper.out中,显然在生产环境中我们不能允许Zookeeper这样做,通过如下方法,可以让Zookeeper输出按尺寸切分的日志文件: 修改conf/log4j.properties文件,将 zookeeper.root.logger=INFO, CONSOLE 改为 zookeeper.root.logger=INFO, ROLLINGFILE 修改bin/zkEnv.sh文件,将 ZOO_LOG4J_PROP="INFO,CONSOLE" 改为 ZOO_LOG4J_PROP="INFO,ROLLINGFILE" 然后重启zookeeper,就ok了 附:Zookeeper默认会将控制台信息输出到启动路径下的zookeeper.out中,显然在生产环境中我们不能允许Zookeeper这样做,通过如下方法,可以让Zookeeper输出按尺寸切分的日志文件: 修改conf/log4j.properties文件,将 zookeeper.root.logger=INFO, CONSOLE 改为 zookeeper.root.logger=INFO, ROLLINGFILE 修改bin/zkEnv.sh文件,将 ZOO_LOG4J_PROP="INFO,CONSOLE" 改为 ZOO_LOG4J_PROP="INFO,ROLLINGFILE" 然后重启zookeeper,就ok了
|
4.2kafka安装
下载地址
http://archive.apache.org/dist/kafka/0.9.0.1/
如下目录
usr/local/kafkacluster/kafka1
usr/local/kafkacluster/kafka2
4.2.1编辑配置文件
vi kafka1/config/server.properties
主要修改以下内容(ip改成localhost也行)
broker.id=0 listeners=PLAINTEXT://:9092 port=9092 host.name=192.168.0.107 advertised.host.name=192.168.0.107 advertised.port=9092 zookeeper.connect=localhost:2181 |
4.2.2启动节点1
[root@localhost kafkacluster]# kafka1/bin/kafka-server-start.sh -daemon kafka1/config/server.properties |
4.2.3测试创建topic
[root@localhost kafkacluster]# kafka1/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
[root@localhost bin]# ./kafka-topics.sh --create --zookeeper localhost:2181,localhost:2182,localhost:2183 --replication-factor 1 --partitions 1 --topic lytest
4.2.4测试topic
[root@localhost kafkacluster]# kafka1/bin/kafka-topics.sh --describe --zookeeper localhost:2181,localhost:2182,localhost:2183
|
4.2.5测试生产者
kafka1/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
[root@localhost kafkacluster]# kafka1/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testhome Test Message 1 Test Message 2 ^C[root@localhost kafkacluster]# |
4.2.6测试消费者
kafka1/bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test --from-beginning
[root@localhost kafkacluster]# kafka1/bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic testhome --from-beginning Test Message 1 Test Message 2 ^CProcessed a total of 2 messages |
4.2.7kafka关闭
kafka1/bin/kafka-server-stop.sh
4.2.8完整的创建topic,测试生产,测试消费
[root@localhost kafkacluster]# kafka1/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic ly Created topic "ly". [root@localhost kafkacluster]# kafka1/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic ly this a message ^C[root@localhost kafkacluster]# kafka1/bin/kafka-console-consumer.sh --zookeeper localst:2181 --topic ly --from-beginning this a message |
5.kafka集群
-
5.1broker的配置
要把一个 broker 加入到集群里,只需要修改两个配置参数。首先,所有 broker 都必须配
置相同的 zookeeper .connect , 该参数指定了用于保存元数据的 Zookeeper 群组和路 径。
其次,每个 broker 都必须为 broke r . i.d 参数设置唯一的值。 如果两个 broker 使用相同的b roke r .id,那么第二个 broker 就无法启动。在运行集群时,还可以配置其他一些参数,特别是那些用于控制数据复制的参数
具体参见如下,kafka2
broker.id=1 listeners=PLAINTEXT://:9093 port=9093 host.name=localhost advertised.host.name=localhost advertised.port=9093 log.dirs=/tmp/kafka-logs-1 //这里不要与kafka1设置一样的 zookeeper.connect=localhost:2181 |
启动2
kafka2/bin/kafka-server-start.sh -daemon kafka2/config/server.properties |
查看是不是启动了
jps –lm查看java进程
[root@localhost kafkacluster]# jps -lm 3505 org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/local/zookeepercluster/zookeeper3/bin/../conf/zoo.cfg 6311 sun.tools.jps.Jps -lm 3482 org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/local/zookeepercluster/zookeeper2/bin/../conf/zoo.cfg 3835 kafka.Kafka kafka1/config/server.properties 6172 kafka.Kafka kafka2/config/server.properties 3469 org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/local/zookeepercluster/zookeeper1/bin/../conf/zoo.cfg |
6. 分配分区是怎样的一个过程得知启动成功
当消费者要计入群组时,它会向群组协调器发送一个JoinGroup请求。第一个加入群组的消费者将成为“群主”。群主从协调器那里获得群组的成员列表(列表中包含了所有最近发送过心跳的消费者,它们被认为是活跃的),并负责给每一个悄费者分配分区。它使用一个实现了partitionAssignor接扣的类来决定哪些分区应该被分配给哪个消费者 。
Kafka内置了两种分配策略。 分配完毕之后,群主把分配情况列表发送给群组协调器,协调器再把这些信息发
送给所有消费者。每个消费者只能看到自己的分配信息,只有群主知道群组里所有消费者的分配信息。这个过程会在每次再均衡时重复发生。
7.偏移量的作用
消费者往一个叫作 _consumer_offset 的特殊主题发送消息,消息里包含每个分区的偏移量。 如果消费者一直处于运行状态,那么偏移量就没有什么用处。不过,如果消费者发生崩愤或者有新的消费者加入群组,就会触发再均衡,完成再均衡之后,每个消费者可能分配到新的分区,而不是之前处理的那个。为了能够继续之前的工作,消费者需要读取每个分区最后一次提交的偏移量,然后从偏移量指定的地方继续处理。如果提交的偏移量小于客户端处理的最后一个消息的偏移量 ,那么处于两个偏移量之间的消息就会被重复处理;如果提交的偏移量大于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息将会丢失;