浅谈分布式消息技术 Kafka
| Kafka的基本介绍Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。主要应用场景是:日志收集系统和消息系统。Kafka主要设计目标如下:以时间复杂度为O(1)的方... | ||||||||||||||||||
|
Kafka的基本介绍 Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。 主要应用场景是:日志收集系统和消息系统。 Kafka主要设计目标如下:
Kafka的设计原理分析
一个典型的kafka集群中包含若干producer,若干broker,若干consumer,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance。producer使用push模式将消息发布到broker,consumer使用pull模式从broker订阅并消费消息。 Kafka专用术语:
Kafka数据传输的事务特点
通常情况下"at-least-once"是我们首选。 Kafka消息存储格式 Topic & Partition 一个topic可以认为一个一类消息,每个topic将被分成多个partition,每个partition在存储层面是append log文件。
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。
这样做的好处就是能快速删除无用文件,有效提高磁盘利用率。
segment中index与data file对应关系物理结构如下:
上图中索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。 其中以索引文件中元数据3,497为例,依次在数据文件中表示第3个message(在全局partiton表示第368772个message),以及该消息的物理偏移地址为497。 了解到segment data file由许多message组成,下面详细说明message物理结构如下:
参数说明:
副本(replication)策略 Kafka的高可靠性的保障来源于其健壮的副本(replication)策略。 1) 数据同步 kafka在0.8版本前没有提供Partition的Replication机制,一旦Broker宕机,其上的所有Partition就都无法提供服务,而Partition又没有备份数据,数据的可用性就大大降低了。所以0.8后提供了Replication机制来保证Broker的failover。 引入Replication之后,同一个Partition可能会有多个Replica,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据。
2) 副本放置策略 为了更好的做负载均衡,Kafka尽量将所有的Partition均匀分配到整个集群上。 Kafka分配Replica的算法如下:
假设集群一共有4个brokers,一个topic有4个partition,每个Partition有3个副本。下图是每个Broker上的副本分配情况。
3) 同步策略 Producer在发布消息到某个Partition时,先通过ZooKeeper找到该Partition的Leader,然后无论该Topic的Replication Factor为多少,Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。Follower在收到该消息并写入其Log后,向Leader发送ACK。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK。 为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中。因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。 Consumer读消息也是从Leader读取,只有被commit过的消息才会暴露给Consumer。 Kafka Replication的数据流如下图所示:
对于Kafka而言,定义一个Broker是否“活着”包含两个条件:
Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)。如果一个Follower宕机,或者落后太多,Leader将把它从ISR中移除。这里所描述的“落后太多”指Follower复制的消息落后于Leader后的条数超过预定值或者Follower超过一定时间未向Leader发送fetch请求。 Kafka只解决fail/recover,一条消息只有被ISR里的所有Follower都从Leader复制过去才会被认为已提交。这样就避免了部分数据被写进了Leader,还没来得及被任何Follower复制就宕机了,而造成数据丢失(Consumer无法消费这些数据)。而对于Producer而言,它可以选择是否等待消息commit。这种机制确保了只要ISR有一个或以上的Follower,一条被commit的消息就不会丢失。 4) leader选举 Leader选举本质上是一个分布式锁,有两种方式实现基于ZooKeeper的分布式锁:
Majority Vote的选举策略和ZooKeeper中的Zab选举是类似的,实际上ZooKeeper内部本身就实现了少数服从多数的选举策略。kafka中对于Partition的leader副本的选举采用了第一种方法:为Partition分配副本,指定一个ZNode临时节点,第一个成功创建节点的副本就是Leader节点,其他副本会在这个ZNode节点上注册Watcher监听器,一旦Leader宕机,对应的临时节点就会被自动删除,这时注册在该节点上的所有Follower都会收到监听器事件,它们都会尝试创建该节点,只有创建成功的那个follower才会成为Leader(ZooKeeper保证对于一个节点只有一个客户端能创建成功),其他follower继续重新注册监听事件。 Kafka消息分组,消息消费原理 同一Topic的一条消息只能被同一个Consumer Group内的一个Consumer消费,但多个Consumer Group可同时消费这一消息。
这是Kafka用来实现一个Topic消息的广播(发给所有的Consumer)和单播(发给某一个Consumer)的手段。一个Topic可以对应多个Consumer Group。如果需要实现广播,只要每个Consumer有一个独立的Group就可以了。要实现单播只要所有的Consumer在同一个Group里。用Consumer Group还可以将Consumer进行自由的分组而不需要多次发送消息到不同的Topic。 Push vs. Pull 作为一个消息系统,Kafka遵循了传统的方式,选择由Producer向broker push消息并由Consumer从broker pull消息。 push模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。push模式的目标是尽可能以最快速度传递消息,但是这样很容易造成Consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据Consumer的消费能力以适当的速率消费消息。 对于Kafka而言,pull模式更合适。pull模式可简化broker的设计,Consumer可自主控制消费消息的速率,同时Consumer可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。 Kafak顺序写入与数据读取 生产者(producer)是负责向Kafka提交数据的,Kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度Kafak采用了两个技术,顺序写入和MMFile。 顺序写入 因为硬盘是机械结构,每次读写都会寻址,写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最“讨厌”随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。 每条消息都被append到该Partition中,属于顺序写磁盘,因此效率非常高。
对于传统的message queue而言,一般会删除已经被消费的消息,而Kafka是不会删除数据的,它会把所有的数据都保留下来,每个消费者(Consumer)对每个Topic都有一个offset用来表示读取到了第几条数据。
即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。 在Linux Kernal 2.2之后出现了一种叫做“零拷贝(zero-copy)”系统调用机制,就是跳过“用户缓冲区”的拷贝,建立一个磁盘空间和内存空间的直接映射,数据不再复制到“用户态缓冲区”系统上下文切换减少2次,可以提升一倍性能。
通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存)。使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销(调用文件的read会把数据先放到内核空间的内存中,然后再复制到用户空间的内存中。) 消费者(读取数据) 试想一下,一个Web Server传送一个静态文件,如何优化?答案是zero copy。传统模式下我们从硬盘读取一个文件是这样的。
先复制到内核空间(read是系统调用,放到了DMA,所以用内核空间),然后复制到用户空间(1、2);从用户空间重新复制到内核空间(你用的socket是系统调用,所以它也有自己的内核空间),最后发送给网卡(3、4)。
Zero Copy中直接从内核空间(DMA的)到内核空间(Socket的),然后发送网卡。这个技术非常普遍,Nginx也是用的这种技术。 实际上,Kafka把所有的消息都存放在一个一个的文件中,当消费者需要数据的时候Kafka直接把“文件”发送给消费者。当不需要把整个文件发出去的时候,Kafka通过调用Zero Copy的sendfile这个函数,这个函数包括:
「 浅谈大规模分布式系统中那些技术点」系列文章: Reference http://www.cnblogs.com/liuming1992/p/6423007.html http://blog.csdn.net/lifuxiangcaohui/article/details/51374862 http://www.jasongj.com/2015/01/02/Kafka深度解析 http://www.infoq.com/cn/articles/kafka-analysis-part-2 http://zqhxuyuan.github.io/2016/02/23/2016-02-23-Kafka-Controller https://tech.meituan.com/kafka-fs-design-theory.html https://my.oschina.net/silence88/blog/856195 https://toutiao.io/posts/508935/app_preview 转载请并标注: “本文转载自 linkedkeeper.com (文/张松然)” |
浅谈分布式消息技术 Kafka的更多相关文章
- 搞懂分布式技术21:浅谈分布式消息技术 Kafka
搞懂分布式技术21:浅谈分布式消息技术 Kafka 浅谈分布式消息技术 Kafka 本文主要介绍了这几部分内容: 1基本介绍和架构概览 2kafka事务传输的特点 3kafka的消息存储格式:topi ...
- 浅谈分布式消息技术 Kafka(转)
一只神秘的程序猿. Kafka的基本介绍 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可 ...
- 【转】浅谈分布式服务协调技术 Zookeeper
非常好介绍Zookeeper的文章, Google的三篇论文影响了很多很多人,也影响了很多很多系统.这三篇论文一直是分布式领域传阅的经典.根据MapReduce,于是我们有了Hadoop:根据GFS, ...
- 分布式消息队列 Kafka
分布式消息队列 Kafka 2016-02-25 杜亦舒 Kafka是一个高吞吐量的.分布式的消息系统,由Linkedin开发,开发语言为scala具有高吞吐.可扩展.分布式等特点 适用场景 活动数据 ...
- 浅谈Android保护技术__代码混淆
浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.将代码中的各种元 ...
- [转帖]浅谈分布式一致性与CAP/BASE/ACID理论
浅谈分布式一致性与CAP/BASE/ACID理论 https://www.cnblogs.com/zhang-qc/p/6783657.html ##转载请注明 CAP理论(98年秋提出,99年正式发 ...
- Kafka无法消费?!我的分布式消息服务Kafka却稳如泰山!
在一个月黑风高的夜晚,突然收到现网生产环境Kafka消息积压的告警,梦中惊醒啊,马上起来排查日志. 问题现象:消费请求卡死在查找Coordinator Coordinator为何物?Coordinat ...
- 分布式消息系统kafka
kafka:一个分布式消息系统 1.背景 最近因为工作需要,调研了追求高吞吐的轻量级消息系统Kafka,打算替换掉线上运行的ActiveMQ,主要是因为明年的预算日流量有十亿,而ActiveMQ的分布 ...
- 浅谈分布式共识算法raft
前言:在分布式的系统中,存在很多的节点,节点之间如何进行协作运行.高效流转.主节点挂了怎么办.如何选主.各节点之间如何保持一致,这都是不可不面对的问题,此时raft算法应运而生,专门 用来解决上述问题 ...
随机推荐
- Eclipse断点调试(DBG)Android应用
1.添加断点 双击左侧边框便可添加断点,右击也能添加断点. 2.进入调试模式 点击虫子,然后选择工程运行,快捷键为单击F11 ,如果是正常运行就是Ctrl+F11 3.单步调试+跳到下一个断点 运行到 ...
- 利用Microsoft.Exchange.WebServices处理Office365邮件的几个属性
使用Microsoft.Exchange.WebServices可以很方便操作Office365邮件.这里列出几个重要的属性. 通常,代码里会先定义一个WebServices对象 ExchangeSe ...
- http协议报头详解HTTP协议结构
http协议 请求报文和响应报文都是由以下4部分组成 1.请求行 2.请求头 3.空行 4.消息主体 下图为http请求的报文结构 下图为http响应报文结构 请求行 格式为: Method Requ ...
- RateLimiter
RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类. 限流算法 常用的更平滑的限流算法有两种:漏桶算法和令牌桶算法. 很多传统的服务提供商如华为中兴都有类似的专利, ...
- Pitch,Yaw,Roll的概念
在航空中,pitch, yaw, roll下图所示. pitch是围绕X轴旋转,也叫做俯仰角. yaw是围绕Y轴旋转,也叫偏航角. roll是围绕Z轴旋转,也叫翻滚角. 在3D系统中,假设视点 ...
- DLL文件实现窗体的模板模式
机房合作版中第一次使用了模板方法,实现了类似窗体的界面和代码的复用..窗体继承有两种方法,一种是通过继承选择器从已编译的程序集合里选择,另一种则是通过DLL文件的方式继承.个人觉得DLL还是比较方便的 ...
- GROUP BY中ROLLUP/CUBE/GROUPING/GROUPING SETS使用示例
oracle group by中rollup和cube的区别: Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句.CUBE ROLLUP 是用于统计数据的. 实验 ...
- iOS截屏方法
//获取屏幕截屏方法 - (UIImage *)capture { // 创建一个context UIGraphicsBeginImageContextWithOptions(self.view.bo ...
- 读书笔记,《Java 8实战》第五章,使用流
本章我们将会了解到关于Stream API的很多操作,这些操作能够完成很多复杂的查询,比如,比如筛选,切片,映射,查找,匹配和规约, 第一节,筛选和切片 首先我们来看看用谓词来选择流动的元素,主 ...
- Redis2.2.2源码学习——Server&Client链接的建立以及相关Event
Redis中Server和User建立链接(图中的client是服务器端用于描述与客户端的链接相关的信息) Redis Server&Client链接的建立时相关Event的建立(图中的cli ...















