高性能消息队列 CKafka 核心原理介绍(上)

时间:2022-09-27 00:10:26

欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~

作者:闫燕飞

1.背景

Ckafka是基础架构部开发的高性能、高可用消息中间件,其主要用于消息传输、网站活动追踪、运营监控、日志聚合、流式处理、事件追踪、提交日志等等需要高性能的场景,目前已经上线腾讯云。Ckafka完全兼容现有的Kafka协议,使现有Kafka用户可以零成本迁入Ckafka。Ckafka基于现有的Kafka进行了扩展开发和优化,为了方便用户理解Ckafka本文也将对Kafka的实现原理进行较为详细的介绍。

2.Kafka原理

2.1 Kafka诞生背景

Kafka是一种高吞吐量的采用发布订阅模式的分布式消息系统,最初由LinkedIn采用Scala语言开发,用作LinkedIn的活动流追踪和运营系统数据处理管道的基础。现已成为Apache开源项目,其主要的设计目标如下:

  1. 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上的数据也能保证常数时间复杂度的访问性能。注:其实对于写Kafka的确保证了O(1)的常数时间性能。但对于读,是segment分片级别对数O(logn)时间复杂度。
  2. 高吞吐率。Kafka力争即使在非常廉价的商用机上也能做到单机支持100Kqps的消息传输能力。
  3. 支持Kafka Server间的消息分区(partition),及分布式消费,同时保证每个partition内的消息顺序传输。注:其实Kafka本身实现逻辑并不做该保证,主要的算法是集中在消费者端,由消费者的分配算法保证,详情下面会介绍。
  4. 同时支持离线数据处理和实时数据处理。
  5. 支持在线水平扩展,Kafka的水平扩展主要来源于其分区(partition)的设计理念。

2.2 主流消息队列对比

  RabbitMQ RocketMQ CMQ Kafka
模式 发布订阅 发布订阅 传统queue/发布订阅 发布订阅
同步算法 GM 同步双写 Raft ISR(Replica)
分布式扩展 支持 支持 支持
堆积能力 磁盘容量 磁盘容量 磁盘(水平扩展) 磁盘(水平扩展)
性能 很高
可靠性 一般 一般 极高 一般
持久化 内存/硬盘 磁盘 磁盘 磁盘

2.3 架构

2.3.1 整体架构图

高性能消息队列 CKafka 核心原理介绍(上)

2.3.2 相关概念介绍

2.3.2.1 zookeeper集群

Kafka系统强依赖的组件。其存储了Kafka核心原数据 (如topic信息配置、broker信息、 消费分组等等,相当于DB充当了Kafka的配置管理中心) 。 Kafka的leader选举(如coordinator选举、controller选举、partition leader选举等等),同样也会借助于zookeeper。

2.3.2.2 coordinator

coordinator协调器模块,主要用来管理消费分组和消费offset,充当中介管理消费者并从消费分组中选举出一个消费者作为leader,然后将消费分组中所有消费者信息发往该leader由该leader负责分配partition。该模块为Kafka 0.9版本新加入的新的模块,Kafka集群中可以存在多个协调器分别管不同的消费分组,提高整个系统的扩展能力,主要用于解决之前消费者(high level消费者api)都需要通过与zookeeper连接进行相关的选举,导致zookeeper压力大、惊群及脑裂问题。

2.3.2.3 controller

controller模块,主要负责partition leader选举、监听创建及删除Topic事件然后下发到指定broker进行处理等功能,整个Kafka集群中只能有一个controller,Kafka利用zookeeper的临时节点特性来进行controller选举。

2.3.2.4 Broker

消息缓存代理,Kafka集群包含一个或多个服务器,这些服务器被称为Broker,负责消息的存储于转发,作为代理对外提供生产和消费服务。

2.3.2.5 Topic

消息主题(类别),逻辑上的概念,特指Kafka处理的消息源的不同分类,用户可以根据自己的业务形态将不同业务类别的消息分别存储到不同Topic。用户生产和消费时只需指定所关注的topic即可,不用关注该topic的数据存放的具体位置。

2.3.2.6 Partition

Topic物理上的分组,在创建Topic时可以指定分区的数量,每个partition是一个有序的队列,按生产顺序存储着每条消息,而且每条消息都会分配一个64bit的自增长的有序offset(相当于消息id)。Partition是整个Kafka可以平行扩展的关键因素。

2.3.2.7 Replication

副本,topic级别的配置,可以理解为topic消息的副本数。Kafka 0.8版本加入的概念,主要目的就是提高系统的可用性。防止broker意外崩溃导致部分partition不可以服务。

2.3.2.8 ISR

In-Sync Replicas ,Kafka用来维护跟上leader数据的broker列表,当leader崩溃后,优先从该列中选举leader

2.3.2.9 Producer

