kafka原理看这一篇就够了

为何使用消息队列

  • 异步。接口方式实现多个系统协作,如图A系统作为用户请求接收方,需要调用多个系统的接口,这些接口还有可能是在A系统里同步调用,所以最后的接口耗时是多个系统接口耗时的总和;mq方式则可以异步发送消息给mq,mq再发送给其他多个系统,多个系统并行且异步的接收消息。当然,mq方式实现有一个前提是用户的请求不需要立即返回请求结果,例如用户发送一个查询请求就不适合mq方式。mq方式多用于传递事件,如发送优惠券、秒杀等。

  • 削峰。用户的请求大部分都集中在固定的时间段,而在晚间凌晨或者用户使用低峰期基本没什么请求。所以mq的削峰就是为了将高峰期的请求泄洪一部分到低峰期。
  • 解耦。接口方式发送消息,发送者调用接口,接收者提供接口,此时发送者作为消息生产者(如图中的A系统)作为主动的一方需要适配上游的各个类型的接口,它们的传输协议、参数、返回值等可能都不一样,同时各个接收方还不能拒收消息,这些都会带来极大的工作量;mq方式发送消息,消息发送者变成了上游,现在只需要将统一格式的消息发送给mq,由mq来控制消息的存储、容灾以及消息是否送达等。消息接收者则遵守消息的统一格式即可,如果不想接收消息可以取消订阅。这样就达到了生产者和消费者之间的解耦效果。

kafka的总体架构

  • Producer:消息的生产者,即消息的入口。
  • Broker:kafka的一个实例,一台kafka服务器上会有一个或多个实例。多台kafka服务构成了kafka的集群。
  • Topic:消息的主题,生产者按照主题发送消息,消费者按照主题接收消息,一个Broker可以有多个主题。
  • Partition:Topic的分区,一个Topic可以有多个分区,分区越多可以并行处理消息的能力越强。同一个Topic上的不同分区消息是不重复的,Partition的本质是文件夹。
  • Replication:Partition的副本,副本用来做数据备份。副本分为主分区副本(Leader)和从分区副本(Follower),它们不能同时出现在一个Broker上。主分区副本负责消息的接收并写入,从分区副本不接收生产者发来的消息,它的唯一职责就是从主分区副本同步过来消息。当主分区副本挂掉的时候,会在从分区副本中选出一个新的Leader作为主分区副本。kafka中一个Partition的最大副本数量是10个,且副本数量不能大于Broker的数量。
  • Consumer:消息的消费者,即消息的出口。
  • Consumer Group:多个消费者组成一个消费组,消费组之间可以重复消费消息。同一个消费组的某一个Partition不能同时被多个消费者消费。
  • Zookeeper:kafka集群依赖Zookeeper保存集群的元信息,以保证kafka集群的可靠性。kafka从2.8版本以后使用其内部的Quorum控制器来代替Zookeeper。

生产者写数据

生产者发送消息给Leader分区副本,并顺序写入到磁盘文件,然后Follower分区副本从Leader分区副本poll消息以保证数据是最新的。kafka将消息写入哪个分区有几下几个原则:

  • 生产者指定了分区,写入对应的分区
  • 生产者没有指定分区,但设置了数据库的key,根据key的hash值算出一个分区
  • 生产者既没有指定分区,也没有设置key,轮询出一个分区

topic本质是一个目录,而topic又是由一些Partition Logs(分区日志)组成。消息采用hash取模的分区算法有序的写入到Partitionp Log上。

producer在将消息写入partition之前会先在内存中缓存,累计到一定量后(按数量、按时间间隔或按数据大小),再批量写入。

一般一条消息大概1~10kB,推荐不要超过1MB。

kafka默认数据保留7天时间。如果数据量大可以修改配置(log.retention.hours)将时间缩短。

消费者读数据

与生产者一样,消费者主动的从Leader分区副本拉取消息。每成功拉取一条partition的消息,partition的消息游标卡尺(offset)就会加1。

partition里的offset默认配置是从最新一条开始消费,也可以配置from beginning从0开始消费。

在同一个消费组里,消费者和partition的关系是1:1或者1:n,不能出现消费者与partition是n:1的情况,意思是同一个消费组里消费者数量要小于等于parition的数量。因为不这样做就会造成多个消费者共享一个offset,从而就不能保证一个partition内的消息的顺序性,也会造成消息被重复消费的安全问题,这是一种不稳定的重复消费。

如果想要稳定的重复消费同一条消息,可以设置两个消费组。两个组内的消费者消费同一个partition时,offset是相互独立的。

