kafka是一个分布式的、分区化、可复制提交的发布订阅消息系统
传统的消息传递方法包括两种:

  • 排队:在队列中,一组用户可以从服务器中读取消息,每条消息都发送给其中一个人。
  • 发布-订阅:在这个模型中,消息被广播给所有的用户。
    kafka与传统的消息传递技术相比优势之处在于:
  • 快速:单一的Kafka代理可以处理成千上万的客户端,每秒处理数兆字节的读写操作。
  • 可伸缩:在一组机器上对数据进行分区和简化,以支持更大的数据
  • 持久:消息是持久性的,并在集群中进行复制,以防止数据丢失。
  • 设计:它提供了容错保证和持久性

基本概念

  1. Topic(话题):Kafka中用于区分不同类别信息的类别名称。由producer指定
  2. Producer(生产者):将消息发布到Kafka特定的Topic的对象(过程)
  3. Consumers(消费者):订阅并处理特定的Topic中的消息的对象(过程)
  4. Broker(Kafka服务集群):已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker). 消费者可以订阅一个或多个话题,并从Broker拉数据,从而消费这些已发布的消息。
  5. Partition(分区)Topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)
  6. Message:消息,是通信的基本单位,每个producer可以向一个topic(主题)发送一些消息。

Log(日志)

日志是一个只能增加的,完全按照时间排序的一系列记录。
我们可以给日志的末尾添加记录,并且可以从左到右读取日志记录。
每一条记录都指定了一个唯一的有一定顺序的日志记录编号。

每个日志文件都是“log entries”序列,每一个log entry包含一个4字节整型数(值为N),其后跟N个字节的消息体。每条消息都有一个当前partition下唯一的64字节的offset,它指明了这条消息的起始位置

这个“log entries”并非由一个文件构成,而是分成多个segment,每个segment名为该segment第一条消息的offset和“.kafka”组成。另外会有一个索引文件,它标明了每个segment下包含的log entry的offset范围。

Topic & Partition


谈到kafka的存储,就不得不提到分区。
创建一个topic时,同时可以指定分区数目,分区数越多,其吞吐量也越大,但是需要的资源也越多,同时也会导致更高的不可用性,kafka在接收到生产者发送的消息之后,会根据均衡策略将消息存储到不同的分区中。

为了使得Kafka的吞吐率可以水平扩展,物理上把topic分成一个或多个partition,每个partition在物理上对应一个文件夹,该文件夹下存储这个partition的所有消息和索引文件。

消息以顺序存储:每一个分区都是一个顺序的、不可变的消息队列, 并且可以持续的添加,最晚接收的的消息会最后被消费。
分区中的消息都被分配了一个序列号,称之为偏移量(64字节的offset),在每个分区中此偏移量都是唯一的。
因为每条消息都被append到该partition中,是顺序写磁盘,因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)

与生产者的交互

生产者在向kafka集群发送消息的时候,可以通过指定分区来发送到指定的分区中。
也可以通过指定均衡策略来将消息发送到不同的分区中。
如果不指定,就会采用默认的随机均衡策略,将消息随机的存储到不同的分区中。

每一条消息被发送到broker时,会根据paritition规则选择被存储到哪一个partition
如果partition规则设置的合理,所有消息可以均匀分布到不同的partition里,这样就实现了水平扩展。(如果一个topic对应一个文件,那这个文件所在的机器I/O将会成为这个topic的性能瓶颈,而partition解决了这个问题)。

在发送一条消息时,可以指定这条消息的key,producer根据这个key和partition机制来判断将这条消息发送到哪个parition。
paritition机制可以通过指定producer的paritition. class这一参数来指定,该class必须实现kafka.producer.Partitioner接口。
本例中如果key可以被解析为整数则将对应的整数与partition总数取余,该消息会被发送到该数对应的partition。(每个parition都会有个序号)

与消费者交互

在消费者消费消息时,kafka使用offset来记录当前消费的位置。
在kafka的设计中,可以有多个不同的group来同时消费同一个topic下的消息
两个不同的group同时消费,他们消费的记录位置offset各不项目,不互相干扰。

