Kafka架构探险(二)——一文带你了解Kafka

上篇博文已经讲解了如何安装Kafka的集群环境,今天我们就来一本带大家了解下Kafka,了解kafka的特点以及基本概念

kafka的特点

Kafka设计的初衷是为了解决互联网公司超大量级数据的实时传输,为了实现这个目标,需要考虑以下四个方面的问题

  • 吞吐量/延时
  • 消息持久化
  • 负载均衡和故障转移
  • 伸缩性
  1. 吞吐量是Kafka每秒能够处理的消息数,那么很显然,我们都希望系统的吞吐量越大越好,与此同时,还有个客户端发送指令,kafka服务端接受指令然后反馈给客户端的时间,这个时间就是延时,那么对于一个系统而言,延时时间间隔越短越好。而kafka是一个高吞吐量和低延时的系统,那么他是如何实现的呢?
  • 大量使用操作系统页缓存,内存的操作速度快且命中率高

由于大量使用也缓存,故读取消息时大部分消息很有可能依然保存在页缓存中,因此可以直接命中缓存,不用“穿透”到底层的物理磁盘上获取消息,从而极大的提升了读取的吞吐量

  • kafka不直接参与物理I/O操作,而是交由最擅长此事的操作系统来完成
  • 采用追加写入方式,摒弃了缓慢的磁盘随机I/O操作

kafka在设计时采用了追加写入消息的方式,即只能在日志文件末尾追加写入新的消息,且不允许修改已经写入的消息,因此他属于典型的磁盘顺序访问型操作,这种类型的操作访问速度堪比内存的读写速度,性能是非常高的

  • 使用sendfile为代表的零拷贝技术加强网络间的数据传输效率

kafka在读取消息时,会首先从OS的页缓存中读取,如果命中便把消息经页缓存直接发送到网络的Socket上,这个过程就是零拷贝技术

  1. 消息引擎都必须要具有持久化的机制,持久化的机制有如下的好处:
  • 让消息的生产和消费解耦

消息生产者只需要将消息发送给kafka即可,不必关系消息是被谁消费的,何时消费的

  • 灵活的消息处理

消息保存在kafka中,方便实现消息重演这样的需求,可以很方便的处理消息

  • 减少内存的使用

将消息持久化到kafka中,给内存释放出更多的空间,方便kafka使用页面缓存技术来提升系统的性能

  1. kafka是一个分布式流处理平台,所以kafka具有分布式系统的两个重要的特性——负载均衡和故障转移
  • 负载均衡就是让系统的负载根据一定的规则均衡的分配到所有参与工作的机器上,从而最大限度的提升整体系统的运行效率,kafka的负载均衡实际上是通过partition以及leader来实现的,后面再详细介绍
  • 当分布式系统的一个节点出现了问题,无法发送心跳或者会话,则master服务器认为备份服务器已经无法工作 ,将会根据一系列的算法来计算新的节点,实现了系统的高可用性
  1. 伸缩性,所谓的伸缩性表示向分布方式中额外的增加计算资源时吞吐量提升的能力,通俗点来讲,就是如何通过增加节点来扩展kafka集群环境的系统,这点kafka是通过将服务器的状态的相关的参数交给zookeeper来管理

kafka的基本概念

  1. 消息

消息是每一个消息引擎的重中之重,好的消息的结构设计能极大的优化系统的性能,这里kafka处理的非常好,我们也有必要理解下kafka的消息的组成以及为什么

首先消息是由:消息头部、Key和Value组成,其中消息头部还包括:CRC、版本号、属性、时间戳和键长度。

image

这里主要说明4个字段的含义:

  • 消息键:对消息做partition时使用,即决定消息被保存在某个topic下的哪个partition
  • 消息体:保存实际的消息数据
  • 时间戳:消息发送的时间戳,主要用于流式处理以及其他依赖时间的处理语义,默认是当前时间
  • 属性:kafka使用一个字节来保存消息的压缩属性,当前只支持4中压缩属性:0——无压缩 1——GZIP压缩 2——Snappy压缩 3——LZ4压缩

Kafka使用二进制字节数组来保存消息,这个和RabbitMQ是一样的,为什么要这样设计呢? 试想一下,如果我们使用Java的类来实现,如果存储成String字符串格式 ,那么对于Java内存模型,对象保存的开销是很大的,随着堆里面的数据量越来越大,GC的也就越频繁,那么系统的性能也就越差,其他Java的操作系统通常默认是开启页缓存机制的,也就是说堆上保存的对象可能在页缓存中还保留一份,这也造成了极大的资源浪费

因此,kafka在消息设计时,直接使用紧凑二进制字节数据,这样我们就能有更多的内存使用

  1. topic和partition

准确来说,topic是一个逻辑上的概念,一般我们用来作为业务上的一个区分的尺度,代表一类消息,比如说A发送消息到topicA中,B发送消息到topicB中,一个topic可能被多个消费者来消费,为了提供系统的吞吐量,kafka提出了partition的概念,我们可以认为一个topic是由多个partition组成的

image

kafka中的partition是不可修改的有序消息队列,每个partition有自己专属的partition号,通常是从0开始的,用户对partition唯一能做的就是在消息队列的尾部追加写入消息,每个消息队列中都有一个序号,这个序号就是接下里要说的 offset

  1. offset

partition中的每个消息队列都是固定的,并且从0开始递增

综合之前所说的topicpartition以及offset我们可以确定一条消息

  1. replica

我们知道partition是有序的消息队列,那么一定不是保存在一个地方的,否则一旦kafka挂了,其上保存的消息也就丢失了,分布式要实现高可用性,这里kafka采用了冗余机制——备份多个日志,这些日志在kafka中就被称为replica副本,他存在的唯一目的就是防止数据丢失

replica分为: leader replicafollower replica,follower replica唯一的用途就是leader replica所在的broker宕机了,不能对外提供服务了,则kafka就会从剩余的replica中选举新的leader来提供服务

  1. leader和follower

上面我们说过什么是leaderfollower,在kafka中,leader对外提供服务,follower只能被动的追随leader的状态,保持与leader同步,follower唯一存在的目的就是当leader宕机了,被选举称为新的leader来继续提供服务

kafka保证统一个partition的多个replica一定不会分配在同一台broker上,毕竟如果同一个broker上有同一个partition的多个replica,那么将无法实现备份冗余的效果

  1. ISR

ISR(in-sync replica)在kafka中是一个重要的概念, 翻译过来就是与 leader replica保持同步的replica集合, kafka为partition动态维护一个replica集合,该集合中的所有的replica保存的消息日志都与leader replica保持同步状态,只有这个集合中的replica才能被选为leader,也只有该集合中的replica都同时接收到同一条消息,kafka才会将该消息置为“已提交”状态,即认为该条消息发送成功

这里需要注意两点:

  • ISR中至少需要一个“活着”的replica
  • “已提交”消息

你可能感兴趣的:(Kafka架构探险(二)——一文带你了解Kafka)