Kakfa消息投递语义
Message Delivery Semantics
- At most once —— Messages may be lost but are never redelivered(消息可能丢失但不会重复投递)
- At least once —— Messages are never lost but may be redelivered(消息不会丢失但可能重复投递)
- Exactly once —— this is what people actually want, each message is delivered once and only once(消息只投递一次)
许多系统都声称提供"exactly once"投递,但是仔细阅读很重要,大部分这种宣称都是误导(他们没有考虑生产者和消费者可能失败的情况,以及多个消费者进程同时处理的情况,还有写到磁盘上的数据可能丢失的情况)。
Kafka的消息投递语义是直接的。发布消息的时候我们有一个概念叫消息被提交到日志。一旦被发布的消息被提交到日志,只要有一个这个消息所在分区的broker活着消息就不会丢失。从0.11.0.0版本以后,Kafka生产者支持幂等投递选项,以保证即使消息被重新发送,日志中也不会有重复的条目。为了实现这一点,broker给没用个生成者指定一个ID并且每条消息指定一个序列号。
并不是所有的情况都需要这样强的保证。
现在,让我们站在消费者的角度来看这个语义。消费者用日志控制它的位置。如果消费者没有崩溃它仅仅只是在内存中存储这个位置,但如果消费者失败了,我们想要另一个进程来接管这个分区,那么这个新的进程需要选择一个合适的位置开始处理。让我们来看一下消费者读取消息后处理消息和更新位置的几种选项。
- It can read the messages, then save its position in the log, and finally process the messages.(读取消息,然后在日志中保存位置,最后处理消息)。这种情况有一种可能就是消费者在保存位置之后就崩溃了。这情况下接管的进程会从保存的那个位置开始处理,即使在这个位置之前有一些消息没有被处理也不管了。这与"at-most-once"的语义是一致的,在这种情况下,消费者处理失败的那些消息就不会被处理了。
- It can read the messages, process the messages, and finally save its position.(读取消息,然后处理消息,最后保存位置)。这种情况下有一种可能是消费者在处理消息之后保存位置之前就崩溃了。这种情况下,新的进程接管以后会接收到一些之前已经被处理过的消息。这与"at-least-once"的语义是一致的。在许多情况下,消息有一个主键,以至于更新是幂等的(接收相同的消息两次,重写日志记录)。
The consumer's position is stored as a message in a topic, so we can write the offset to Kafka in the same transaction as the output topics receiving the processed data. If the transaction is aborted, the consumer's position will revert to its old value and the produced data on the output topics will not be visible to other consumers, depending on their "isolation level." In the default "read_uncommitted" isolation level, all messages are visible to consumers even if they were part of an aborted transaction, but in "read_committed," the consumer will only return messages from transactions which were committed (and any messages which were not part of a transaction).
当从主题消费并生产到另一个主题的时候,我们可以用事务生产者。消费者的位置作为消息被存储在topic中,以至于我们可以在接收处理数据的那个事务中将offset写到kafka。如果事务被中止,消费者的位置会恢复成旧值并且生产的数据对其它消费者不可见,这取决于隔离级别。默认的隔离级别是"read_uncommitted"表示消息对所有消费者可见,即使有些消息来自被中止的事务。
总结
1、消息投递语义
最多一次:可能丢失消息但不会重复投递
最少一次:不会丢失消息但可能重复投递
精确一次:只会投递一次
2、kafka给每个生产者指定一个ID,每个发布的消息一个序列号,这样的话即使生产者重复发送消息,在提交日志中也不会有重复记录
3、站在消费者的角度,先保存位置后处理消息就是“最多一次”;先处理消息后保存位置就是“最少一次”;至于“精确一次”,可以使用事务生产者来实现,即在同一个事务中接收并处理消息,将位置(offset)保存到另一个topic中。只要事务成功了,皆大欢喜,若事务失败,则位置恢复。
参考 http://kafka.apache.org/documentation/#design
Kakfa消息投递语义的更多相关文章
- Exactly-Once 投递语义
小结: 1.Exactly-Once 是指发送到消息系统的消息只能被消费端处理且仅处理一次,即使生产端重试消息发送导致某消息重复投递,该消息也在消费端也只被消费一次. 消息队列 RocketMQ &g ...
- 【转】Windows消息投递流程:WM_COMMAND消息流程
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182585 该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COM ...
- Rabbitmq可靠消息投递,消息确认机制
前言 我们知道,消息从发送到签收的整个过程是 Producer-->Broker/Exchange-->Broker/Queue-->Consumer,因此如果只是要保证消息的可靠投 ...
- Windows各种各种消息投递函数
1.SendMessage:发送消息给指定的窗口过程:直到窗口过程处理了消息才返回. 2.PostMessage:将消息放入消息队列(与指定窗口创建的线程相关)中:无需等待消息处理,立即返回. 不 ...
- skynet1.0阅读笔记2_skynet的消息投递skynet.call
为了了解 skynet.call 的调用过程,需要先看看 skynet的队列是如何把包分到不同工作线程的.看下图 查看 global_queue 的skynet_globalmq_push和skyne ...
- 【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646 本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数 ...
- rocketmq批量消息投递
批量发送消息可提高传递小消息的性能.同时也需要满足以下特征 批量消息要求必要具有同一topic.相同消息配置 不支持延时消息 建议一个批量消息最好不要超过1MB大小 示例 小于1MB String t ...
- 【kafka学习之六】kakfa消息生产、消费示例
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 kafka_2.11-0.11.0.0 zookeepe ...
- ActiveMq C# 消息特性:延迟和定时消息投递
ActiveMQ from version 5.4 has an optional persistent scheduler built into the ActiveMQ message broke ...
随机推荐
- 【Java学习笔记之一】java关键字及作用
Java关键字及其作用 一. 总览: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements ...
- 2017 Multi-University Training Contest - Team 1 1002&&HDU 6034 Balala Power!【字符串,贪心+排序】
Balala Power! Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- hdu_1036(取整和格式控制)
题意很简单,求平均时间 复习一下如何取整 (int) fl 是直接向下取整 == floor(fl) 向上取整 (int)(fl+1) == ceil(fl) 四舍五入 (int)(fl+0.5 ...
- hbmy周赛1--A
Age Sort You are given the ages (in years) of all people of a country with at least 1 year of age. Y ...
- 编写shell时,提示let/typeset:not found
刚刚开始接触linux shell 编程,脚本里面有一条let命令,在运行该脚本时却提示 let:not found 于是各种找自己写的脚本的问题,没发现错误,只好去网上百度,好心人告诉了我答案: / ...
- oracle 数据库——知识点总结(加示例)
新入oracle数据库,把目前学到的知识点记录下来,可能都比较基础,但还是比较全的,里面的示例都是自己在PL/SQL中跑过的,如果有错误,还望各位大侠指出哈. 创建用户 1.创建用户(使用管理员身份创 ...
- 一步一步从原理跟我学邮件收取及发送 5.C语言的socket示例
说到 C 语言版本的程序,首先要解决的问题就是兼容性. 作为 20 年开发有 10 多年是在服务端的程序员,我深刻地感受到服务端平台的两极分化之严重,linux 派对 windows 那是超级的不屑一 ...
- 织梦dedecms如何去除版权中的Power by DedeCms
很多站长在使用dedecms建站过程中,很多人都会调用到dedecms自带的powerby标签,这样在版权信息中就会多出Power by DedeCms这个连接.今天教大家如何去除. 工具/原料 de ...
- Python3 的元组
元组(tuple):戴上了枷锁的列表 元组与列表非常相似但是元组内元素的类型相同,且元组内的元素不能修改 1.创建元组的方法 与列表不同创建元组大部分情况下是用小括号,例如 tuple1=(1,2,3 ...
- eclipse导入web项目变成java项目解决办法
右键工程,properties-> Project Facets-> 点convert to faceted..连接 -> 把Dynamic Web Moudle勾上