对于一个group而言,消费者的数量不应该多于分区的数量
因为每个分区被同一个group中的一个消费者所消费。所以:

  1. 一个消费者可以消费多个分区,但一个分区只能给同一个组的一个消费者消费
  2. 同一个group下消费者对分区互斥,而不同消费组之间是共享的。
  3. 因此,若一个group中的消费者数量大于分区数量的话,多余的消费者将不会收到任何消息

通过设置不同的消费者,可以实现传统的发布订阅模式和队列模式:

offset偏移量

  1. 在每个分区中此偏移量都是唯一的。
  2. 消费者所持有的仅有的元数据就是这个偏移量,也就是消费者在这个log中的位置。
  3. 偏移量由消费者控制。正常情况当消费者消费消息的时候,偏移量也线性的的增加。消费者可以将偏移量重置为更老的一个偏移量,重新读取消息。
  4. 一个消费者的操作不会影响其它消费者对此log的处理
  5. 一个topic中有100条数据,我消费了50条并且提交了,那么此时的kafka服务端记录提交的offset就是49(offset从0开始),那么下次消费的时候offset就从50开始消费。

手动控制Offest

首先了解一下消息传递保证:

  1. At most once 最多一次 --- 消息可能丢失,但绝不会重发。
  2. At least once 至少一次 --- 消息绝不会丢失,但有可能重新发送。
  3. Exactly once 正好一次 --- 这是人们真正想要的,每个消息传递一次且仅一次。

自动提交是在kafka拉取到数据完就直接提交数据偏移量。

而业务系统中,消费数据还伴随着一些逻辑业务处理,插入数据库等。
这事务过程,需要完成才提交。不然还没插进数据库,新的数据又来了。
加入插入数据库还失败了,就没法再消费一次失败的数据了。

所以要严格的不丢数据,需要手动控制offest。

  1. 手动commit offset,并针对partition_num启同样数目的consumer进程,这样就能保证一个consumer进程占有一个partition,commit offset的时候不会影响别的 partition 的 offset。但这个方法比较局限,因为partition和consumer进程的数目必须严格对应。
  2. 另一个方法同样需要手动commit offset,另外在consumer端再将所有fetch到的数据缓存到queue里,当把queue里所有的数据处理完之后,再批量提交offset,这样就能保证只有处理完的数据才被commit。

官网还说:
手动控制offest让我们能精确控制消息被消费(实现 提交了offest的不再消费,没提交过offest的数据会再次消费)。
但这一过程可能在 数据插入数据库后,但是还没commit offset到kafka时 失败了;那么下一次消费将还是从上次消费的起点取到数据,会重复插入数据库,造成重复。
kafka提供的是 "at-least once delivery" 保证, 即可能有两次三次被消费(我们项目就是这样)。

at-least once还有一个问题:
加入一个分区中先后进来 1,2 两条数据。在进来1时,网络不好导致插入失败,然后进行重试机制后网络还是不行,如果不停程序继续消费,这时2数据进来时网络好了,对2插入成功,那么偏移量就偏到数据2了,将1数据覆盖了,这时就不会再插入1数据了。就没法保证只at-least once了,除非停掉消费者,但是停了的话,同一组的消费者还会继续消费,这时又要实际到使用 assign模式还是subscribe模式订阅消息了。