消息的有序性

想要保证消息被消费的有序性,有以下两个方法:

  • 一个topic只设置一个partition。缺点是消费组里只能有一个消费者消费,不适用高并发场景。
  • producer将需要保证顺序的消息发送到同一个partition。两种方式指定:1、指定partition;2、不指定partition,根据key的hash值运算后得到partition。

消息的可靠性

kafka的数据是可持久化的写在Partition Log文件里。每个topic都可以设置副本数量。副本数量决定了有几个broker来存放写入的数据。

consumer和partition数量的关系是:partition数 >= 同一个消费组里的consumer数。因为一个partition只能被同一个消费组的一个consumer消费(但一个consumer可以消费多个partition)。这是为了消息在一个partition里的顺序读。

生产端消息可靠性

分区副本

所有的读写请求都发往leader副本所在的broker,follower副本不处理客户端请求,它唯一的任务就是从leader副本异步拉取消息。

Kafka默认的副本因子是3,即每个分区只有1个leader副本和2个follower副本。

同步副本(In-sync replicas)

ISR同步副本机制是用来判断follower是否同步了leader的最新数据。

ISR列表保存了与leader已经同步的副本,leader自己是长期存在于ISR列表。当follower副本超过设定的时间间隔(replica.lag.time.max.ms)没有和leader同步,就会被踢出ISR列表,反之则不会被踢出。

acks参数(生产者配置)

acks参数,表示有多少的分区副本收到消息,才能认为消息是写入成功的。

  • acks=0。不需要副本收到消息,producer就能收到broker的响应。该模式吞吐量高,但安全性低,容易丢消息。

  • acks=1(默认)。只要leader副本接收到了消息并写入到磁盘,producer就能收到broker的响应。需要注意的是这种模式依然会有丢消息的安全问题。例如,当leader副本收到消息以后还没来得及同步副本到follower就宕机了,此时producer已经收到了成功的响应,但follower变为新的leader时还未将最新的那条消息同步过来。

  • acks=all(或-1)。只有ISR列表里的所有分区副本都收到消息,producer才能收到broker的响应。该模式延迟最高。

acks=all模式下,有一个最小副本配置(min.insync.replicas)。该配置默认值是1,只在acks=all时生效。该参数控制消息最少被多少个副本写入才算成功写入。即ISR列表的副本最小数量。因为ISR列表始终要有leader副本,所以如果该配置默认是1,实际上是起不到副本作用的,所以该配置最好配置为大于1的数。

当leader副本宕机时,acks=all模式下,会在ISR列表中选举一个新的broker作为leader。

  • 增大min.insync.replicas。可以增加数据的可靠性。
  • 减小min.insync.replicas。可以增加系统的可用性。

消费端消息可靠性

要想实现消费端的消息可靠性,必须抓住两点:

  • 保证消息到达的状态(offset)和本地事务的状态保持一致。
  • 保证消费的幂等性。

要想保证消费端消息的可靠性,首先必须保证提交offset和提交本地事务要么一起成功,要么一起失败。我们以自动提交offset和手动提交offset分别举例说明。

  • 自动提交offset。消息到达消费客户端,不论本地事务是否提交成功,offset都会自动提交。一旦本地事务提交失败,就会造成消息丢失的问题。
  • 手动提交offset。有三种方法:
    • 第一种方式是消费端KafkaListener不配置本地事务,业务代码执行完后数据入库,最后再提交offset,即使offset提交失败,只要保证业务代码的幂等性,消息重复消费也可以接受。
    • 第二种方式是消费端KafkaListener配置本地事务,将offset的值写道数据库里和业务数据一起提交,这样就将业务数据和offset做了绑定关系,在消费一开始就根据业务id和offset判断消息是否消费过,如果没有消费过才执行业务代码。
    • 第三种方式是前两种方式的结合,这种方式不需要将offset入库。该方法在消费端KafkaListener配置本地事务,先执行业务代码最后执行offset提交,这样业务代码失败就不会执行提交offset的代码;而如果是最后提交offset失败,本地事务也会回滚。

在实际的运用中,考虑到数据库事务相对性能较差,可以把本地事务和offset的绑定关系用缓存来保存。

kafka优化

kafka削峰的几种方法:

  • 增加分区。增加分区数可以提高消息并行处理的能力。当然也会增加集群的维护成本,需要权衡。
  • 使用消费组。使用消费组可以让多个消费者并行消费一个partition的消息,因为每个消费组在同一个partition的offset不是共享的。但是为了避免重复消费消息,需要为不同消费组上的多个消费者指定所消费消息的key。
  • 增加副本数。可以提高kafka的吞吐量,提升kafka的可靠性和容错性。