Producer 生产者,采用Push方式进行消息发布生产。Producer可以通过与zookeeper连接获取broker信息, topic信息等等元数据,然后再与broker交互进行消息发布。在此过程中zookeeper相当于一个配置管理中心(类似于Name Server提供相关的路由信息)。采用直接向Producer暴露zookeeper信息存在以下两个非常大的弊端:

  1. zookeeper属于整个Kafka系统的核心结构,其性能直接影响了整个集群的规模,故当暴露给生产者过多的生产者会导致zookeeper性能下降最终影响整个Kafka集群的规模和稳定性。
  2. zookeeper存储着Kafka的核心数据,若公开暴露出去则容易受到恶意用户的攻击,最终导致Kafka集群不可服务,故非常不建议Kafka服务提供方向使用者暴露zookeeper信息。

正因为存在上面的问题,Kafka也提供了Metadata RPC,通过该RPC生产者可以获取到broker信息、topic信息以及topic下partition的leader信息,然后生产者在访问指定的broker进行消息生产,从而对生产者隐藏了zookeeper信息使的整个系统更加安全、稳定、高效。

2.3.2.10 Consumer

消费者,采用Pull方式,从Broker端拉取消息并进行处理。当采用订阅方式(一般通过使用consumer high level api或new consumer来进行订阅)订阅感兴趣的Topic时,Consumer必须属于一个消费分组,而且Kafka保证同一个Topic的一条消息只能被同一个消费分组中的一个Consumer消费,但多个消费分组可以同时消费这一条消息。

其实Kafka本身不对这个(同一个topic的一条消息只能被同一个消费分组中一个消费者消费)做任何保证,尤其是在0.9版本之前Kafka Broker根本都没有消费分组的概念也没有消费offset概念,Kafka只是提供FetchMessage RPC供使用者去拉取消息,至于是谁来取,取多少次其根本不关心,该保证是由消费者api内部的算法自己完成。

在0.9版本之前消费分组只是消费者端的概念,同一个消费分组的所有消费者都通过与zookeeper连接注册,然后自主选择一个leader(一个消费分组一个leader),再通过该leader进行partition分配(分配算法默认是range,也可以配置成round robin甚至自己实现一个算法非常的灵活)。所有消费者都按照约定访问分配给自己的partition,并且可以选择将消费offset保持在zookeeper或自己存。该方式会暴露zookeeper从而导致存在和暴露zookeeper给Producer一样的问题,并且因为任何一个消费者退出都会触发zookeeper事件,然后重新进行rebalance,从而导致zookeeper压力非常大、而且还存在惊群及无法解决的脑裂问题,针对这个问题0.9版本(含)之后,Kafka Broker添加了coordinator协调器模块。

但coordinator模块也未进行任何分配算法相关的处理,只是替换了zookeeper的一些功能,充当了中介将之前消费者都要通过zookeeper自己选择leader, 变成统一和coordinator通信,然后由coordinator选择leader,然后将同一个消费分组中的消费者都发送给leader(消费者api),由leader负责分配。另一个方面就是coordinator当前多了管理offset的功能,消费者可以选择将offset提交给coordinator,然后由coordinator进行保存,当前默认情况下coordinator会将offset信息保存在一个特殊的topic(默认名称_consumer_offsets)中,从而减少zookeeper的压力。消费分组中partition的分配具体可以看下一个小结中消费分组的相关说明。

2.3.2.11 Consumer Group

消费分组,消费者标签,用于将消费者分类。可以简单的理解为队列,当一个消费分组订阅了一个topic则相当于为这个topic创建了一个队列,当多个消费分组订阅同一个topic则相当于创建多个队列,也变相的达到了广播的目的,而且该广播只用存储一份数据。 为了方便理解,通过下面的图片对消费分组相关概念进行讲解。

高性能消息队列 CKafka 核心原理介绍(上)

  1. 一个消费分组可以订阅多个topic,同理一个topic可以被多个消费分组订阅
  2. topic中的partition只会分配给同一个消费分组中的一个消费者,基于这种分配策略,若在生产消息时采用按照消息key进行hash将同一个用户的消息分配到同一partition则可以保证消息的先进先出。Kafka正是基于这种分配策略实现了消息的先进先出。
  3. 同一个消费分组中,不同的消费者订阅的topic可能不一样,但Kafka的partition分配策略保证在同一个消费分组的topic只会分配给订阅了该topic的消费者,即消费分组中会按照topic再划分一个维度。以上图为例Consumer group1中C1和C2同时订阅了Topic 1所以将Topic1下面的P0 ~ P3四个partition均分给C1和C2。同样Consumer group1中只有C1订阅了Topic0故Topic0中的两个partition只分配给了C1未分配给C2。

2.3.2.12 Message

消息,是通信和存储的最小单位。其包含一个变长头部,一个变长key,和一个变长value。其中key和value是用户自己指定,对用户来说是不透明的。Message的详细格式下面会有介绍,这里先不展开说明。

下一篇:《高性能消息队列 CKafka 核心原理介绍(下)》

相关阅读

如何更优雅地使用 Redux

图表组件常见设置

腾讯云分布式高可靠消息队列 CMQ 架构


