CN114500416A - 用于最多一次消息投递的投递方法和投递*** - Google Patents

用于最多一次消息投递的投递方法和投递*** Download PDF

Info

Publication number
CN114500416A
CN114500416A CN202111526107.6A CN202111526107A CN114500416A CN 114500416 A CN114500416 A CN 114500416A CN 202111526107 A CN202111526107 A CN 202111526107A CN 114500416 A CN114500416 A CN 114500416A
Authority
CN
China
Prior art keywords
consumption
site
message
server
delivery
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN202111526107.6A
Other languages
English (en)
Other versions
CN114500416B (zh
Inventor
金融通
杜恒
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Alibaba China Co Ltd
Original Assignee
Alibaba China Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Alibaba China Co Ltd filed Critical Alibaba China Co Ltd
Priority to CN202111526107.6A priority Critical patent/CN114500416B/zh
Publication of CN114500416A publication Critical patent/CN114500416A/zh
Application granted granted Critical
Publication of CN114500416B publication Critical patent/CN114500416B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Classifications

    • HELECTRICITY
    • H04ELECTRIC COMMUNICATION TECHNIQUE
    • H04LTRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
    • H04L49/00Packet switching elements
    • H04L49/90Buffering arrangements
    • H04L49/9063Intermediate storage in different physical parts of a node or terminal
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/54Interprogram communication
    • G06F9/546Message passing systems or structures, e.g. queues

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Networks & Wireless Communication (AREA)
  • Signal Processing (AREA)
  • Information Transfer Between Computers (AREA)
  • Data Exchanges In Wide-Area Networks (AREA)

Abstract

公开了一种用于最多一次消息投递的投递方法和***。所述方法包括:在消费端根据队列拉取消息时,服务端直接将所述队列中的消费位点更新到下一个拉取位点;以及在服务端发生变动后,基于服务端记录的消费位点和启动时最大位点确定变动后所述消费端的拉取位点。本发明的投递方案通过由服务端直接控制队列消费位点的更新来避免重复投递,在服务端由于各种原因出现变动时,可以通过对消费位点的记录以及启动时最大位点快照的恢复,合理确定变动后的拉取位点,避免变动状态下的重复投递。通过对消费端缓存和拉取参数的配置以及服务端按步长持久化的合理设定,可以保证由于异常原因导致消息丢失的数量控制在预期范围内。

Description

用于最多一次消息投递的投递方法和投递***
技术领域
本公开涉及分布式消息中间件领域,尤其涉及一种用于最多一次消息投递的投递方法和投递***。
背景技术
市面上大部分的分布式消息中间件都满足At Least Once(最少一次)的消息投递语义,保证消息不丢。但一些对消息可靠性要求不太高的场景可以接受数据少量丢失,但不允许消息有重复,也就是消息中间件需要满足At Most Once(最多一次)的消息投递语义。但在服务端或是客户端发生异常变动时,现有的At Most Once投递会由于种种原因发生消息重复投递或是大量消息未被投递的问题。
为此,需要一种改进的用于最多一次消息投递的投递方案。
发明内容
本公开要解决的一个技术问题是提供一种改进的用于最多一次投递消息语义的投递方法和***。本公开的投递方案通过由服务端直接控制队列消费位点的更新来避免重复投递,在服务端因为各种原因出现变动时,还可以通过对消费位点的记录以及启动时最大位点快照的恢复,合理确定变动后的拉取位点,从而避免变动状态下的重复投递。
根据本公开的第一个方面,提供了一种用于最多一次消息投递的投递方法,包括:在消费端根据队列拉取消息时,服务端将所述队列中的消费位点更新到下一个拉取位点;以及在服务端发生变动后,基于服务端记录的消费位点和启动时最大位点确定变动后所述消费端的拉取位点。
可选地,在消费端根据队列拉取消息时,服务端将所述队列中的消费位点更新到下一个拉取位点包括:获取客户端的消息拉取请求;将所述队列中的消费位点更新到下一个拉取位点;以及将请求的消息返回给客户端。
可选地,在服务端发生变动后,将服务端记录的消费位点和启动时最大位点中更大的位点作为变动后的所述消费端的拉取位点。
可选地,服务端在所述消费位点更新满足步长参数时,将更新的消费位点进行持久化存储,并且,所述服务端记录的消费位点对应于基于步长被持久化存储的消费位点。
可选地,在服务端发生预期外变动后,将服务端记录的消费位点加上所述步长参数,作为修正后的消费位点,并选取所述修正后的消费位点和所述启动时最大位点中更小的位点作为变动后的所述消费端的拉取位点。
可选地,所述服务端为每个队列设定标识位,以在所述服务器重启或是主备切换时记录当前队列的最大位点作为所述启动时最大位点。
可选地,所述服务端设置所述消费端缓存参数,将消费端宕机引起的消息数量丢失控制为不多于消费端缓存参数对应的消息条数。
可选地,所述服务端设置所述消费端缓存参数和每次拉取条数参数,将重平衡引起的消息数量丢失控制为消费端缓存参数与每次拉取条数参数*分配到的队列数中的最大值。
可选地,所述服务端基于主题和消费群体为对应的每个队列加锁,使得同一时刻仅有一个消费端访问某一队列。
根据本公开的第二个方面,提供了一种最多一次消息投递的投递***,包括:服务端,用于执行如上述第一方面所述的投递方法;以及消费端,用于拉取服务端中的消息,并且拉取的消息是所述服务端基于最多一次投递语义投递的消息。
根据本公开的第三个方面,提供了一种非暂时性机器可读存储介质,其上存储有可执行代码,当所述可执行代码被电子设备的处理器执行时,使所述处理器执行如上述第一方面所述最多一次消息投递的投递方法。
由此,本发明通过队列服务端更新消费位点,记录启动/主备切换时的队列最大位点快照,以及合理确定拉取位点三者配合,提供一种可以满足At Most Once投递语义下消息投递不重复的方案。进一步地,通过客户端缓存配置以及服务端按步长持久化的合理设定,保证由于异常原因导致消息丢失的数量控制在预期范围内。
附图说明
通过结合附图对本公开示例性实施方式进行更详细的描述,本公开的上述以及其它目的、特征和优势将变得更加明显,其中,在本公开示例性实施方式中,相同的参考标号通常代表相同部件。
图1示出了消息中间件的组织架构示意图。
图2示出了基于日志的主题队列分发的示意图。
图3示出了服务端发生变动造成消息重复投递的例子。
图4示出了不同投递语义的投递模型示意图。
图5示出了根据本发明一个实施例的用于最多一次消息投递的投递方法的示意性流程图。
图6示出了在服务端发生变动时选择拉取位点的一个例子。
图7示出了最多一次语义下由重平衡引起的消息丢失的例子。
具体实施方式
下面将参照附图更详细地描述本公开的优选实施方式。虽然附图中显示了本公开的优选实施方式,然而应该理解,可以以各种形式实现本公开而不应被这里阐述的实施方式所限制。相反,提供这些实施方式是为了使本公开更加透彻和完整,并且能够将本公开的范围完整地传达给本领域的技术人员。
市面上大部分的分布式消息中间件都满足At Least Once(最少一次)的消息投递语义,保证消息不丢。但一些对消息可靠性要求不太高的场景可以接受数据少量丢失,但不允许消息有重复,也就是消息中间件需要满足At Most Once(最多一次)的消息投递语义。但在服务端或是客户端发生异常变动时,现有的At Most Once投递会由于种种原因发生消息重复投递或是大量消息未被投递的问题。
为此,本发明提供一种改进的用于最多一次投递消息语义的投递方案,该方案通过由服务端直接控制队列消费位点的更新来避免重复投递;而在服务端因为各种原因出现变动时,还可以通过对消费位点的记录以及启动时最大位点快照的恢复,合理确定变动后的拉取位点,从而避免消息的重复投递。
在此,为了帮助理解本发明的原理,首先将对最多一次消息投递语义的背景知识进行介绍。
***架构是从所有的服务模块都集中在一个应用,由该应用直接访问数据库,完成相应操作的单体架构开始演进的。随着***功能的愈发复杂和***规模的愈发增大,衍生出了按照模块拆分应用,前台***按照服务逻辑调用相关后端应用,并且其他后台应用进行互相调用的分布式架构。为了进一步降低模块应用间的耦合,产生出了专门用来沟通模块应用间的数据交换的消息中间件。
图1示出了消息中间件的组织架构示意图。如图所示,消息的生产者生产消息,交由消息中间件存储,再由消息中间件将消息分发到对应的消费者。例如,图示的生产者1产生的消息A可以首先交由消息中间件存储,再分发给对应的消费者1,换句话说,生产者1将消息A向消费者1发送这个任务完全交给了消息中间件。由此,相比于生产者和消费者之间的直接连接,经由消费中间件的存储和分发使得消息传递变为异步,降低了生产者和消费者之间的耦合程度,尤其适用于跨***的数据传递、高并发的流量削峰、数据异步处理等等。
另外,应该理解的是,虽然图中示出了生产者1、2和3产生的消息A、B、C经由消息中间件存储分发后分别对应的投递给了消费者1、2和3,但在实际操作中,可以是不同的生产者向同一个消费者投递不同的消息,也可以是多个消费者获取来自同一个生产者的消息。例如,用户的订单信息可由消息中间件分发给积分模块、用户画像模块和商品统计模块,分别用于用户消费积分的更新、用户画像的更新、以及订单商品的销售统计等等。
消息中间件可以通过特殊的结果来实现对海量消息的复杂分发模式下的分发。图2示出了基于日志的主题队列分发的示意图。
如图所示,消息中间件接收到的来自生产者的消息被顺序写入日志(即,CommitLog文件)。这里的“日志”并非应用日志那种非结构化文件,而是一种数据文件,用于存储接收到的消息。具有消息顺序追加、全局有序的特点。为了方便索引,每条日志项对应一个唯一序号。
由于消息中间件一般是基于消息主题的订阅机制,这样便给按照消息主题检索消息带来了极大的不便。为了提高消息消费的效率,需要引入消息队列(queue)。虽然图中示出为一个先进先出的队列,但实际上不同的队列,例如图中的队列0和队列1可以对应于不同的ConsumeQueue文件,文件中包含对日志文件中不同日志项的索引。例如,图示的数据文件包含多个数据项,每个数据项对应于不同的消息并经由虚线箭头所示,由队列0和队列1的ConsumeQueue文件通过偏移量(Offset)来进行索引。在实际操作中,消费者可以通过消费队列中记录的偏移量来从日志中拉取消息(对应于拉取模式)或由消息中间件根据消费队列中记录的偏移量来向对应的消费者进行消息推送(对应于推送模式)。
在图2所示的发布订阅模式中,生产者将消息发布到一个消费主题(Topic)中,订阅了该消费主题的所有消费者可以视为一个消费群组(ConsumerGroup),并且由于存在过滤机制,因此消费群组的每个消费者不一定会接收到属于该消费主题的每一条消息。
由于一个消息队列同一时间只允许被一个消费者消费,一个消费者可以消费多个消息队列。因此,一个消费主题中通常包括多个消费队列,例如,图2所示的队列0和队列1。由于消费队列中记录的是消息在数据文件中的索引,因此消费主题对应的是目录文件(与称为日志的数据文件相对)。另外,虽然图中仅仅示出了一个消费主题下的两个队列,即,队列0和队列1,以及各自对应的消费者1和2,但应该理解的是,同一个消费群组内的消费者可以根据重平衡策略,负载均衡的消费消息。在此,“重平衡”指代在基于日志位点的消费中间件中,由于消费者(也可称为“客户端”)或是队列数据的增加或减少,消费主题中的队列重新负载均衡给消费者的过程。
如图所示,消息主题下的每个队列(队列也可理解为分区)都会记录自己的最小位点、消费位点和最大位点。在此,最小位点是当前队列首条消息的位点(位点可以认为是消息到达队列时被指定的序列号),最大位点是当前队列最新消息的位点,消费位点则可以看作是队列被现有消费者消费了的最大位点。在现有技术中,消费位点由客户端(即,该条队列的消费者)提给交服务端保存。如果消费者一直处于运行状态,则一切正常,但如果消费者发生崩溃或有新的消费者加入群组(服务端扩缩容的情形也类似),就会触发重平衡,重平衡完成后,每个消费者会分配到新的队列,而不是之前处理的队列。为了能继续之前的操作,消费者需要读取每个队列最后一次的提交的消费位点,然后从消费位点处继续拉取消息。在实际执行过程中,由于客户端提交给服务端的消费位点并不是实时的,因此每次重平衡都会有消息重复。另一方面,由于服务端消费位点的持久化也并不是实时的,服务端的重启和主备切换也会造成消费位点的回退,造成消息的重复消费。
具体地,以拉取为例说明消费端内部的操作。消费者内部例如在重平衡之后,针对分配到的队列,生成相应的拉取请求,再由消息拉取线程从服务端拉消息到客户端本地缓存,然后再由消费线程池中的线程去消费本地缓存的消息,应用层确认(Ack)后,更新消费者(即,客户端)内存中的消费位点管理模块的消费位点,消费位点会后台定时同步到服务端。
图3示出了服务端发生变动造成消息重复投递的例子。在图3的例子中,消费者在前一次消费消息后,发送Ack,确认消息4#已消费完毕,并在随后发出例如一次拉取5条消息的请求,即拉取到消息9#。随后,客户端的消息拉取线程开始从服务端拉取消息到客户端本地缓存,在拉取到消息7#时,服务端发生重平衡(或是重启)。由于确认Ack尚未发送,服务端记录的消费位点还是前次提交到消息4#。等再有队列分配给该消费者时,由于需要保证消息至少被发送一次(即,如下详述的至少一次投递语义),消费者还需要从消息4#开始拉取,导致消息4#至7#重复发放。
在消息的传输过程中,如果需要确保消息在传输过程中绝不丢失(但可能会重复传输),可以采用最少一次(Atleastonce)消息投递语义进行投递,如图3所示的场景。而在一些对消息可靠性要求不太高的场景则可接受数据少量丢失,但不允许消息有重复的。例如,银行在向客户群发推广短信时,可以接受数据少量丢失导致个别用户不发送短信,但不能重复向同一个用户发送多次,这就需要消息中间件满足最多一次(At Most Once)消息投递语义,即,消息在传输过程中允许丢失,但绝不重复传输。
图4示出了不同投递语义的投递模型示意图。在此,生产者可以为目标消费群组产生消息的组件。消息中间件的代理服务器(broker),用于消息的存储和转发。对于应用最少一次(Atleastonce)消息投递语义的消费群组,消费者在拉取或是被推送消息之后,需要返回确认(Ack)。而对于应用最多一次(Atleastonce)消息投递语义的消费群组,消费者在拉取或是被推送消息不需要返回确认。
另外,虽然图4中没有示出,但还存在恰好一次(Exactlyonce)消息投递语义,要求消息在传输过程中肯定被传输一次且仅被传输一次。显然,传输所需要的开销和成本,从恰好一次、到最少一次、到最多一次逐个递减。换句话说,最多一次投递语义可以看作是一种***开销少的低成本投递方式。
由于图3所示的回退流程不适用于最多一次消息投递语义的应用场景,因此本发明提出一种改进的用于最多一次投递消息语义的投递方案。该方案可以基于日志位点的消息***提供满足最多一次语义的服务,保证消息不重复,并且能够通过参数的合理设置将消息的丢失量控制在预期范围内。
图5示出了根据本发明一个实施例的用于最多一次消息投递的投递方法的示意性流程图。该方法可由消息中间件执行,例如图4所示的broker针对应用最多一次投递消息语义的消费群组执行。
首先,在步骤S510,在消费端根据队列拉取消息时,服务端将所述队列中的消费位点更新到下一个拉取位点。在此,服务端直接更新消费位点,换句话说,服务端不需要获取来自消费端的任何确认,就可以直接进行拉取位点的更新。
在一个优选实施例中,步骤S510可以包括:获取客户端的消息拉取请求;将所述队列中的消费位点更新到下一个拉取位点;以及将请求的消息返回给客户端。换句话说,虽然服务端也能够根据消费端当前正拉取的消息来更新位点,但直接更新位点,再返回请求的消息使得服务端无需知晓消费端的消息拉取过程,从而进一步降低了开销。这样,同样在图3所示的场景中,如果前次提交消费位点为消息4#,本次消费端要求拉取5条消息,则服务端直接将消费位点更新到消息9#之后。如果在消费端随后正处理消息7#时发生了变动,无论是消费端变动(例如,客户端宕机)还是服务端变动(包括诸如主备切换或是重平衡的预期变动,也包括broker的意外宕机),只要服务端持久化存储了更新的消费位点(即,9#),则变动后的消息拉取必然不会早于该更新的消费位点。由此确保消息不会被重复投送。
其次,针对服务端的变动进行相应处理。为此,在步骤S520,可以在服务端发生变动后,基于服务端记录的消费位点和启动时最大位点确定变动后所述消费端的拉取位点。
在此,服务端变动可以包括诸如主备切换或是重平衡的预期变动,也包括服务端本身(例如,broker)的意外宕机。由于服务端会对消费位点进行持久化记录(即,从内存存入非易失性存储器,例如磁盘),因此服务端记录的消费位点可以是在服务端发生变动前,服务端进行持久化记录的最新的消费位点。而启动时最大位点则可以是变动前服务端记录的最大位点快照。服务端可以为每个队列设定标识位(例如,以Topic-Queue进行设置),以在服务器重启或是主备切换时记录当前队列的最大位点作为所述启动时最大位点。
由此,如上的投递方法可以通过由服务端直接控制队列消费位点的更新来避免重复投递,在服务端因为各种原因出现变动时,还可以通过对消费位点的记录以及启动时最大位点快照的恢复,合理确定变动后的拉取位点,从而避免变动状态下的重复投递。
对于服务端宕机重启而言,由于消费位点的持久化是有时间间隔的,异常宕机由于消费位点没有及时持久化造成消费位点的回退,仍然可能造成消费重复。此外,由于主备之间的消费进度同步有延迟,主备切换后,也有可能造成消费重复。针对该方面的问题,可以通过新分配队列的拉取位点策略来解决。为此,步骤S520可以包括:在服务端发生变动后,可以将如上所述的服务端记录的消费位点和启动时最大位点中更大的位点作为变动后的消费端的拉取位点。
图6示出了在服务端发生变动时选择拉取位点的一个例子。由于broker重启或主备切换时,可能存在实际消费位点没有被持久化的情况。因此,broker重启或主备切换时回退的消费位点consumerOffset可能会早于实际的消费位点。但由于在服务端每个Topic-Queue设定了标识位,因此可以在重启或主备切换时记录queueStartMaxOffset为当前队列最大位点MaxOffset快照。在处理消费者消息拉取请求时,就可以比较当前服务端消费位点consumerOffset和queueStartMaxOffset的大小并选取其中更大的值进行拉取,使得最终拉取消息的位点满足Max(consumerOffset,queueStartMaxOffset)。
这样保证只有宕机重启服务端的那些队列的消费位点被重置到服务端启动或主备切换时queue的最大位点快照,而QueueStartMaxOffset到cosumerOffset之间的数据将丢失。
在一个优选实施例中,服务端可以将现有技术中消费位点的定时持久化(例如,每个一分钟)修改为消费位点按步长的持久化。由此,可以基于持久化步长的设置,对基于服务端记录的消费位点和启动时最大位点确定变动后所述消费端的拉取位点进行优化。即,可以设置步长参数,并且使得服务端在消费位点更新满足步长参数时,将更新的消费位点进行持久化存储。并且,所述服务端记录的消费位点对应于基于步长被持久化存储的消费位点。例如,假设步长参数为10,则消费位点每更新10,就将新的消费位点存储到磁盘。
在基于步长进行持久化时,如果服务端是意外重启,例如,意外宕机,则可以基于上述步长对拉取位点的确定进行优化。如上根据图6所述,consumerOffset和queueStartMaxOffset都是队列上的位点,假设不基于步长更新消费位点,则重启时消费位点consumerOffset通常会被设置到QueueStartMaxOffset,则最多QueueStartMaxOffset到consumerOffset之间的消息会丢失。在使用持久化步长更新位点之后,在服务端意外宕机并重启的情况下,由于可以保证consumerOffset与实际的消费位点之间的回退值在步长参数flushStepSize的范围之内,因此可以将重置的位点从如上的Max(consumerOffset,queueStartMaxOffset)修正为Min(ConsumerOffset+flushStepSize,QueueStartMaxOffset)。如果设置到ConsumerOffset+flushStepSize,则最多丢失flushStepSize数量的消息,如果重置到QueueStartMaxOffset,则说明QueueStartMaxOffset-consumerOffset也没超过步长(如果超过步长就应该持久化了),所以最多也就丢失flushStepSize数量。
进一步地,服务端还可以通过为消费端提供关键参数,来控制消费端宕机时,以及消费端宕机叠加服务端变动(例如,服务端重平衡)时,丢失消息的数量上限。在本文中,消费端也可被称为消费者或是客户端。
如前所述,消费者内部在重平衡之后,针对分配到的队列,生成相应的拉取请求,再由消息拉取线程从服务端拉消息到客户端本地缓存,然后再由消费线程池中的线程去消费本地缓存的消息,应用层确认(Ack)后,更新消费者(即,客户端)内存中的消费位点管理模块的消费位点,消费位点会后台定时同步到服务端。由于服务端会直接在接收到拉取消息请求后更新消费位点,由此,在消费端宕机的情况下,客户端本地缓存中的消息将会无法找回,客户端也无法从服务端找回更新的消费位点之前的消息。为此,服务端设置可以设置消费端缓存参数,将消费端宕机引起的消息数量丢失控制为不多于消费端缓存参数对应的消息条数。
进一步地,由于消费端通常分配不止一条队列,为此在例如服务端发送重平衡等变动时,如果消费端此时宕机,则会引起更多数量的消息丢失。此时,服务端可以设置消费端缓存参数和每次拉取条数参数,将重平衡引起的消息数量丢失控制为客户端缓存参数与每次拉取条数参数*分配到的队列数中的最大值。
在服务端进行重平衡的情况下,由于拉完后直接更新消费位点,也会造成消息的丢失。图7示出了最多一次语义下由重平衡引起的消息丢失的例子。如图7所示,由于正在处理消息的位点≤消费位点=拉取的位点,因此重平衡后正在处理消息的位点与拉取的位点(即,服务端在本发明的最多一次投递语义下提交的消费位点)之间的消息会丢失。
通过控制消费端的缓存参数以及每次拉取条数的参数,可以将重平衡数量的丢失控制在预期范围内。假设MaxCachedMessageAmount为客户端的缓存数量配置,MAX_BATCH_MESSAGE_COUNT为客户端每次拉取的最大消息数量,则消费端异常宕机重启后最大丢失消息数计算公式如下:
Max(MaxCachedMessageAmount,MAX_BATCH_MESSAGE_COUNT*分配到的队列数)
换句话说,在某一消费端分配到同一消费主题下的队列较少时,由于消费端的缓存参数通常要大于每个队列每次拉取条数,因此最多丢失的消息数通常为消费端的缓存参数。但如果某一消费端分配到同一消费主题下的队列较多时,则需要比较消费端的缓存参数与每个队列每次拉取条数*分配到的队列数的值谁大来确定最大丢失的消息数量。
如下给出了基于消费端的缓存参数以及每次拉取条数的参数控制最大丢失的消息数量的例子:
1.四组broker,1个消费者消费1个消息主题下的32个队列,假设MaxCachedMessageAmount为100,MAX_BATCH_MESSAGE_COUNT为32,则最多丢失的消息数为Max(100,32*32)=1024条消息。
2.四组broker,2个消费者消费1个消息主题下的32个队列,每个消费者分配到16个队列,假设MaxCachedMessageAmount为200,MAX_BATCH_MESSAGE_COUNT设置为1,则每个消费者重启最多丢失的消息数为Max(200,1*16)=200条消息。
3.四组broker,1个消费者消费1个消息主题下的32个队列,每个消费者分配到32个队列,假设MaxCachedMessageAmount为100,MAX_BATCH_MESSAGE_COUNT设置为1,则消费者重启最多丢失的消息数为Max(100,32)=100条消息。
换句话说,由于1个消费者能够分配到的队列数量不确定,每个队列每次拉取条数若设置过大,会导致1个消费者分配大量队列时,大量消息的丢失(如上例1)。但每个队列每次拉取条数如果设置过小,则会降低拉取效率,因此需要对如上情况进行折中来选择合适的MAX_BATCH_MESSAGE_COUNT的值。
进一步地,由于重平衡过程中可能存在多个消费者试图访问一个队列的情况,为此服务端基于主题和消费群体为对应的每个队列加锁(即,基于Topic-ConsumerGroup-Queue进行设置),使得同一时刻仅有一个客户端访问某一队列。进一步地,在最多一次投递语义下,可以设置服务端屏蔽所有消费端所有的ACK逻辑和重试逻辑。
由上结合附图说明了根据本发明的用于最多一次消息投递的投递方法。如上方法也可由消息中间件结合消费端实现为一个投递***。为此,本发明还包括一种最多一次消息投递的投递***。该***包括:服务端,用于执行如如上所述的用于最多一次消息投递的投递方法;消费端,用于拉取服务端中的消息,并且拉取的消息是所述服务端基于最多一次投递语义投递的消息。例如,本发明投递方案可由图4所示的broker和最多一次投递语义下的消费群组组成的投递***来实现。
上文中已经参考附图详细描述了根据本发明的用于最多一次投递消息语义的投递方法和***。本发明通过队列服务端更新消费位点,记录启动/主备切换时的队列最大位点快照,以及合理确定拉取位点三者配合,提供一种可以满足At Most Once投递语义下消息投递不重复的方案。进一步地,通过客户端缓存配置以及服务端按步长持久化的合理设定,保证由于异常原因导致消息丢失的数量控制在预期范围内。
进一步地,本发明提供了消息处理场景中满足At Most Once语义的消费端实现。相比于需要外部组件依赖进行去重的方案,本发明不需要依赖任何外部组件,能够通过投递过程本身完成最多一次投递,并且能够跨库实现。
具体地,本发明的优选At Most Once方案需要满足如下规则:
1.在服务端区分消费群组是At Most Once还是At Least Once。
2.消费端在服务端拉取消息后,服务端直接更新消费位点到下一个拉取位点,更新完消费位点之后再返回消息给消费者,所有请求位点均以服务端为准。
3.为了防止同一个消费者拉到同一批消息,在拉取消息时服务端以Topic-ConsumerGroup-Queue维度进行加锁。
4.适配重平衡到新队列,拉取位点如上所述的新分配队列的拉取位点策略。
5.服务端屏蔽掉所有客户端所有的ACK逻辑和重试逻辑。
由此,本发明的最多一次投递消息语义的投递方法和***可以保证消费客户端的宕机重启、网络断连、重平衡不会造成消息重复。丢失消息个数主要是队列中已经拉到本地缓存的消息。
由此,本发明通过基于日志位点的分布式消息中间件中保证消费时消息不重复,满足At Most Once语义,并且由于异常原因导致消息丢失的数量,都控制在预期范围内。
此外,根据本发明的方法还可以实现为一种计算机程序或计算机程序产品,该计算机程序或计算机程序产品包括用于执行本发明的上述方法中限定的上述各步骤的计算机程序代码指令。
或者,本发明还可以实施为一种非暂时性机器可读存储介质(或计算机可读存储介质、或机器可读存储介质),其上存储有可执行代码(或计算机程序、或计算机指令代码),当所述可执行代码(或计算机程序、或计算机指令代码)被电子设备(或计算设备、服务器等)的处理器执行时,使所述处理器执行根据本发明的上述方法的各个步骤。
本领域技术人员还将明白的是,结合这里的公开所描述的各种示例性逻辑块、模块、电路和算法步骤可以被实现为电子硬件、计算机软件或两者的组合。
附图中的流程图和框图显示了根据本发明的多个实施例的***和方法的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段或代码的一部分,所述模块、程序段或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标记的功能也可以以不同于附图中所标记的顺序发生。例如,两个连续的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的***来实现,或者可以用专用硬件与计算机指令的组合来实现。
以上已经描述了本发明的各实施例,上述说明是示例性的,并非穷尽性的,并且也不限于所披露的各实施例。在不偏离所说明的各实施例的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。本文中所用术语的选择,旨在最好地解释各实施例的原理、实际应用或对市场中的技术的改进,或者使本技术领域的其它普通技术人员能理解本文披露的各实施例。

Claims (11)

1.一种用于最多一次消息投递的投递方法,包括:
在消费端根据队列拉取消息时,服务端将所述队列中的消费位点更新到下一个拉取位点;以及
在服务端发生变动后,基于服务端记录的消费位点和启动时最大位点确定变动后所述消费端的拉取位点。
2.如权利要求1所述的方法,其中,在消费端根据队列拉取消息时,服务端将所述队列中的消费位点更新到下一个拉取位点包括:
获取客户端的消息拉取请求;
将所述队列中的消费位点更新到下一个拉取位点;以及
将请求的消息返回给客户端。
3.如权利要求1所述的方法,其中,在服务端发生变动后,将服务端记录的消费位点和启动时最大位点中更大的位点作为变动后的所述消费端的拉取位点。
4.如权利要求1所述的方法,其中,服务端在所述消费位点更新满足步长参数时,将更新的消费位点进行持久化存储,
并且,所述服务端记录的消费位点对应于基于步长被持久化存储的消费位点。
5.如权利要求4所述的方法,其中,在服务端发生预期外变动后,将服务端记录的消费位点加上所述步长参数,作为修正后的消费位点,并选取所述修正后的消费位点和所述启动时最大位点中更小的位点作为变动后的所述消费端的拉取位点。
6.如权利要求1所述的方法,其中,所述服务端为每个队列设定标识位,以在所述服务器重启或是主备切换时记录当前队列的最大位点作为所述启动时最大位点。
7.如权利要求1所述的方法,其中,所述服务端设置所述消费端缓存参数,将消费端宕机引起的消息数量丢失控制为不多于消费端缓存参数对应的消息条数。
8.如权利要求1所述的方法,其中,所述服务端设置所述消费端缓存参数和每次拉取条数参数,将重平衡引起的消息数量丢失控制为消费端缓存参数与每次拉取条数参数*分配到的队列数中的最大值。
9.如权利要求1所述的方法,其中,所述服务端基于主题和消费群体为对应的每个队列加锁,使得同一时刻仅有一个消费端访问某一队列。
10.一种最多一次消息投递的投递***,包括:
服务端,用于执行如权利要求1-9中任一项所述的投递方法;
消费端,用于拉取服务端中的消息,并且拉取的消息是所述服务端基于最多一次投递语义投递的消息。
11.一种非暂时性机器可读存储介质,其上存储有可执行代码,当所述可执行代码被电子设备的处理器执行时,使所述处理器执行如权利要求1-9中任一项所述的用于最多一次消息投递的投递方法。
CN202111526107.6A 2021-12-14 2021-12-14 用于最多一次消息投递的投递方法和投递*** Active CN114500416B (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN202111526107.6A CN114500416B (zh) 2021-12-14 2021-12-14 用于最多一次消息投递的投递方法和投递***

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN202111526107.6A CN114500416B (zh) 2021-12-14 2021-12-14 用于最多一次消息投递的投递方法和投递***

Publications (2)

Publication Number Publication Date
CN114500416A true CN114500416A (zh) 2022-05-13
CN114500416B CN114500416B (zh) 2024-07-09

Family

ID=81493838

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202111526107.6A Active CN114500416B (zh) 2021-12-14 2021-12-14 用于最多一次消息投递的投递方法和投递***

Country Status (1)

Country Link
CN (1) CN114500416B (zh)

Cited By (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN115051963A (zh) * 2022-06-06 2022-09-13 阿里巴巴(中国)有限公司 消息处理方法及装置、消息队列***及电子设备
CN115396339A (zh) * 2022-08-24 2022-11-25 银清科技有限公司 一种异常报文处理方法及装置

Citations (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN106789741A (zh) * 2016-12-26 2017-05-31 北京奇虎科技有限公司 消息队列的消费方法及装置
US9894143B1 (en) * 2013-11-06 2018-02-13 Amazon Technologies, Inc. Pre-processing and processing pipeline for queue client
US20180088816A1 (en) * 2016-09-29 2018-03-29 International Business Machines Corporation Retrospective snapshots in log structured storage systems
CN108874562A (zh) * 2018-06-21 2018-11-23 北京顺丰同城科技有限公司 分布式高并发消息队列推送***
CN109412821A (zh) * 2017-08-16 2019-03-01 阿里巴巴集团控股有限公司 消息处理方法和装置以及电子设备
CN110535787A (zh) * 2019-07-25 2019-12-03 北京奇艺世纪科技有限公司 消息消费方法、装置及可读存储介质
CN110740145A (zh) * 2018-07-18 2020-01-31 北京京东尚科信息技术有限公司 消息消费方法、装置、存储介质及电子设备
CN111240859A (zh) * 2020-01-07 2020-06-05 北京达佳互联信息技术有限公司 一种数据处理方法、装置、服务器以及存储介质
CN112416614A (zh) * 2020-10-28 2021-02-26 网宿科技股份有限公司 基于消息队列的数据处理方法、***及服务器
CN113220435A (zh) * 2021-05-27 2021-08-06 深圳市商汤科技有限公司 任务处理方法及相关产品

Patent Citations (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US9894143B1 (en) * 2013-11-06 2018-02-13 Amazon Technologies, Inc. Pre-processing and processing pipeline for queue client
US20180088816A1 (en) * 2016-09-29 2018-03-29 International Business Machines Corporation Retrospective snapshots in log structured storage systems
CN106789741A (zh) * 2016-12-26 2017-05-31 北京奇虎科技有限公司 消息队列的消费方法及装置
CN109412821A (zh) * 2017-08-16 2019-03-01 阿里巴巴集团控股有限公司 消息处理方法和装置以及电子设备
CN108874562A (zh) * 2018-06-21 2018-11-23 北京顺丰同城科技有限公司 分布式高并发消息队列推送***
CN110740145A (zh) * 2018-07-18 2020-01-31 北京京东尚科信息技术有限公司 消息消费方法、装置、存储介质及电子设备
CN110535787A (zh) * 2019-07-25 2019-12-03 北京奇艺世纪科技有限公司 消息消费方法、装置及可读存储介质
CN111240859A (zh) * 2020-01-07 2020-06-05 北京达佳互联信息技术有限公司 一种数据处理方法、装置、服务器以及存储介质
CN112416614A (zh) * 2020-10-28 2021-02-26 网宿科技股份有限公司 基于消息队列的数据处理方法、***及服务器
CN113220435A (zh) * 2021-05-27 2021-08-06 深圳市商汤科技有限公司 任务处理方法及相关产品

Non-Patent Citations (3)

* Cited by examiner, † Cited by third party
Title
YOUNG丶: "【RocketMQ工作原理】offset管理", Retrieved from the Internet <URL:https://blog.csdn.net/eclipse9527/article/details/122219676> *
王岩 等: "一种基于Kafka的可靠的Consumer的设计方案", 《软件》 *
高宗宝 等: "Spark平台中Kafka偏移量的读取管理与设计", 《软件》 *

Cited By (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN115051963A (zh) * 2022-06-06 2022-09-13 阿里巴巴(中国)有限公司 消息处理方法及装置、消息队列***及电子设备
CN115051963B (zh) * 2022-06-06 2024-01-26 阿里巴巴(中国)有限公司 消息处理方法及装置、消息队列***及电子设备
CN115396339A (zh) * 2022-08-24 2022-11-25 银清科技有限公司 一种异常报文处理方法及装置

Also Published As

Publication number Publication date
CN114500416B (zh) 2024-07-09

Similar Documents

Publication Publication Date Title
CN110113420B (zh) 基于nvm的分布式消息队列管理***
US9009104B2 (en) Checkpoint-free in log mining for distributed information sharing
US5987502A (en) Workload management in an asynchronous client/server computer system
US7779418B2 (en) Publisher flow control and bounded guaranteed delivery for message queues
JP5714571B2 (ja) キャッシュクラスタを構成可能モードで用いるキャッシュデータ処理
US7647595B2 (en) Efficient event notification in clustered computing environments
US6247141B1 (en) Protocol for providing replicated servers in a client-server system
CN111368002A (zh) 一种数据处理方法、***、计算机设备和存储介质
US8954994B2 (en) System and method for message service with unit-of-order
CN105493474B (zh) 用于支持用于同步分布式数据网格中的数据的分区级别日志的***及方法
US7818386B2 (en) Repeatable message streams for message queues in distributed systems
CN114500416A (zh) 用于最多一次消息投递的投递方法和投递***
CN102449628A (zh) 用于持久性Web应用设计的架构模式
US20120278422A1 (en) Live object pattern for use with a distributed cache
EP4213038A1 (en) Data processing method and apparatus based on distributed storage, device, and medium
CN110134550B (zh) 一种数据处理方法、装置以及计算机可读存储介质
CN112052230B (zh) 多机房数据同步方法、计算设备及存储介质
US9298765B2 (en) Apparatus and method for handling partially inconsistent states among members of a cluster in an erratic storage network
US20140108642A1 (en) Efficient Reliable Distributed Flow-controlled Event Propagation
JP2017516237A (ja) 分散データグリッドにおける分散データ構造をサポートするためのシステムおよび方法
US20090150395A1 (en) System and method for updating file
CN114625566A (zh) 数据容灾方法、装置、电子设备及存储介质
CN106951443B (zh) 基于分布式***的副本同步的方法、设备和***
CN113326146A (zh) 一种消息处理方法、装置、电子设备及存储介质
US11386043B2 (en) Method, device, and computer program product for managing snapshot in application environment

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination
GR01 Patent grant
GR01 Patent grant