kafka

163 阅读6分钟

kafka

消息队列介绍

图片.png

异步的方式,减少上游时间,提高吞吐量。在分布式系统中,利用分布式事务保证最终的一致性。
常见消息队列中间件:rabbitMQ rocketMQ kafka zeroMQ
消息队列的类型:
有broker
	重topic:根据topic进行消息转发(kafka)
	轻topic:topic这是一种方式
无broker:不需要broker,类似于socket通信(zeroMQ)

kafka基本概念

kafka就是解决通信问题的,底层封装了数据是如何发送的。
producer:发布消息到broker
broker:依据topic将消息发布
topic:实现消息的分类,不同消费者订阅不同topic
consumer:获取消息

安装

分布式发布/订阅消息系统
# vim server.properties
listeners=PLAINTEXT://192.168.43.33:9092
zookeeper.connect=192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181
log.dirs=/tmp/kafka-logs
# vim zookeeper.properties
dataDir=/tmp/zookeeper
maxClientCnxns=100
tickTimes=2000
initLimit=10
syncLimit=5
admin.enableServer=false

./kafka-server-start.sh -daemon /usr/local/src/kafka/config/server.properties
验证方式
# ./zkCli.sh查看对应brokerid即可

图片.png

消息的发布与订阅

创建主题topic
创建主题名为"test"的topic,1个分区,1个副本
# ./kafka-topics.sh --create --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181 -replication-factor 1 --partitions 1 --topic test
Created topic test.
查看当前kafka的topic
# ./kafka-topics.sh --list --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181
test

--zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181
发送消息
kafka自带了一个producer命令客户端,可以从本地文件中读取内容或命令行输入内容,并将这些内容以消息的形式发送到kafka集群中。
使用Kafka指定的客户端,要发送到kafka的服务器和topic上
# ./kafka-console-producer.sh --broker-list 192.168.43.33:9092 --topic test
消费消息
kafka自带了一个consumer命令客户端,会将获取到的内容展示出来,默认消费最新的消息
方式1:最后一条消息偏移量+1
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092 --topic test
方式2:从头开始消费
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092 --from-beginning --topic test

注意:
消息是顺序存储的,可以从特定偏移量开始消费
producer将消息发送给broker,broker会将消息保存在kafka上
消息保存在/tmp/kafka-logs/主题-分区/00000000000000000000.log中

单播消息

如果多个消费者在一个消费组中,只能有一个消费者能收到topic的消息
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092 --consumer-property group.id=Group1 --topic test

图片.png 图片.png 图片.png

多播消息

不同的消费组中的消费者都能收到同一个topic中的消息
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092 --consumer-property group.id=Group1 --topic test
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092 --consumer-property group.id=Group2 --topic test

图片.png 图片.png 图片.png

消费组

查看消费组
# ./kafka-consumer-groups.sh --bootstrap-server 192.168.43.33:9092 --list
Group1
Group2
testGroup1
描述组信息
# ./kafka-consumer-groups.sh --bootstrap-server 192.168.43.33:9092 --describe --group testGroup1
Consumer group 'testGroup1' has no active members.

TOPIC           PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG             CONSUMER-ID     HOST            CLIENT-ID
test            0          8               12              4               -               -               -

已经消费8条,还有4条未消费,共12条消息

主题与分区

创建分区

topic:kafka消息的一种划分
由于消息会被保存在log文件中(容量非常大),所以分区出现

图片.png

分区存储优点:
1、解决统一存储文件过大问题
2、分布式存储,并行写

查看当前kafka的topic
# ./kafka-topics.sh --list --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181
创建分区
# ./kafka-topics.sh --create --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181 -replication-factor 1 --partitions 2 --topic test2
描述test
# ./kafka-topics.sh --describe --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181 --topic test

图片.png

副本

副本概念
创建主题为my-replicated-topic 有两个分区,三个副本
# ./kafka-topics.sh --create --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181 -replication-factor 3 --partitions 2 --topic my-replicated-topic
描述 my-replicated-topic
# ./kafka-topics.sh --describe --zookeeper 192.168.43.30:2181,192.168.43.31:2181,192.168.43.32:2181 --topic my-replicated-topic

图片.png

多个副本在kafka集群中的多个broker中,只有一个leader(leader负责读写),follower负责同步数据
Leader:2表示Partition:0的leader为broker-2
Leader:0表示Partition:0的leader为broker-1
Replicas: 2,0,1表示副本所在的broker节点
Isr表示可以同步的节点、已经同步的节点(当节点性能较差时,会被踢出Isr)

因此broker、主题、分区、副本、isr等概念完整了

图片.png

消息日志文件中保存的内容

消息存放文件,文件过大时利用索引能快速查找需要的消息。
kafka自带了50个主题-分区
__consumer_offsets-0
__consumer_offsets-1
         ...
         ...
__consumer_offsets-49
key:消费组+主题+分区号 
value:当前offset值

每次消费后都会将消费的主题的偏移量上报给kafka,默认给了50个分区(默认保存7天)

集群消息消费

查看消费组
# ./kafka-consumer-groups.sh --bootstrap-server 192.168.43.33:9092,192.168.43.34:9092,192.168.43.35:9092 --list
描述消费组
# ./kafka-consumer-groups.sh --bootstrap-server 192.168.43.33:9092,192.168.43.34:9092,192.168.43.35:9092 --describe --group testGroup1

向集群中发送消息
# ./kafka-console-consumer.sh --bootstrap-server 192.168.43.33:9092,192.168.43.34:9092,192.168.43.35:9092 --from-beginning --consumer-property group.id=testGruop1 --topic my-replicated-topic

图片.png

rebalance机制

前提:消费者未指定分区消费
当消费者和分区的关系发送变化,就会触发rebalance机制
触发rebalance机制之前,消费者消费分区有三种策略
range(公式计算)、轮询、sticky(触发rebalance机制后,在原来消费分区的基础上进行调整)

HW和LEO

图片.png

LEO是某个副本最后消息的位置,HW是已完成同步的位置。(每个broker都有自己维护的HW和LEO值)
只有消息在写入broker且完成同步后,HW才会发生改变,在这之前LEO所在的位置的消息是不能被消费的。

kafka性能调优

1、防止消息丢失

使用同步发送
设置ack=1或all
设置同步的分区数>=2

2、防止消息的重复消费

幂等:多次访问结果是一样的
1、数据库中创建联合主键,防止相同主键创建多条记录
2、使用分布式锁,保证只有一条记录被创建
3、关闭重试(不建议)

图片.png

3、顺序消费

ack不为0、同步发送、关闭重试----->在上游保证消息顺序写入broker
消费者:主题只能有一个分区,消费组只能有一个消费者(牺牲了性能)------>使用场景不多

4、消息积压问题

图片.png

生产者发送消息的速度远大于消费者消费消息的速度,导致kafka集群性能变慢,导致其它消费者访问的速度也变慢
1、消费者使用多线程,充分利用机器性能
2、创建多个消费组、多个消费者部署在其它机器上,提高消费者的消费速度
3、创建一个消费者,这个消费者创建新的topic并配置多个分区,多个分区配置多个消费者。利用创建的消费者poll消息然后放到新topic中。保证了新topic的多个分区被多个消费者消费
4、通过业务的架构设计,提升业务层面的消费性能

5、延时队列

例子:在创建订单30分钟后还未付款,自动删除订单

图片.png

kafka中创建相应的主题
消费者轮询消费该主题的消息
当时间大于30分钟,消费者将数据库中的订单改为已取消
当时间小于30分钟,消费者记录offset值,并间隔1分钟poll消息,直到订单完成