golang LogAgent 项目实战(二)

本文主要记录了学习golang时做的一个项目:日志收集项目。

关键词:日志收集项目

消息队列的通信模型

点对点模式

消息生产者生产消息发送到queue里,然后消息消费者从queue中取出并且消费消息。一条消息被消费以后,queue中就没有了,不存在重复消费。

发布订阅模式

消息发布者(发布)将消息发布到topic中,同时有多个消费消息者(订阅)消费该消息。

和点对点方式不同,发布到topic的消息被所有订阅者消费(类似于关注了微信公众号的人都能收到推送的文章)。

补充:发布订阅模式下,放发布者消息量很大时,显然单个订阅者的处理能力是不足的,实际上现实场景中是多个订阅者节点组成一个订阅组负载均衡消费topic消息即分组订阅,这样订阅者很容易实现消费能力线性扩展。

对于不同的消息订阅者,可以看作是一个topic下有多个Queue,每个Queue是点对点的方式,Queue之间是发布订阅方式。

kafka

Apache Kafka由著名社交公司LinkdIn开发, 最初是被设计用来解决Linkedin公司内部海量日志传输等问题。

kafka实验Scala语言编写,于2011年开源并进入Apache孵化器,于2012年10月正式毕业,现为Apach顶级项目。

介绍

Kafka是一个分布式数据流平台,可以运行在单个服务器上,也可以在多台服务器上部署行程集群。它提供了发布和订阅功能,使用者可以发送数据到Kafka,也可以从Kafka中读取数据(以便进行后续的处理)。

Kafka 具有高吞吐、低延迟、高容错等特点。

  • Producer:Producer即生产者,消息的生产者,是消息的入口。
  • kafka cluster:kafka集群,一台或者多台服务器组成
    • Broker:Broker是指部署了Kafka实例的服务器节点。每个服务器上由一个或者多个Kafka的实例。姑且将每个broker对应一台服务器,每个Kafka集群里的broker都有一个不重复的编号,如图中的broker-0、broker-1等。
    • Topic:消息的主题,可以理解为消息的分类,kafka的数据就保存在topic。每个broker上都可以创建多个topic。实际应用中通常是一个业务线创建一个topic。
    • Partition:Topic的分区,每个topic可以由多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是一个个的文件夹。
    • Replication:每一个分区在不同的Broker上都有副本,副本的作用是做备胎。当主分区(Leader)宕机时会重新选择一个备胎(Follower)上位,成为Leader。在Kafka中绝对副本的最大数量是10个,且副本的数量不能大于Broker的数量,follower和leader绝对是在不同的机器同一机器对同一个分区也只能存放一个副本(包括自己)。

工作流程

Producer是生产者,是数据的入口,Producer在写入数据的时候会把数据写入到leader中,不会将数据直接写入follower!

  1. 生产者从Kafka集群中获取分区leader信息
  2. 生产者将消息发送给leader
  3. leader将消息写入本地磁盘
  4. follower从leader拉取数据 :生产者把数据写入Leader之后,Leader其他的副本主动从Leader中拉取数据
  5. follower将消息写入本地磁盘以后向leader发送ACK(回复确认)
  6. leader收到所有的follower的ACK后向生产者发送ACK(回复确认)

选择Partition的原则

如果某个topic有多个partition,producer怎么知道应该将数据发给那个partition呢?

Kafka中有以下几个原则:

  • partition在写入的时候可以指定写入的partition,如果有指定,则写入对应的partition;
  • 如果在写入的时候没有指定partition,但是又设置了数据的key,则会根据key的值hash出一个partition;
  • 如果既没有指定partition,有没有设置key,则会采用轮询方式,即每次取一小段时间的数据写入某个partition,下一小段的时间写入下一个partition。

ACK应答机制

producer在Kafka写入消息的时候,可以设置参数来确定是否确认kafka接收到数据,这个参数可设置为0、1、all

  • 0代表producer往集群发送数据不需要等到集群返回,不确保消息发送成功,安全性最低但是效率最高;
  • 1代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功。
  • all代表producer往集群发送数据需要所有的follower都完成从leader的同步才会发送下一条,确保leader发送成功和所有的副本都完成备份。安全性最高,但是效率最低。

注意:若往不存在的topic写数据,kafka会自动创建topic,partition和replication的数量的默认配置都是1。

Topic和数据日志

topic是统一类别的消息记录(record)的集合。 在Kafka中,一个主题通常有多个订阅者,对于每个主题,kafka集群维护了一个分区数据日志文件结构如下:

每个partition都是一个有序而且不可变的消息记录集合,当新的数据写入时,就被追加到partition的末尾。在每个partition中,每条消息都会被分配一个顺序的唯一标识,这个表示被称为offset,即偏移量

  • Kafka只保证在同一个partition内部消息是有序的,在不同partition之间,不能保证消息有序。

顺序读取,所以读取更快。

Kafka可以配置一个保留期限,用来标识日志会在Kafka集群中保留多长时间,Kafka集群回保留在保留期限内所以被发布的消息,不管这些消息是否被消费过。比如保留期限设置为两天,那么数据被发布到Kafka两天以内,所有的数据都可以被消费。当超过两天,这些数据都会被清空,一边为后续的数据腾出空间。由于kafka会将数据进行持久化存储(即写入到硬盘上),所以保留的数据大小可以设置为一个比较大的值。

Partition结构

Partition在服务器上的表现形式就是一个一个的文件夹,每个partition的文件夹下会有多组segment文件,每组segment文件又包含.index文件,.log文件和.timeindex文件三个文件,其中.log文件是实际存储message的地方,而.index.timeindex文件为索引文件,用于检索消息。

消费数据

多个消费者实例可以组成一个消费者组,并用一个便签来标识这个消费者组。一个消费者组的不同消费者实例可以运行在不同的进程甚至不同的个服务器上。

  • 如果所有的消费者实例都在同一个消费者组中,那么消息记录会被很好的均衡发送到每个消费者实例。
  • 如果所有的消费者实例都在不同的消费者组,那么每一条纤细记录会被广播到每一个消费者实例。

  • 同一消费者组中,每个消费者实例可以消费多个分区;
  • 每个分区最多只能被消费者组中的一个实例消费;

总结关键点

  1. Kafka集群的架构
    1. broker
    2. topic
    3. partition:分区,把同一个topic分成不同的分区,提高负载
      1. leader:分区的主节点
      2. follower:分区的从节点
    4. Consumer Group:消费组
  2. 生产者往Kafka发送数据的流程(6步)
  3. 选择分区的模式(三种)
    1. 指定分区写
    2. 指定key,kafka根据key做hash决定写分区
    3. 轮询方式
  4. 生产者往kafka发送数据的模式
    1. 0:把数据发哦是那个给leader就成功,效率最高,安全性最低
    2. 1:把数据发送给leader,等待leader回ack
    3. all:把数据发送给leader,follow从leader拉取数据成功后b回复ack给leader,leader收到所有的follower都回复ack给leader以后,生产者才会发送下一条数据
  5. 分区存储文件的原理
  6. 为什么Kafka快
  7. 消费者组消费数据的原理(参考官方文档)

Zookeeper

zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby的一个开源实现,是集群的管理者,监视着集群中各个系欸但的状态,并根据节点提交的反馈进行下一步合理操作。最终将简单易用的接口和性能高效、功能稳定的系统提供给用户。