Kafka(Go)教程(十)---Kafka 是如何实现精确一次(exactly once)语义的?

Kafka 中“精确一次(exactly-once)”语义解析 阅读详情

来自:指月 https://www.lixueduan.com

原文:https://www.lixueduan.com/post/kafka/10-exactly-once-impl/

本文主要讲述了Kafka 消息交付可靠性保障以及精确处理一次语义的实现,具体包括幂等生产者和事务生产者。

Kakfa 相关代码见 Github

1. 概述

所谓的消息交付可靠性保障,是指 Kafka 对 Producer 和 Consumer 要处理的消息提供什么样的承诺。常见的承诺有以下三种:

  • 最多一次(at most once):消息可能会丢失,但绝不会被重复发送。
  • 至少一次(at least once):消息不会丢失,但有可能被重复发送。
  • 精确一次(exactly once):消息不会丢失,也不会被重复发送。

目前,Kafka 默认提供的交付可靠性保障是第二种,即至少一次。

这样虽然不出丢失消息,但是会导致消息重复发送。

Kafka 也可以提供最多一次交付保障,只需要让 Producer 禁止重试即可。

这样一来肯定不会重复发送,但是可能会丢失消息。

无论是至少一次还是最多一次,都不如精确一次来得有吸引力。大部分用户还是希望消息只会被交付一次,这样的话,消息既不会丢失,也不会被重复处理。

Kafka 分别通过 幂等性(Idempotence)和事务(Transaction)这两种机制实现了 精确一次(exactly once)语义。

2. 幂等性(Idempotence)

幂等这个词原是数学领域中的概念,指的是某些操作或函数能够被执行多次,但每次得到的结果都是不变的。

幂等性最大的优势在于我们可以安全地重试任何幂等性操作,反正它们也不会破坏我们的系统状态。

在 Kafka 中,Producer 默认不是幂等性的,但我们可以创建幂等性 Producer。它其实是 0.11.0.0 版本引入的新功能。指定 Producer 幂等性的方法很简单,仅需要设置一个参数即可,即 props.put(“enable.idempotence”, ture),或 props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)。

enable.idempotence 被设置成 true 后,Producer 自动升级成幂等性 Producer,其他所有的代码逻辑都不需要改变。Kafka 自动帮你做消息的重复去重。

底层具体的原理很简单,就是经典的用空间去换时间的优化思路,即在 Broker 端多保存一些字段。当 Producer 发送了具有相同字段值的消息后,Broker 能够自动知晓这些消息已经重复了,于是可以在后台默默地把它们“丢弃”掉。

当然,实际的实现原理并没有这么简单,但你大致可以这么理解。

Kafka 为了实现幂等性,它在底层设计架构中引入了 ProducerID 和 SequenceNumber。

Producer 需要做的只有两件事:

  • 1)初始化时像向 Broker 申请一个 ProducerID
  • 2)为每条消息绑定一个 SequenceNumber

Kafka Broker 收到消息后会以 ProducerID 为单位存储 SequenceNumber,也就是说即时 Producer 重复发送了, Broker 端也会将其过滤掉。

实现比较简单,同样的限制也比较大:

  • 首先,它只能保证单分区上的幂等性。即一个幂等性 Producer 能够保证某个主题的一个分区上不出现重复消息,它无法实现多个分区的幂等性。
    • 因为 SequenceNumber 是以 Topic + Partition 为单位单调递增的,如果一条消息被发送到了多个分区必然会分配到不同的 SequenceNumber ,导致重复问题。
  • 其次,它只能实现单会话上的幂等性。不能实现跨会话的幂等性。当你重启 Producer 进程之后,这种幂等性保证就丧失了。
    • 重启 Producer 后会分配一个新的 ProducerID,相当于之前保存的 SequenceNumber 就丢失了。

3. 事务(Transaction)

Kafka 的事务概念类似于我们熟知的数据库提供的事务。

