kafka学习--初识kafka。
学习背景:
公司最近打算将之前的项目改造成分布式的。但我觉得是个坑。。。 简单来说就是将之前的单体应用(应用程序、数据库)部署多套在不同的地市上。应用给统一的入口,相互之间的数据同步在应用层面进行同步。(其实数据库层面同步比较不坑,那样的话就不用从繁杂的业务里把数据的操作挑出来进行同步了。)。应用层面进行消息同步,所以选择了kafka这个消息中间件。于是就开始了kafka的学习之路。
1、 消息队列(Message Queue)
kafka是消息队列中的一种。所以,介绍kafka之前先简单的说下现在比较流行的几个消息队列吧
Message Queue消息传送系统提供传送服务。消息传送依赖于大量支持组件,这些组件负责处理连接服务、消息的路由和传送、持久性、安全性以及日志记录。消息服务器可以使用一个或多个代理实例。
JMS(Java Messaging Service)是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,翻译为Java消息服务。
1.1 消息队列分类
消息队列分类:点对点和发布/订阅两种:
1、点对点:
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。
消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
2、发布/订阅:
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
1.2 消息队列对比
1、RabbitMQ:支持的协议多,非常重量级消息队列,对路由(Routing),负载均衡(Loadbalance)或者数据持久化都有很好的支持。2、ZeroMQ:号称最快的消息队列系统,尤其针对大吞吐量的需求场景,擅长的高级/复杂的队列,但是技术也复杂,并且只提供非持久性的队列。
3、ActiveMQ:Apache下的一个子项,类似ZeroMQ,能够以代理人和点对点的技术实现队列。
4、Redis:是一个key-Value的NOSql数据库,但也支持MQ功能,数据量较小,性能优于RabbitMQ,数据超过10K就慢的无法忍受。
5、kafka--后面详细介绍。
2、kafka
2.1 kafka介绍
首先弄清楚kafka是个怎么的中间件吧。
——Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。
具有以下几个特性:
1、通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能
2、高吞吐量:即使是非常普通的硬件Kafka也可以支持每秒数百万 的消息
3、支持通过Kafka服务器和消费机集群来分区消息
4、支持Hadoop并行数据加载
2.2 kafka应用场景
1、构建可在系统或应用程序之间可靠获取数据的实时流数据管道。
2、构建实时流应用程序,可以转换或响应数据流
2.3 kafka的构成、相关名词解释
Kafka中发布订阅的对象是topic。我们可以为每类数据创建一个topic,把向topic发布消息的客户端称作producer,从topic订阅消息的客户端称作consumer。Producers和consumers可以同时从多个topic读写数据。一个kafka集群由一个或多个broker服务器组成,它负责持久化和备份具体的kafka消息。
kafka消息队列生产者、消费者部署图
kafka消息队列系统架构图
1、Producer : 生产消息到topic的一方
2、Consumer:订阅topic消费消息的一方
3、Broker:Kafka的服务实例就是一个broker,多个broker组成kafka集群。
4、Topic : 消息存放的目录即主题
5、Partition(消息分区):每个partition是一个有序的消息队列,partition中的每条消息都会被分配一个id(offset)用于标记当前消息位置。Partition是Topic物理上的组成单元。一个Topic由一个或多个Partition组成
Parition结构图
6、消费者分组:Group,用于归组同类消费者,在Kafka中,多个消费者可以共同消费一个Topic下的消息,每个消费者消费其中的部分消息,这些消费者就组成了一个分组,拥有同一个分组名称,通常也被称为消费者集群。
注:多个Consumer组成一个消费者分组。当所有的消费者在一个分组时为传统的队列模式,如果所有的Consumer都在不同的组中就成了发布订阅模式。 消费者分组中的Consumer共同竞争同一个Topic,一个Topic中的消息只能被一个消费者的分组中的一个Consumer消费。
消费者分组图
7、Offset:消息存储在Kafka的Broker上,消费者拉取消息数据的过程中需要知道消息在文件中的偏移量,这个偏移量就是所谓的Offset。
注:Kafka版本[0.10.1.1],已默认将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中。其实,早在 0.8.2.2 版本,已支持存入消费的 offset 到Topic中,只是那时候默认是将消费的 offset 存放在 Zookeeper 集群中。那现在,官方默认将消费的offset存储在 Kafka 的Topic中,同时,也保留了存储在 Zookeeper 的接口,通过 offsets.storage 属性来进行设置
其实,官方这样推荐,也是有其道理的。之前版本,Kafka其实存在一个比较大的隐患,就是利用 Zookeeper 来存储记录每个消费者/组的消费进度。虽然,在使用过程当中,JVM帮助我们完成了一些优化,但是消费者需要频繁的去与 Zookeeper 进行交互,而利用ZKClient的API操作Zookeeper频繁的Write其本身就是一个比较低效的Action,对于后期水平扩展也是一个比较头疼的问题。如果期间 Zookeeper 集群发生变化,那 Kafka 集群的吞吐量也跟着受影响。
关于Kafka offset存储的详细介绍可看这里:Kafka offset存储介绍
2.4 Kafka分布式
ZooKeeper是一个开源的分布式协调服务,他为分布式应用提供了高效且可靠的分布式协调服务,提供了诸如统一命名空间服务,配置服务和分布式锁等分布式基础服务。详情请看Zookeeper概述
2.5 Kafka的通讯协议
2、基本数据类型:(Kafka是基于Scala语言实现的,类型也是Scala中的数据类型)
定长数据类型:int8,int16,int32和int64,对应到Java中就是byte, short, int和long。
变长数据类型:bytes和string。变长的数据类型由两部分组成,分别是一个有符号整数N(表示内容的长度)和N个字节的内容。其中,N为-1表示内容为null。bytes的长度由int32表示,string的长度由int16表示。
数组:数组由两部分组成,分别是一个由int32类型的数字表示的数组长度N和N个元素。
3、Kafka通讯的基本单位是Request/Response。
2.6 Kafka数据传输的事务定义
1、at most once:最多一次,这个和JMS中"非持久化"消息类似.发送一次,无论成败,将不会重发。
at most once:消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理.那么此后"未处理"的消息将不能被fetch到,这就是"atmost once"。
2、at least once:消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功。at least once:消费者fetch消息,然后处理消息,然后保存offset.如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"atleast once",原因offset没有及时的提交给zookeeper,zookeeper恢复正常还是之前offset状态。
3、exactly once:消息只会发送一次。
exactly once: kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的
注:通常情况下"at-least-once"是我们首选。(相比at most once而言,重复接收数据总比丢失数据要好)。
Kafka的入门介绍就到这儿了。关于Kafka的环境搭建可以参考这篇博客Kafka入门的简单部署。
后续将会整理一下使用springBoot整合Kafka的步骤。学习的过程不就是一个踩坑的过程嘛。共勉!