此文已由作者授权腾讯云技术社区发布,转载请注明文章出处

原文链接:

此文已由作者授权腾讯云技术社区发布,转载请注明文章出处

原文链接:https://www.qcloud.com/community/article/549934

高性能消息队列 CKafka 核心原理介绍(上)的更多相关文章

  1. 基于消息队列 RocketMQ 的大型分布式应用上云最佳实践

    作者|绍舒 审核&校对:岁月.佳佳 编辑&排版:雯燕 前言 消息队列是分布式互联网架构的重要基础设施,在以下场景都有着重要的应用: 应用解耦 削峰填谷 异步通知 分布式事务 大数据处理 ...

  2. 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转

    线程安全使用(四)   这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...

  3. RocketMQ读书笔记5——消息队列的核心机制

    [Broker简述] Broker是RocketMQ的核心,大部分“重量级”的工作都是由Broker完成的,包括: 1.接受Producer发过来的消息: 2.处理Consumer的消费信息请求: 3 ...

  4. 消息队列mq的原理及实现方法

    消息队列技术是分布式应用间交换信息的一种技术.消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走.通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置.或在继续执行前不需要等待 ...

  5. 【转】diamond专题(二)– 核心原理介绍

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  6. 高性能消息队列(MQ)Kafka 简单由来介绍(1)

    Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据. 这种动作(网页浏 ...

  7. 高性能消息队列NSQ

    前言 最近我再网上寻找使用golang实现的mq,因为我知道golang一般实现的应用部署起来很方便,所以我就找到了一个叫做nsq的mq,其实它并不能完全称为队列,但是它的轻量和性能的高效,让我真的大 ...

  8. golang:高性能消息队列moonmq的简单使用

    在上一篇moonmq的介绍中(这里),我仅仅简短的罗列了一些moonmq的设计想法,但是对于如何使用并没有详细说明,公司同事无法很好的使用. 对于moonmq的使用,其实很简单,样例代码在这里,我们只 ...

  9. 分布式消息队列RocketMQ与Kafka架构上的巨大差异

    分布式消息服务 Kafka 是一个高吞吐.高可用的消息中间件服务,适用于构建实时数据管道.流式数据处理.第三方解耦.流量削峰去谷等场景,具有大规模.高可靠.高并发访问.可扩展且完全托管的特点,是分布式 ...

随机推荐

  1. DDN - Digital Data Network

    DDN(Digital Data Network,数字数据网)是一种利用光纤.数字微波或卫星等数字传输通道和数字交叉复用设备组成的数字数据传输网.它可以为用户提供各种速率的高质量数字专用电 数字数据网 ...

  2. Segment-Based stereo matching

    首先代码实现是根据"Segment-Based Stereo Matching Using Belief Propogation and Self-Adapting Dissimilarit ...

  3. 繁华模拟赛day8 牛栏

    /* 标称并没有用到题解中提到的那种奇妙的性质,我们可以证明,正常从1开始走的话,需要T次,如何使这个次数减小?题解中提到一个办法,有一步小于n/t,我们考虑这一步,如果把它匀到左右两步中,则可以减小 ...

  4. javascript中静态方法、实例方法、内部方法和原型的一点见解

    1.静态方法的定义 var BaseClass = function() {}; // var BaseClass=new Function(); BaseClass.f1 = function(){ ...

  5. UC 浏览器远程调试手机web网页记录

    浏览器远程调试插件有很多,本来要使用chrome浏览器的调试插件的,但是需要FQ才能使用(公司网络有限制,果断放弃),最终选择使用UC浏览器的. 其实UC官网插件使用已经介绍的很详细了,但是有几处坑需 ...

  6. This application failed to start because it could not find or load the Qt platform plugin “windows”错误解决方法

    这是一个困扰我很久的问题,关于Qt下生成的exe文件在没有安装Qt的机器上无法运行的问题.Qt是编写C++图形界面的一个很好工具,比MFC来的直观.可是,Qt的安装却是一个让人头疼的事情.早在上个学期 ...

  7. git创建和删除远程分支

    问题描述:           使用git创建和删除远程分支 问题解决:              (1)git创建本地分支 注:            如上所示,使用命令 git branch -a ...

  8. Swift流程控制之循环语句和判断语句详解

    Swift提供了所有c类语言的控制流结构.包括for和while循环来执行一个任务多次:if和switch语句来执行确定的条件下不同的分支的代码:break和continue关键字能将运行流程转到你代 ...

  9. Linux通配符摘要

    参考<鸟哥linux私房菜> * - 通配符,代表随机字符(0对于许多) ? - 通配符,它代表一个字符 # - 凝视 / - 跳转符号,将特殊字符或通配符还原成一般符号 | - 分隔两个 ...

  10. Jmeter中使用SSH插件,连接远程linux机器执行命令

    一.Why 在云主机测试中,需要使用SSH协议连接云主机进行相关操作 在python中使用paramiko库很好实现,在如果要使用jmeter做性能测试时,怎么做? 二.解决 既然原生jmeter没有 ...