Kafka 自 0.11 版本开始也提供了对事务的支持,目前主要是在 read committed 隔离级别上做事情。它能保证多条消息原子性地写入到目标分区,同时也能保证 Consumer 只能看到事务成功提交的消息。

事务型 Producer 能够保证将消息原子性地写入到多个分区中。这批消息要么全部写入成功,要么全部失败。另外,事务型 Producer 也不惧进程的重启。Producer 重启回来后,Kafka 依然保证它们发送消息的精确一次处理。

设置事务型 Producer 的方法也很简单,满足两个要求即可:

  • 和幂等性 Producer 一样,开启 enable.idempotence = true。
  • 设置 Producer 端参数 transactional. id。最好为其设置一个有意义的名字。

此外,你还需要在 Producer 代码中做一些调整,如这段代码所示:

producer.initTransactions();
try {
            producer.beginTransaction();
            producer.send(record1);
            producer.send(record2);
            producer.commitTransaction();
} catch (KafkaException e) {
            producer.abortTransaction();
}

和普通 Producer 代码相比,事务型 Producer 的显著特点是调用了一些事务 API,如 initTransaction、beginTransaction、commitTransaction 和 abortTransaction,它们分别对应事务的初始化、事务开始、事务提交以及事务终止。

这段代码能够保证 Record1 和 Record2 被当作一个事务统一提交到 Kafka,要么它们全部提交成功,要么全部写入失败。

实际上即使写入失败,Kafka 也会把它们写入到底层的日志中,也就是说 Consumer 还是会看到这些消息。因此在 Consumer 端,读取事务型 Producer 发送的消息也是需要一些变更的。修改起来也很简单,设置 isolation.level 参数的值即可。当前这个参数有两个取值:

  • read_uncommitted:这是默认值,表明 Consumer 能够读取到 Kafka 写入的任何消息,不论事务型 Producer 提交事务还是终止事务,其写入的消息都可以读取。
    • 很显然,如果你用了事务型 Producer,那么对应的 Consumer 就不要使用这个值。
  • read_committed:表明 Consumer 只会读取事务型 Producer 成功提交事务写入的消息。
    • 当然了,它也能看到非事务型 Producer 写入的所有消息。

4. Go 客户端

Go 客户端 sarama 暂时并没有实现 事务功能。

幂等性 Producer

sarama 中使用幂等性 Producer 设置和 Java 客户端也差不多:

	config := sarama.NewConfig()
	config.Producer.Idempotent = true                // 1.开启幂等性
	config.Producer.RequiredAcks = sarama.WaitForAll // 开启幂等性后 acks 必须设置为 -1 即所有 isr 列表中的 broker 都ack后才ok
	config.Net.MaxOpenRequests = 1                   // 并发请求数也只能为1
	// 上述的几个额外配置完全可以由 sarama 内置,或者直接提供一个方法即可,全部需要调用者手动配置感觉体验不是很好

除了开启 Idempotent 之外还必须配置其他几个配置项,具体条件如下:

	if c.Producer.Idempotent {
		if !c.Version.IsAtLeast(V0_11_0_0) {
			return ConfigurationError("Idempotent producer requires Version >= V0_11_0_0")
		}
		if c.Producer.Retry.Max == 0 {
			return ConfigurationError("Idempotent producer requires Producer.Retry.Max >= 1")
		}
		if c.Producer.RequiredAcks != WaitForAll {
			return ConfigurationError("Idempotent producer requires Producer.RequiredAcks to be WaitForAll")
		}
		if c.Net.MaxOpenRequests > 1 {
			return ConfigurationError("Idempotent producer requires Net.MaxOpenRequests to be 1")
		}
	}
  • Kafka 版本必须大于 V0_11_0_0。

  • Retry 次数必须大于0 ,不然发送失败后不能 Retry 就保证不了 Exactly Once 了。

    • 默认值为3,不需要手动设置。
  • Acks 必须为 -1,即所有 ISR 中的 Broker 都返回才算成功。

  • 最后并发请求数必须为1,不能并发请求。

