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并且每条消息指定一个序列号。

并不是所有的情况都需要这样强的保证。

现在,让我们站在消费者的角度来看这个语义。消费者用日志控制它的位置。如果消费者没有崩溃它仅仅只是在内存中存储这个位置,但如果消费者失败了,我们想要另一个进程来接管这个分区,那么这个新的进程需要选择一个合适的位置开始处理。让我们来看一下消费者读取消息后处理消息和更新位置的几种选项。

  1. It can read the messages, then save its position in the log, and finally process the messages.(读取消息,然后在日志中保存位置,最后处理消息)。这种情况有一种可能就是消费者在保存位置之后就崩溃了。这情况下接管的进程会从保存的那个位置开始处理,即使在这个位置之前有一些消息没有被处理也不管了。这与"at-most-once"的语义是一致的,在这种情况下,消费者处理失败的那些消息就不会被处理了。
  2. 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消息投递语义的更多相关文章

  1. Exactly-Once 投递语义

    小结: 1.Exactly-Once 是指发送到消息系统的消息只能被消费端处理且仅处理一次,即使生产端重试消息发送导致某消息重复投递,该消息也在消费端也只被消费一次. 消息队列 RocketMQ &g ...

  2. 【转】Windows消息投递流程:WM_COMMAND消息流程

    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182585 该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COM ...

  3. Rabbitmq可靠消息投递,消息确认机制

    前言 我们知道,消息从发送到签收的整个过程是 Producer-->Broker/Exchange-->Broker/Queue-->Consumer,因此如果只是要保证消息的可靠投 ...

  4. Windows各种各种消息投递函数

    1.SendMessage:发送消息给指定的窗口过程:直到窗口过程处理了消息才返回. 2.PostMessage:将消息放入消息队列(与指定窗口创建的线程相关)中:无需等待消息处理,立即返回.   不 ...

  5. skynet1.0阅读笔记2_skynet的消息投递skynet.call

    为了了解 skynet.call 的调用过程,需要先看看 skynet的队列是如何把包分到不同工作线程的.看下图 查看 global_queue 的skynet_globalmq_push和skyne ...

  6. 【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)

    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646 本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数 ...

  7. rocketmq批量消息投递

    批量发送消息可提高传递小消息的性能.同时也需要满足以下特征 批量消息要求必要具有同一topic.相同消息配置 不支持延时消息 建议一个批量消息最好不要超过1MB大小 示例 小于1MB String t ...

  8. 【kafka学习之六】kakfa消息生产、消费示例

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 kafka_2.11-0.11.0.0 zookeepe ...

  9. ActiveMq C# 消息特性:延迟和定时消息投递

    ActiveMQ from version 5.4 has an optional persistent scheduler built into the ActiveMQ message broke ...

随机推荐

  1. Choose the best route(最短路)dijk

    http://acm.hdu.edu.cn/showproblem.php?pid=2680 Choose the best route Time Limit: 2000/1000 MS (Java/ ...

  2. c语言基础学习08_关于内存管理的复习

    =============================================================================对于c语言来讲,内存管理是一个很重要的内容,它 ...

  3. ImportError: No module named 'BaseHTTPServer':解决方案

    利用python写了一小段代码,里面使用到了Python标准库的BaseHTTPServer来构建一个基础HTTP服务器: 1 #-*- coding:utf-8 -*- 2 import http. ...

  4. oracle 数据库——知识点总结(加示例)

    新入oracle数据库,把目前学到的知识点记录下来,可能都比较基础,但还是比较全的,里面的示例都是自己在PL/SQL中跑过的,如果有错误,还望各位大侠指出哈. 创建用户 1.创建用户(使用管理员身份创 ...

  5. JavaScript变量声明与提升

    一直以来对变量提升都是比较模糊的,今天特地看了一下这个知识点,总结一下. 1.举个最简单的例子来说一下什么是变量提升吧. function foo(){ console.log(x); // unde ...

  6. linux一键安装

    http://source.docs.cloudcare.cn/support/faq/webfaq/webfaq_11/?spm=5176.730006-cmgj000262.102.8.QsmPR ...

  7. Vue版本过渡变化

    到了2.0以后,有哪些变化: 在每个组件模板,不在支持片段代码 之前: <template id="aaa"> <h3>我是组件</h3>< ...

  8. ios - 如何获取app上的数据

    做过ios开发的人应该都用过Charles,通常叫它花瓶.Charles是Mac下常用的对网络流量进行分析的工具,类似于Windows下的Fiddler.在开发iOS程序的时候,往往需要调试客户端和服 ...

  9. 引用类型之数组array最全的详解

    Array类型 今天总结一下array类型. js中的数组是有着非常强大的功能.具有很大的灵活性,有两个方面的特点 1.数组的每一项可以保存任何的数据类型:2.数组大小可以动态的调整:看下面的例子: ...

  10. 使用axios post 提交数据,后台获取不到提交的数据解决方案

    一.问题发现 前后端分离使用vue开发,结合axios进行前后端交互数据,一开始使用 get 请求,获取数据,没有发现任何问题,当使用 post请求 传参时,发现,数据明明已经提交,在打开F12 开发 ...