此外,修改一些kafka配置参数也能达到一定的优化效果。例如,

  • 为了减少每次发送/拉取消息的次数,可以提高消息发送/拉取的消息数量/数据大小的阈值,或者增加时间间隔。减少消息发送/拉取的次数意味着一次发送/拉取的量比较大,所以还要注意提高会话超时、拉取超时的时间间隔,以免触发rebalance。
  • 减小并行度(concurrency)。当concurrency=3时,就会有4*3=12个Consumer线程,12个Listener线程。减小concurrency可以减少客户端线程数量。

kafka和rocketmq

目前消息队列用的比较多的就是kafka和rocketmq了。我们可以比较一下这两种消息队列的优缺点。

  • 适用场景

topic较多时推荐使用rocketmq;topic少时kafka性能更佳。因为kafka一个topic一个partition文件,rocketmq是多个topic一个文件。

kafka适合日志处理、大数据领域;rocketmq适合业务处理。

  • 性能

kafka的tps在百万条/秒;rocketmq大约10万条/秒。

  • 可靠性

kafka异步刷盘,异步副本;recketmq异步/同步刷盘,异步/同步副本。

  • 支持队列数量

kafka单机最大支持64个队列/分区,增加分区性能降低严重;rocketmq单机最大支持5w队列,性能稳定。

  • 消息顺序性

kafka在同一个partition下支持消息顺序性,但如果一台broker宕机会打乱顺序;rocketmq支持消息顺序性,一台broker宕机消息会发送失败,但顺序性依然可以保证。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/172112.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

终于有人把数据资产入表知识地图总结出来了,轻松看懂

在当前数字化的浪潮下,数据已经成为劳动、土地、知识、技术以后的第五大生产要素,“数据就是资源”已成为共识。如今数据资产“入表”已成定局,数据资产化迫在眉睫。 2023年8月21日,财政部正式印发《企业数据资源相关会计处理暂行…

[Linux] 进程入门

💻文章目录 📄前言计算机的结构体系与概念冯诺依曼体系结构操作系统概念目的与定位 进程概念描述进程-PCBtask_struct检查进程利用fork创建子进程 进程状态进程状态查看僵尸进程孤儿进程 📓总结 📄前言 作为一名程序员&#xff0c…

Django学习日志09

choices参数的使用 """对于以上可能被我们列举完的字段我们一般都是选择使用choices参来做""" class UserInfo(models.Model):username models.CharField(max_length64)password models.CharField(max_length32)# 先写一个映射关系gender_cho…

从零开始的搭建指南:开发高效的抖音预约服务小程序

预约服务小程序提高了效率,节省了用户时间。下文,小编将与大家一同探讨如何从零开始打造预约服务小程序。 第一步:明确需求和目标 确定你的小程序主要服务领域是什么?是医疗预约、美容美发、餐厅预订还是其他行业?明…

【C++ 学习 ㊴】- 详解 C++ 的 I/O 流

目录 一、C 的 I/O 流 二、C 的标准 I/O 流 三、C 的文件 I/O 流 一、C 的 I/O 流 C 语言有一套完成数据读写(I/O)的解决方案: 使用 scanf()、gets() 等函数从键盘读取数据,使用 printf()、puts() 等函数向屏幕输出数据&#…

Web前端—移动Web第三天(移动Web基础、rem、less、综合案例—极速问诊)

版本说明 当前版本号[20231120]。 版本修改说明20231120初版 目录 文章目录 版本说明目录移动 Web 第三天01-移动 Web 基础谷歌模拟器屏幕分辨率视口二倍图适配方案 02-rem简介媒体查询rem 布局flexible.jsrem 移动适配 03-less注释运算嵌套变量导入导出禁止导出 04-综合案例…

【用unity实现100个游戏之16】Unity程序化生成随机2D地牢游戏2(附项目源码)

文章目录 先看看最终效果前言生成走廊生成房间修复死胡同增加走廊宽度获取走廊位置信息集合方法一方法二 源码完结 先看看最终效果 前言 上期已经实现了房间的生成,本期紧跟着上期内容,生成走廊并结合上期内容生成连通的房间。 生成走廊 修改Procedur…

WPF Button点击鼠标左键弹出菜单

