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。

kafka消息队列生产者、消费者部署图


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组成


kafka学习--初识kafka。

Parition结构图

    6、消费者分组:Group,用于归组同类消费者,在Kafka中,多个消费者可以共同消费一个Topic下的消息,每个消费者消费其中的部分消息,这些消费者就组成了一个分组,拥有同一个分组名称,通常也被称为消费者集群。

        注:多个Consumer组成一个消费者分组。当所有的消费者在一个分组时为传统的队列模式,如果所有的Consumer都在不同的组中就成了发布订阅模式。 消费者分组中的Consumer共同竞争同一个Topic,一个Topic中的消息只能被一个消费者的分组中的一个Consumer消费。


kafka学习--初识kafka。

消费者分组图

    7、Offset:消息存储在KafkaBroker上,消费者拉取消息数据的过程中需要知道消息在文件中的偏移量,这个偏移量就是所谓的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分布式

        kafka学习--初识kafka。
Kafka分布式关系图

    ZooKeeper是一个开源的分布式协调服务,他为分布式应用提供了高效且可靠的分布式协调服务,提供了诸如统一命名空间服务,配置服务和分布式锁等分布式基础服务。详情请看Zookeeper概述


2.5 Kafka的通讯协议

  1、Kafka的Producer、Broker和Consumer之间采用的是一套自行设计基于TCP层的协议,根据业务需求定制,而非实现一套类似ProtocolBuffer的通用协议。

  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的步骤。学习的过程不就是一个踩坑的过程嘛。共勉!