Producer 完整代码如下:

func Producer(topic string, limit int) {
	config := sarama.NewConfig()
	config.Producer.Return.Successes = true
	config.Producer.Return.Errors = true
	config.Producer.Idempotent = true                // 开启幂等性
	config.Producer.RequiredAcks = sarama.WaitForAll // 开启幂等性后 acks 必须设置为 -1 即所有 isr 列表中的 broker 都ack后才ok
	config.Net.MaxOpenRequests = 1                   // 开启幂等性后 并发请求数也只能为1
	// 上述的几个额外配置完全可以由 sarama 内置,或者直接提供一个方法即可,全部需要调用者手动配置感觉体验不是很好
	producer, err := sarama.NewSyncProducer([]string{conf.HOST}, config)
	if err != nil {
		log.Fatal("NewSyncProducer err:", err)
	}
	defer producer.Close()
	for i := 0; i < limit; i++ {
		str := strconv.Itoa(int(time.Now().UnixNano()))
		msg := &sarama.ProducerMessage{Topic: topic, Key: sarama.StringEncoder(str), Value: sarama.StringEncoder(str)}
		partition, offset, err := producer.SendMessage(msg)
		if err != nil {
			log.Println("SendMessage err: ", err)
			return
		}
		log.Printf("[Producer] partitionid: %d; offset:%d, value: %s\n", partition, offset, str)
	}
}

注意:幂等性 Producer 保证的是同一条消息不会因为 Kafka 的原因发送多次,并不是说会过滤掉重复消息。一直发送相同内容的消息,依旧会正常发送成功。

即:Producer 中的去重并不依赖根据消息内容。

源码分析

通过源码简单分析一下 samara 中的 幂等性 Producer 是如何实现的。

大致原理:发送消息后会在 Producer 中记录一个字段用于去重。

具体 Producer 逻辑在上文Kafka(Go)教程(六)—sarama 客户端 producer 源码分析有详细介绍,这里也按照这个顺序进行分析。

newAsyncProducer

首先在创建 Producer 的时候会调用newTransactionManager创建一个TransactionManager,这个就是用于保证 幂等性的。

func newAsyncProducer(client Client) (AsyncProducer, error) {

	txnmgr, err := newTransactionManager(client.Config(), client)
	if err != nil {
		return nil, err
	}

	p := &asyncProducer{
		client:     client,
		conf:       client.Config(),
		errors:     make(chan *ProducerError),
		input:      make(chan *ProducerMessage),
		successes:  make(chan *ProducerMessage),
		retries:    make(chan *ProducerMessage),
		brokers:    make(map[*Broker]*brokerProducer),
		brokerRefs: make(map[*brokerProducer]int),
		txnmgr:     txnmgr,
	}
	return p, nil
}

transactionManager 结构如下:

type transactionManager struct {
	producerID      int64
	producerEpoch   int16
	sequenceNumbers map[string]int32
	mutex           sync.Mutex
}

其中 producerID+producerEpoch用于区分 Producer,sequenceNumbers则是用于消息去重。

进入newTransactionManager看下具体实现:

func newTransactionManager(conf *Config, client Client) (*transactionManager, error) {
	txnmgr := &transactionManager{
		producerID:    noProducerID,
		producerEpoch: noProducerEpoch,
	}
	// 如果开启了 幂等性 特殊处理
	if conf.Producer.Idempotent {
		initProducerIDResponse, err := client.InitProducerID()
		if err != nil {
			return nil, err
		}
		txnmgr.producerID = initProducerIDResponse.ProducerID
		txnmgr.producerEpoch = initProducerIDResponse.ProducerEpoch
		txnmgr.sequenceNumbers = make(map[string]int32)
		txnmgr.mutex = sync.Mutex{}

		Logger.Printf("Obtained a ProducerId: %d and ProducerEpoch: %d\n", txnmgr.producerID, txnmgr.producerEpoch)
	}

	return txnmgr, nil
}

