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

作者:闫燕飞

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 整体架构图

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则相当于创建多个队列,也变相的达到了广播的目的,而且该广播只用存储一份数据。 为了方便理解,通过下面的图片对消费分组相关概念进行讲解。

  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. 消息队列MQ核心原理全面总结(11大必会原理)

    消息队列已经逐渐成为分布式应用场景.内部通信.以及秒杀等高并发业务场景的核心手段,它具有低耦合.可靠投递.广播.流量控制.最终一致性 等一系列功能. 无论是 RabbitMQ.RocketMQ.Act ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. 高性能消息队列NSQ

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

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

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

随机推荐

  1. NodeJS项目迁移兼Ubuntu下NodeJS环境部署

    前言 之前做的几个项目都托管在阿里云服务器,但是最近要到期了.想着到底要不要续期,毕竟100/月.后面看着阿里云有个活动,800/三年.果断买下.环境部署折腾了一天,其中也遇到几个坑. 目录 一.安装 ...

  2. javaScript获取url问号后面的参数

    javaScript获取url问号后面的参数方法 function GetRequest() { var url = location.search; //获取url中"?"符后的 ...

  3. [js高手之路]es6系列教程 - 解构详解

    解构通俗点说,就是通过一种特定格式,快捷的读取对象/数组中的数据的方法, es6之前,我们通过对象名称[键] 读取数据 var User = { 'name' : 'ghostwu', 'age' : ...

  4. Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

    我用String代替了链表显示,本题的大意是每k个进行逆序处理,剩下的不够k个的就按照原顺序保留下来. public class ReverseNodes { public static void m ...

  5. laravel框架cookie应用到中间件的理解

    昨天博主接到一个委托的需求,大数据同事想要在请求日志抓取数据,希望在我的每个页面进行cookie的种植,方便他们进行定位分析,我思考了一下,简单呀,首先考虑的是通过中间件进行cookie种植,但是随后 ...

  6. 浅谈JavaScript和DOM中的类数组对象

    JavaScript是一门弱类型语言,它的数据类型分为两大类:简单数据类型(5种:Undefined.Null.Boolean.Number.String)和复杂数据类型(1种:Object).Obj ...

  7. Linux系统中cgroup功能介绍

    1  Cgroups简介 1.1 What are cgroups ? Cgroups(控制组)是Linux内核的一个功能,用来限制.统计和分离一个进程组的资源(CPU.内存.磁盘输入输出等).换句话 ...

  8. Oracle SQL优化[转]

    Oracle SQL优化 1. 选用适合的ORACLE优化器 ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性) 设置缺省的优化 ...

  9. Ext.NET加入自定义验证JS函数

    ExtJS验证很方便,在使用FormPanel的时候,我们可以很方便的进行验证.比如设置必填项.正则.字段类型等等.比如如下所示: 上面的验证是这么写的: 1 2 3 <Listeners> ...

  10. 关于Filter

    [1].关于Filter Filter简介: Filter翻译为中文是过滤器的意思. Filter是JavaWeb的三大web组件之一Servlet.Filter.Listener Filter的作用 ...