kafka系列 -- 基础概念的更多相关文章

  1. WCF系列 基础概念

    WCF全称Windows Communication Foundation,是微软构建面向服务的分布式编程框架.而它其实是统一了COM和.Net Remoting等分布式技术提供一个完整,通用,可靠的 ...

  2. MongoDB入门系列(一):基础概念和安装

    概述 MongoDB是目前非常流行的一种非关系型数据库,作为入门系列的第一篇本篇文章主要介绍Mongdb的基础概念知识包括命名规则.数据类型.功能以及安装等. 环境: OS:Windows Versi ...

  3. .NET技术面试题系列(1) 基础概念

    这是.NET技术面试题系列第一篇,今天主要分享基础概念. 1.简述 private. protected. public.internal 修饰符的访问权限 private : 私有成员, 在类的内部 ...

  4. Spring Cloud Security OAuth2.0 认证授权系列(一) 基础概念

    世界上最快的捷径,就是脚踏实地,本文已收录[架构技术专栏]关注这个喜欢分享的地方. 前序 最近想搞下基于Spring Cloud的认证授权平台,总体想法是可以对服务间授权,想做一个基于Agent 的无 ...

  5. 快速入门系列--WCF--01基础概念

    转眼微软的WCF已走过十个年头,它是微软通信框架的集大成者,将之前微软所有的通信框架进行了整合,提供了统一的应用方式.记得从自己最开始做MFC时,就使用过Named Pipe命名管道,之后做Winfo ...

  6. 理解 angular2 基础概念和结构 ----angular2系列(二)

    前言: angular2官方将框架按以下结构划分: Module Component Template Metadata Data Binding Directive Service Dependen ...

  7. 关系型数据库基础概念:MySQL系列之开篇

    一.基础概念 数据(Data)是描述事物的符号记录,是指利用物理符号记录下来的.可以鉴别的信息. 1.数据库(Database,DB)是指长期储存在计算机中的有组织的.可共享的数据集合.数据要按照一定 ...

  8. 【Machine Learning】机器学习及其基础概念简介

    机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  9. iOS系列 基础篇 07 Action动作和输出口

    iOS系列 基础篇 07 Action动作和输出口 目录:  1. 前言及案例说明 2. 什么是动作? 3. 什么是输出口? 4. 实战 5. 结尾 1. 前言及案例说明 上篇内容我们学习了标签和按钮 ...

随机推荐

  1. leetcode202

    public class Solution { private int SumSqares(int n) { //将一个数字的各个数位的值分开存储 var list = new List<int ...

  2. hibernate-注解及配置

    联合主键: 一.将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为@Embeddable,最后在主类中(该类不 ...

  3. 前端-CSS-9-文本和字体-背景颜色

    字体属性 div{ width: 300px; height: 100px; /*background-color: red;*/ border: 1px solid red; /*设置字体大小 px ...

  4. UI5-文档-2-开发环境

    这一部分将指导您安装.配置和设置SAPUI5开发环境的最常见和推荐用例. 请注意:您可以在不同的平台上使用SAPUI5.各自平台的许可和维护条件也适用于SAPUI5.例如,如果在SAP云平台上使用SA ...

  5. 在Linux Bash通过上下键快速查找历史命令

    在centos 7中 ~/.bashrc 或者Mac中的 ~/.bash_profile 中添加,然后source一下以下内容: if [[ $- == *i* ]] then bind '" ...

  6. CSS3 弹性盒模型 box-flex

    说明:本文档兼容性测试基础环境为:windows系统:IE6-IE10, Firefox6.0, Chrome13.0, Safari5.1, Opera11.51 语法: box-flex:< ...

  7. Windows 2008开启远程桌面连接

    具体请看下面的截图. 最重要的就是要打开远程允许远程桌面的默认端口 3389 的入站规则,我第一次弄,这一端口没打开,折腾了很久!!! 第一.首先打开“服务器管理器”—“配置”—“高级安全Window ...

  8. pyplot图像组件

    pyplot图像组件 ax子对象的组件内容 Title 图表标题 plt.title() Axis 坐标范围,x轴,y轴 plt.axis() label 坐标轴标注 plt.xlabel() plt ...

  9. spring学习笔记(三)

    spring jdbc spring tx 1.spring的jdbc模板 Spring提供了很多持久层技术的模板类简化编程: 1.1.jdbc模板的基本使用 @Test // JDBC模板的基本使用 ...

  10. 可能空字符串转换为浮点型或者整数型:java.lang.NumberFormatException: For input string: " "

    Integer.valueOf(str.equals("")?"0":str)