目录 ContextMenu介绍WPF实现点击鼠标左键弹出菜单如何禁用右键菜单如何修改菜单样式菜单位置设置 本篇博客介绍WPF点击按钮弹出菜单,效果如下: 菜单的位置、央视可以自定义。 实现技巧:不在xaml里菜单,在按钮左键按下的点击事件里…

Linux系统编程 系统编程概念

1.系统调用 系统调用(system call)其实是 Linux 内核提供给应用层的应用编程接口(API),是 Linux 应用层进入内核的入口。不止 Linux 系统,所有的操作系统都会向应用层提供系统调用,应用程序通过…

每日汇评:美日在两个月低点附近似乎较为脆弱,熊市可能会在FOMC会议纪要公布前暂停

美元/日元跌至两个月低点,并受到多种因素的压力; 美联储鸽派预期和美国债券收益率下降继续令美元承压; 美日利差缩小以及日本央行政策转变的押注提振了日元; 美元/日元货币对在周二持续第四天承受着沉重的卖压,同时也标…

jenkins-2.426.1-1.1.noarch.rpm 的公钥没有安装

执行命令 yum install jenkins 报错 jenkins-2.426.1-1.1.noarch.rpm 的公钥没有安装 下载的软件包保存在缓存中,直到下次成功执行事务。 您可以通过执行 yum clean packages 删除软件包缓存。 错误:GPG 检查失败 解决办法: 1、安装新的公…

Linux上通过SSL/TLS和start tls连接到LDAP服务器(附C++代码实现认证流程)

一,大致流程。 1.首先在Linux上搭建一个LDAP服务器 2.在LDAP服务器上安装CA证书,服务器证书,因为SSL/TLS,start tls都属于机密通信,需要客户端和服务器都存在一个相同的证书认证双方的身份。3.安装phpldapadmin工具&am…

集群创建(flannel)时候,没有自动创建出cni0网卡

给旧的集群加入四台新的服务器启动时候发现都是正常的,但是pod通信报错 集群通信失败,第一时刻想看看是不是cni0和flannel.1的网段是不是通的,点进去一看发现cni0网卡没有生成。 部署是通过kubeadm方式部署的集群,目前有两种解决…

数据库表的内连接和外连接

1.内连接查询语法 -- 隐式内链接 SELECT 字段列表 FROM 表1,表2WHERE 条件; -- 显示内连接 select 字段列表 from 表1 [inner] join 表2 on 条件; 如果两个表没用进行内连接,会生成笛卡尔积。A集合和B集合全部元素进行排列组合。 …

Oracle数据库安装踩坑记录

Oracle数据库安装踩坑记录 踩坑目录 可能会用到的教程1. 管理员用户(sys)登录oracle命令2. 默认密码:三个 如果忘记改密码参考 1. 登录后修改密码3. 查看账号密码:只有sys用户登录后才能查看4. sqldeveloper 连接oracle数据库5. o…

logic-flow 使用过程中遇到的bug - 拖动节点到画布的时候,鼠标松开,节点不落在画布,仍旧跟着鼠标走

背景: 插件:logicFlow 用途:画流程图 bug表现: 初始化的样子: bug的样子: 拖动第一个节点的时候,一切正常(无论哪个节点作为第一个节点,都是正常的,但是拖动…

渗透实例------2个星期艰难的渗透纪实

2个星期艰难的渗透纪实 kyo327 入侵原因,需删一帖子,目标用www.111.com代替,前期通过初期的网站文件暴力猜解,扫描到robots.txt这个文件,有以下目录。如图1: 图1 再通过对这些文件的访问,从3gadm.php文件的标题栏得到该网站采用的是diy-page8.3的cms,自然可以先用搜索…

SpringBoot-Docker容器化部署发布

在生产环境都是怎么部署 Spring Boot? 打成 jar 直接一键运行打成 war 扔到 Tomcat 容器中运行容器化部署 一、准备Docker 在 CentOS7 上安装好 Docker 修改 Docker 配置,开启允许远程访问 Docker 的功能,开启方式很简单,修改 /usr/lib/s…

使你的软文更具说服力的技巧,媒介盒子分享

软文想要写好除了日常素材积累和思维的训练外,还需要充分的前期策划,这样才能使软文的写作效果更好,今天媒介盒子就来和大家分享,使你的软文更具说服力和吸引力的技巧! 一、 受众分析 了解受众的基本属性这样能使写作…

每日一练:X加上100为完全平方数,再加上168任然为完全平方数

题目 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 实现方式1 解题思路 设整数为x,根据题意建立方程:   (1) x 100 是一个完全平方数,即存在整数a满…
最新文章