可以看到 如果开启了 幂等性 则会调用client.InitProducerID()像 Kafka Broker 发送请求,申请一个 ProducerID,用以区分不同 Producer。

具体生成规则由 Kafka Broker端实现。

dispatch
func (pp *partitionProducer) dispatch() {
    	// msg.retries == 0 保证了每条消息只会生成一次序号
		if pp.parent.conf.Producer.Idempotent && msg.retries == 0 && msg.flags == 0 {
			msg.sequenceNumber, msg.producerEpoch = pp.parent.txnmgr.getAndIncrementSequenceNumber(msg.Topic, msg.Partition)
			msg.hasSequence = true
		}

		pp.brokerProducer.input <- msg
	}
}
func (t *transactionManager) getAndIncrementSequenceNumber(topic string, partition int32) (int32, int16) {	key := fmt.Sprintf("%s-%d", topic, partition) // 序号是以分区为单位的 这也是为什么只能保证指定分区下的 ExactlyOnce	t.mutex.Lock() // 加锁保证并发安全	defer t.mutex.Unlock()	sequence := t.sequenceNumbers[key]	t.sequenceNumbers[key] = sequence + 1 // seq 是递增的	return sequence, t.producerEpoch}

fmt.Sprintf 拼接字符串效率特别低,不建议使用。

在把消息交给 brokerProducer 之前给消息分配了一个 sequenceNumber,通过这个序号来保证了同一条消息只会发送一次,以实现 Exactly Once 语义。

add

最后到了 brokerProducer 的 add 方法,堆积消息批量发送。

func (ps *produceSet) add(msg *ProducerMessage) error {	var size int	set := partitions[msg.Partition]	if set == nil {		if ps.parent.conf.Version.IsAtLeast(V0_11_0_0) {			batch := &RecordBatch{				FirstTimestamp:   timestamp,				Version:          2,				Codec:            ps.parent.conf.Producer.Compression,				CompressionLevel: ps.parent.conf.Producer.CompressionLevel,				ProducerID:       ps.producerID,				ProducerEpoch:    ps.producerEpoch,			}            // 如果是幂等性 Producer 则在这里把消息的 seq 赋值给 batch.FirstSequence            // 由于只有 set == nil 时才会执行该逻辑 所以 batch.FirstSequence 只会被第一条消息赋值			if ps.parent.conf.Producer.Idempotent {				batch.FirstSequence = msg.sequenceNumber			}			set = &partitionSet{recordsToSend: newDefaultRecords(batch)}			size = recordBatchOverhead		} else {			set = &partitionSet{recordsToSend: newLegacyRecords(new(MessageSet))}		}		partitions[msg.Partition] = set	}	if ps.parent.conf.Version.IsAtLeast(V0_11_0_0) {        // 最后判断当前消息的 sequenceNumber 是否小于 batch 的 FirstSequence 这里的 set.recordsToSend.RecordBatch 就是上面的 batch       	// 所以正常情况下 msg.sequenceNumber 应该是大于等于 FirstSequence 的		if ps.parent.conf.Producer.Idempotent && msg.sequenceNumber < set.recordsToSend.RecordBatch.FirstSequence {			return errors.New("assertion failed: message out of sequence added to a batch")		}	}	return nil}

在初始化 Set 时将当前 msg 的 seq 赋值给了 Set,而 Seq 是单调递增的,所以后续 msg 的 seq 应该都大于 Set 的 FirstSequence。

小结

Producer 逻辑基本分析完了,和前面分析的一样,Producer 需要做的只有两件事:

  • 1)初始化时像向 Broker 申请一个 ProducerID
  • 2)为每条消息绑定一个 SequenceNumber

具体重复消息过滤其实是由 Kafka 实现的。

5. 小结

Kakfa 相关代码见 Github

幂等性 Producer 和事务型 Producer 都是 Kafka 社区力图为 Kafka 实现精确一次处理语义所提供的工具,只是它们的作用范围是不同的。

  • 幂等性 Producer 只能保证单分区、单会话上的消息幂等性;
  • 而事务能够保证跨分区、跨会话间的幂等性。

从交付语义上来看,自然是事务型 Producer 能做的更多。天下没有免费的午餐。比起幂等性 Producer,事务型 Producer 的性能要更差,在实际使用过程中,我们需要仔细评估引入事务的开销,切不可无脑地启用事务。

最后还是建议实际使用时在 Consumer 端也要进行去重,防止重复消费,这样比较稳妥。

6. 参考

https://github.com/Shopify/sarama

https://www.cnblogs.com/smartloli/p/11922639.html

《Kafka 核心技术与实战》

Kappa架构在实时日志分析中的应用:ELK+Flink+Kafka整合方案 Kappa架构+ELK+Flink+Kafka的整合方案,不是简单的"工具拼接",而是**“数据→信息→洞察→决策”**的全链路能力升级。它让日志从"事后排查的工具"变成"实时决策的引擎"——运维可以在故障发生1分钟内定位问题,产品可以在用户行为变化时立即调整策略,安全可以在攻击发生时实时阻断。在数字化时代,实时性就是竞争力。希望这篇文章能帮你掌握Kappa架构的核心逻辑,搭建属于自己的实时日志分析系统,让数据真正"活"起来。附录:生产环境配置清单组件版本配置建议Kafka2.8+ 阅读详情

相关推荐

【Kafka】Kafka 实现 Exactly-once (ack机制、高水位)

这个acks参数在kafka的使用中,是非常核心以及关键的一个参数,决定了很多东西。Kafka producer有三种ack机制 初始化producer时在config中进行配置ack等于0:意味着producer不等待broker同步完成的确认,继续发送下一条(批)信息提供了最低的延迟。但是最弱的持久性,当服务器发生故障时,就很可能发生数据丢失。例如leader已经死亡,producer不知情,还会继续发送消息broker接收不到数据就会数据丢失。ack等于1(默认)

九师兄 1448

Kafka 是如何实现exactly once语义的?

一、消息语义概述 在分布式系统中,构成系统的任何节点都是被定义为可以彼此独立失败的。比如在 Kafka中,broker可能会crash,在producer推送数据至topic的过程中也可能会遇到网络问题。根据producer处理此类故障所采取的提交策略类型,我们可以获得不同的语义: 至少一次(at-least-once):消息不会丢失,但有可能被重复发送。如果producer收到来自Kafka broker的确认(ack)或者acks = all,则表示该消息已经写入到Kafka。但如果producer

大数据 3247

深入理解Kafka—如何保证Exactly Once语义

Kafka 是一种高吞吐量、分布式、可分区、多副本的消息系统。它在使用上非常灵活,可以作为 Pulsar、RabbitMQ 的替代品。但同时也带来了一些复杂性和问题,比如Exactly Once 语义。从本质上说,Exactly Once 就是对消费者读取的数据只要不丢失,就一定能得到一次完整的处理,而且不会被重复处理。确保 Exactly Once 语义一直是企业级应用中必须考虑的问题。

AI天才研究院 1598

Stream Processing: Apache Kafka的Exactly-once的定义 原理和实现

2018年,Apache Kafka以一种特殊的设计和方法实现了强语义的exactly-once和事务性。热泪盈眶啊! 这篇文章将讲解kafka中exactly-once和事务操作的原理,具体为(1)exactly-once在kafka中的定义。(2)数据生产者的幂等操作和kafka的事务性支持。(3)exactly-once的流处理。 1. 什么是恰好一次exactly-once exact...

ChainingBlocks 5322

利用 Golang 和 Kafka 构建分布式任务调度系统

本文旨在为开发人员提供一套完整的解决方案,用于构建基于 Golang 和 Kafka 的分布式任务调度系统。我们将覆盖从基础概念到高级特性的所有内容,包括系统架构设计、核心组件实现、错误处理和性能优化等。核心概念与联系:介绍分布式任务调度和 Kafka 的基本概念系统架构设计:详细讲解系统整体架构核心实现:使用 Golang 和 Kafka 实现关键组件实际应用:展示系统在真实场景中的应用高级话题:讨论性能优化和扩展性考虑分布式任务调度:在多个计算节点上协调和执行任务的过程Kafka。

AI Agent Harness Engineering 760

Go实战:消息队列系统设计

消息队列的核心是分区并行、消费者组负载均衡、可靠性保证。生产者按Key分区保证同实体消息有序,批量发送提升吞吐。消费者组内每分区只被一个消费者消费,手动提交offset保证消息不丢。Exactly-Once靠消费端幂等加事务性提交实现,Redis做消息去重。消费失败的消息进死信队列,不丢弃可重放。自动提交offset是最大的坑,生产环境必须手动提交。

白话机器学习 111

如何在go-zero中实现Kafka事务消息与Exactly Once语义:完整指南

go-zero是一个云原生Go微服务框架,提供了与Kafka消息队列集成的能力,支持高可靠性的消息处理。本文将详细介绍如何在go-zero中实现Kafka事务消息与Exactly Once语义,帮助开发者构建可靠的分布式系统。 ## 为什么需要Kafka事务消息? 在分布式系统中,确保消息的可靠传递至关重要。Kafka事务消息提供了以下核心能力: - **原子性**:确保一组消息要么全部成功发

gitblog_00922的博客 352

矩阵LED和矩阵按键

先说矩阵LED,如图: 下面以行几、列几的表达方法说明 三极管可以当做开关使用 由图可知,如果想让一个LED亮,那么它对应的行和列的三极管都要导通。如果这个矩阵每次只亮一个LED,那么正常写程序没问题。 如果我们想让LED1和LED6亮,其他灯不亮,则需要开启行1、行2、列1、列2,随之带来的问题就是LED2和LED5也会跟着亮起来。 解决方法类似于扫描,因为单片机运行速度很快,可以在很短的时间内开关数次而肉眼看不到。所以我们可以每次只亮一列(排)灯,亮单位时间后关掉同时开启另外一列(排),如此四次一循环

qq_46615634的博客 5797

用go实现的kafka客户端,基于sarama和sarama-cluster

工作中需要将原先的消息队列替换成kafka,于是接触了基于go实现的sarama,又因为sarama不支持consumer group,于是又使用了sarama cluster,同时因为需要尽量保证消费一次的语义,就自己造了个简单的轮子,把sarama和sarama cluster封装到一起,同时实现了保证消费一次的语义,我给它起名为kago。 先附上kago的依赖,需要先进行安装: go...

jeffrey11223的博客 2万+

常见卫星图源下载教程

上面列出的8个常见的亚米级别数据源都可以通过xyz协议或者wmts/wms协议进行下载。这些协议是什么?地理信息数据为了方便网络传输,制定了一系列的地理数据传输标准(wms/wmts/xyz等)。协议特点优点缺点栅格数据支持矢量数据支持WMS通过HTTP请求获取GIS数据,服务器会将数据渲染成图像高度定制的地图;交互性强服务器渲染图像,响应时间较长支持有限支持WMTS提供预渲染的地图瓦片速度快,因为地图瓦片可以预先生成并在请求时快速提供瓦片的内容是预先确定的,无法进行定制支持。

锐多宝的地理空间 1万+

H3C模拟器HCL防火墙路由模式主备配置实验

摘要:本文详细介绍了网络拓扑规划与设备配置方案。运营商仅提供一个接口地址,通过虚IP技术实现双防火墙高可用部署:主备防火墙分别配置10.20.10.1/29和10.20.10.2/29作为实际上联地址,共享10.10.10.2/24虚IP;下联配置172.168.10.0/24网段,核心交换机配置VLAN接口及192.168.10.1、192.168.20.1两个下联接口。文章包含运营商路由器、防火墙(HA配置、VVRP设置)和核心交换机的具体命令行配置步骤,并强调需进行主备切换验证。整个方案实现了单运营商

LQ的博客 1124

攻克数据一致性难题:Sarama事务与Exactly-Once语义实战指南

Sarama是Go语言生态中针对Apache Kafka的高性能客户端库,提供了完整的事务支持和Exactly-Once语义实现能力。本文将深入解析如何利用Sarama构建可靠的数据管道,确保消息传递的精确一致性,特别适合需要处理金融交易、日志审计等关键业务场景的开发者。 ## 📊 为什么事务与Exactly-Once语义至关重要 在分布式系统中,数据一致性面临三大挑战:消息重复发送、消息丢

gitblog_00564的博客 946

INS/伪距组合导航(1)

星间单差GNSS/INS伪距紧组合

u014430081的博客 877

Sarama:写稳写快的 Go Kafka 客户端

当 Go 服务要在高并发下稳定地收发 Kafka 消息,Sarama 这个 Go Kafka 客户端把批量、重试、再平衡和协议版本这些脏活都消化掉了,你只管写业务。 ## 整体架构鸟瞰 仓库文件看似平铺,分层其实很清晰:[client.go](https://link.gitcode.com/i/2633aca14f646ae90016d8bfa0ceaf6b) 缓存集群元数据,[broker

gitblog_00687的博客 872

k8s部署 普罗米修斯(Prometheus)监控

Prometheus是一个开源的服务监控系统和时序数据库其提供了通用的数据模型和快捷数据采集、存储和查询接口它的核心组件Prometheus服务器定期从静态配置的监控目标或者基于服务发现自动配置的目标中进行拉 取数据新拉取到啊的 数据大于配置的内存缓存区时,数据就会持久化到存储设备当中。

D2961953033的博客 3860

Frida实战:SSL Pinning绕过技术全解析

本文详细解析了如何使用Frida工具绕过SSL Pinning技术,包括环境搭建、四种实战绕过方案及常见问题排查指南。通过具体代码示例和实战经验,帮助安全研究人员快速掌握SSL Pinning绕过技术,适用于金融类App的安全测试场景。

weixin_42530732的博客 188

An Overview of End-to-End Exactly-Once Processing in Apache Flink® (with Apache Kafka, too!)

This post is an adaptation ofPiotr Nowojski’s presentation from Flink Forward Berlin 2017. You can find the slides and a recording of the presentation on the Flink Forward Berlin website. Apache Flink 1.4.0, released in December 2017, introduced a sign...

u011250186的博客 325

PyTorch深度学习实战(2)——PyTorch基础

PyTorch 是广泛应用于机器学习领域中的强大开源框架,因其易用性和高效性备受青睐。在本节中,将介绍使用 PyTorch 构建神经网络的基础知识。首先了解 PyTorch 的核心数据类型——张量对象。然后,我们将深入研究用于张量对象的各种操作。PyTorch 提供了许多帮助构建神经网络的高级方法及组件,并提供了利用 GPU 更快地训练神经网络的张量对象。

盼小辉丶的博客 5万+

深度解析Sarama:构建高性能Go语言Kafka客户端的完整指南

Sarama是一个MIT许可的Go客户端库,专为Apache Kafka设计,提供可靠、高效的消息传递能力。作为Go语言生态中最受欢迎的Kafka客户端之一,Sarama支持从Kafka 0.8.2.0到最新版本的协议,为开发者提供了构建高并发、低延迟消息系统的强大工具。 ## 为什么选择Sarama? ### ✅ 核心优势 - **全面的协议支持**:兼容Kafka 0.8.2.0至最新版本

gitblog_00963的博客 918

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

如何快速上手go-queue:从安装到实现第一个Kafka消息推送的完整教程

go-queue是一个轻量级的消息队列框架,支持Kafka、Beanstalkd等多种消息中间件,帮助开发者快速实现可靠的消息传递功能。本教程将带你从环境准备到完成第一个Kafka消息推送,轻松掌握go-queue的核心使用方法。 ## 📋 环境准备 ### 安装Go环境 确保你的系统已安装Go 1.16或更高版本,可通过以下命令检查: ```bash go version ``` ###

gitblog_00565的博客 1088

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【Go Kafka 高并发实战指南】:从入门到精通的10个关键技巧

掌握高并发消息处理难题?本文深入解析Go Kafka用法,涵盖生产者消费者模式、错误重试、批量发送等10大实战技巧,适用于微服务异步通信与日志处理场景。性能提升显著,架构更稳定,值得收藏。

PixelGlow的博客 722

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Go 语言系统编程与云原生开发实战(第8篇)消息队列实战:Kafka 事件驱动 × CQRS 架构 × 最终一致性(生产级落地)

本文基于真实业务场景,探讨了消息队列(Kafka)在分布式系统中的实践方案。通过用户注册-邮件服务解耦、CQRS读写分离、Saga事务模式等典型案例,详细展示了消息队列在异步解耦、削峰填谷、最终一致性等场景的应用。重点包括:1)Kafka生产消费的可靠实现(幂等性、精确一次语义);2)事件驱动架构实现服务解耦;3)CQRS模式提升查询性能;4)Saga模式处理分布式事务。所有方案均在Minikube环境中实测验证,并提供了消息可靠性验证脚本和监控告警方案。文章最后总结了消息队列的避坑清单,强调其核心价值在于

小二丶的博客 1056

Watermill 实现 Exactly-once Delivery:基于 MySQL 事务的精确一次投递实战

"Exactly-once delivery(精确一次投递)不可能实现"是分布式系统领域流传甚广的说法,但 Watermill 用一套务实且可落地的方案证明:只要对"精确一次"给出清晰的定义、接受两个必要的约束条件,就能在 Go 应用中真正实现它。本文以仓库中 [exactly-once-delivery-counter 示例](https://link.gitcode.com/i/1a290cc

gitblog_00760的博客 8

Spark Streaming消费Kafka Direct保存offset到Redis,实现数据零丢失和exactly once

一、概述 上次写这篇文章文章的时候,Spark还是1.x,kafka还是0.8x版本,转眼间spark到了2.x,kafka也到了2.x,存储offset的方式也发生了改变,笔者根据上篇文章和网上文章,将offset存储到Redis,既保证了并发也保证了数据不丢失,经过测试,有效。 二、使用场景 Spark Streaming实时消费kafka数据的时候,程序停止或者Kafk...

579

sarama的消费者组分析、使用

kafka的go客户端,使用最多的应该是sarama,但以前老的sarama版本不支持消费者组的消费方式,所以大多数人都用sarama-cluster。 后来sarama支持了消费者组的消费方式,sarama-cluster也停止维护了,但网上关于sarama的消费者组的解析很少,且官方的样例很简单,所以这里分析一下。 一、官方样例 官方样例比较简单: 1、通过 sarama.NewConfig 创建一个配置 2、通过 NewConsumerGroup 创建一个消费者组 3、通过 Consume 创建消费者

Deepexi_Date的博客 3770
上一篇: Kafka(Go)教程(九)---如何避免消息丢失?
下一篇: Kafka(Go)教程(十一)---Consumer Group & Rebalance
探索云原生
博客等级 码龄9年 730粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值