文|孙超后端
网易智慧企业资深后端开发工程师缓存
官方定义 安全
根据官网的介绍,kafka是一个提供统一的、高吞吐、低延迟的,用来处理实时数据的流式平台,它具有如下三特性:服务器
kafka通常用在两大类应用中:并发
在邮箱服务中,咱们主要将kafka做为消息系统,用于系统内部消息的传输。为何要采用kafka呢?让咱们先从kafka的设计原理提及。分布式
概念与存储机制 高并发
kafka中是以Topic机制来对消息进行分类的,同一类消息属于同一个Topic,你能够将每一个Topic当作是一个消息队列。生产者将消息发送到相应的Topic,而消费者经过从Topic拉取消息来消费,没错,在kafka中是要求消费者主动拉取消息消费的,它并不会主动推送消息,这是它的一个特色,为何会这样设计呢?咱们后面再说,先来看一下Topic的结构:spa
Partition分区,每一个topic能够有多个分区,这是kafka为了提升并发量而设计的一种机制:一个topic下的多个分区能够并发接收消息,一样的也能供消费者并发拉取消息,即分区之间互不干扰,这样的话,有多少个分区就能够有多大的并发量。因此,若是要更准确的打比方,一个分区就是一个消息队列,只不过这些消息队列同属于一种消息分类。操作系统
在kafka服务器,分区是以目录形式存在的,每一个分区目录中,kafka会按配置大小或配置周期将分区拆分红多个段文件(LogSegment), 每一个段由三部分组成:线程
其中*.log用于存储消息自己的数据内容,*.index存储消息在文件中的位置(包括消息的逻辑offset和物理存储offset),*.timeindex存储消息建立时间和对应逻辑地址的映射关系。
段文件结构图以下 :
将分区拆分红多个段是为了控制存储的文件大小,若是整个分区只保存为一个文件,那随着分区里消息的增多,文件也将愈来愈大,最后不可控制。而若是每一个消息都保存为一个文件,那文件数量又将变得巨大,一样容易失去控制。因此kafka采用段这种方式,控制了每一个文件的大小,也方便控制全部文件的数量。同时,这些文件由于大小适中,能够很方便地经过操做系统mmap机制映射到内存中,提升写入和读取效率。这个设计的另外一个好处是:当系统要清除过时数据时,能够直接将过时的段文件删除,很是简洁。
可是这里也会有一个问题:若是每一个消息都要在index文件中保存位置信息,那么index文件也很容易变得很大,这样又会减弱上文所说的好处。因此在kafka中,index设计为稀疏索引来下降index的文件大小,这样,index文件存储的实际内容为:该段消息在消息队列中的相对offset和在log文件中的物理偏移量映射的稀疏记录。
那么多少条消息会在index中保存一条记录呢?这个能够经过系统配置来进行设置。索引记录固定为8个字节大小,分别为4个字节的相对offset(消息在partition中全局offset减去该segment的起始offset),4个字节的消息具体存储文件的物理偏移量。
index文件结构图以下:
Kafka不会在消费者拉取完消息后立刻就清理消息,而是会保存段文件一段时间,直到其过时再标记为可清理,由后台程序按期进行清理。这种机制使得消费者能够重复消费消息,知足更灵活的需求。
查询机制
上面说过,kafka虽然做为消息系统,可是消费消息并非经过推送而是经过拉取来消费的,client须要经过offset和size参数主动去查询消息。
kafka收到客户端请求后,对消息的寻址会通过下面几个步骤:
kafka读取示意图:
RabbitMQ vs kafka
介绍了kafka的实现原理,咱们再来对比一下一样做为消息队列服务的RabbitMQ。MQ的应用也很普遍,功能多而全,那么和MQ相比,kafka有哪些优点呢?为何咱们会使用kafka而抛弃了RabbitMQ呢?
RabbitMQ流程图:
RabbitMQ消费者只能从队列头部按序进行消费,消息一旦被消费,就会被打上删除标记,紧接着消费下一条消息,没办法进行回溯操做,这样的话一个消费者消费完消息,另外一个消费者就别想再消费了。而Kafka提供动态指定消费位点,可以灵活地进行回溯消费操做,只要该消息还在生命周期内能够重复拉取,而且不一样消费者能够互不干扰的消费同一个消息队列,这就比RabbitMQ灵活多了。
kafka消费位点示意图:
RabbitMQ若是要知足多个消费者消费同一个消息队列,也能够借助exchange路由能力,可是这样会将消息复制到多个队列,每一个消费者须要绑定一个本身的队列进行消费。若是有几百个消费者,那么队列复制几百倍,引发mq的消息水位猛涨,容易失控。而kafka就没这个问题,无论多少个消费者都只须要一个队列就能知足,每一个消费者均可以完整地不相互干扰地消费队列中的全部消息。
固然,RabbitMQ也有其优势,它提供的exchange,binding, queue等抽象实体,提供强大的路由关系(rounte key and bindkey)和消息过滤能力。做为传统消息系统提供了细粒度的消息控制能力。而Kafka主要是面向高流量,大吞吐的批处理系统,在路由抽象方面化繁为简,重点关注系统的高吞吐,因此使用上更为简洁。
kafka还有传统解决方案没法知足的高伸缩能力等优点,这里就不一一介绍了。
Kafka在邮件系统data bus中的运用
正由于kafka有着以上介绍的能力和优点,咱们的邮箱服务中采用了它做为消息系统,其中一个应用就是邮件系统的data bus。
data bus介绍
邮件系统用户收发信流程伴随着大量的业务逻辑和子系统调用,若是将这些流程都强依附在主干枝上,将会对系统形成较大的压力,整个业务流程也将变得复杂而缓慢。因此经过数据总线将主次流程进行解耦,减轻收发信主流程的复杂度,使其能够以更快的速度完成,加快系统响应时间。主流程产生事件源,经过kafka的传输,触发多个次要流程,次要流程能够并发在系统后台完成,而且能够轻易的扩展多种多样的次要流程。
下图以简化后的信流程为例:
Kafka在data bus中的运用
邮件系统在完成收发信流程后,会生成当次流程相关的系统事件,好比新邮件事件。data bus将这些事件写入到kafka集群的相应topic中,下游的一系列子系统对topic进行消费。
以下图所示,应用消费能力能借助Kafka集群实现弹性扩容
总 结
kafka在邮件系统中的应用给咱们带来的好处: