一种Kafka消息唯一消费方法、系统、服务器及存储介质
技术领域
本发明涉及软件工程领域,具体涉及一种Kafka消息唯一消费方法、系统、服务器及存储介质。
背景技术
Kafka作为一个流式消息处理中间件,具有高吞吐能力,快速读写能力和负载均衡能力,常被应用在日志处理,消息分发等。Kafka在架构上分为生产者,平台和消费者。生产者负责生产消息到平台,平台负责托管消息以及生产和消费的负载均衡,消费者则从平台拉取自己所需的消息。Kafka的消费者消费消息是基于Offset的,且Kafka本身不维护消费者的消费Offset,Offset的管理需要消费者自行管理。消费者消费完消息会记录最新消费的Offset,如下:Topic--Partition--Offset,即某消费者消费某个Topic的消息的某个Partition的Offset是什么。之所以有Offset这个概念是因为同个消费组内的消费者会增加或者减少,如消费者宕机等,新的消费者基于Offset便可得知最新的Offset,便可以继续消费消息。Kafka提供了消费者消费消息的Api,Api提供了保存Offset的方法,目前有两种种方法;
方法一,设置Offset自动更新到Kafka,更新的间隔为时间间隔和消费的消息数量间隔。
方法二,不采用Offset自动更新,而是在程序中手动更新Offset。既可以是拿到消息立刻更新Offset,也可以是消费完消息后更新Offset。
以上的两种方法都可以完成消息消费后更新Offset的功能,但是存在的问题是,无法保证消息的有且仅有1次消费的保证。如方法一中,程序在某一时刻触发了自动更新Offset的动作,但是此时消费者宕机,正在消费的数据丢失,但是消费的Offset已经更新到Kafka,待消费者恢复后,从Kafka获取的最新消费Offset开始消费,便会丢失部分数据。方法二中,从平台拉到消息后立刻更新Offset,此时消费者宕机,则同样出现方法一中的问题,或者从平台拉到消息后,消费完成后,手动更新Offset,但是更新的过程中消费者宕机,没有更新成功,待消费者重启后,获取到的最新消费Offset其实已经落后于实际消费消息的Offset,则会出现重复消费问题。
在大多数场景中,系统默认允许部分消息的丢失或重复消费,但是某些系统不能如此,希望能实现消息的有且仅有1次消费。
发明内容
鉴于现有技术存在的问题,本发明的目的是提供一种Kafka消息唯一消费方法、系统、服务器及存储介质,将消费者从平台拉到的消息保存在外部存储Redis中,同时将消息消费的Offset放置在Redis中,通过Redis来托管消费者的消息消费状态,并结合一定的故障处理策略,实现Rafka消费唯一消费。
为了实现上述目的,本发明采用的技术方案为一种Kafka消息唯一消费方法,所述方法包括以下步骤:
S1、Kafka消息分发平台包括多个Topic消息类,每个Topic消息类包括多个Partition分块,每个Partition分块包括消费者的消费记录Offset,通过Redis中Hash结构,创建Hash结构的多个第一Key值,所述第一Key值用于记录消费者对每个Topic消息类所有的Partition分块消费记录Offset;
S2、在Redis的Hash结构中创建第二Key值,所述第二Key值用于存储所述任一Topic消息任一Partition分块内获取的批量的消息;
S3、通过步骤S2获取的批量消息,存储于Redis的第二Key值中,消费者根据需求对所述存储的消息进行消费,并等待消息消费完毕后更新步骤S1中第一Key值中的消费记录Offset,并进行删除处理;
S4、消费者消费中若发生宕机,重新启动后,需确认步骤S2中Redis的Key值中是否有消息,若有消息则继续消费,若没有消息,则重复步骤S3继续进行消息处理。
在上述技术方案中,所述每个Topic建立第一Key值,结构为Topic_consumerGroup,所述Topic_consumerGroup结构中包括的多个第一Field与所述Topic的所有Partition一一对应,第一Field的第一Value值为所述Topic的Partition的Offset值。
在上述技术方案中,所述每个Topic创建第二Key值,其结构为Topic_consumerGroup_partitionId_msgOffsetStart_msgOffsetEnd,其中MsgOffsetStart和MsgOffsetEnd为Kafka平台拉取消息的开始消费记录offset和结束消费记录offset,第二Key值中第二Field为所述当前消费记录offset的值,第二Value为消息的具体内容。
在上述技术方案中,所述批量消息处理完后进行的删除处理包括以下步骤:
S31、若消息消费失败,则根据失败消息的ID,通过第二Key值重新获取所述失败的消息并进行消费处理,直至消费成功;
S32、若批量消息全部消费成功,记录所述消费成功的MsgOffsetEnd,并删除Redis的第二Key值,并将MsgOffsetEnd消费成功的数据在所述第一Key值中对应管理的消费组的Topic的Partition的Offset进行更新。
在上述技术方案中,所述步骤S32中若MsgOffsetEnd消费记录数据在第一Key值中的Offset中需要更新的位置已经被其他Topic消费数据更新,则不再更新MsgOffsetEnd消费记录数据,若未更新,则进行更新,并将更新后的第一Key值中的Offset值更新至Kaflka平台。
本发明还公开一种Kafka消息唯一消费系统,所述系统包括第一创建模块、第二创建模块、消息处理模块及判断模块;
第一创建模块,用于将Kafka消息分发平台包括多个Topic消息类,每个Topic消息类包括多个Partition分块,每个Partition分块包括消费者的消费记录Offset,通过Redis中Hash结构,创建Hash结构的多个第一Key值,所述第一Key值用于记录消费者对每个Topic消息类所有的Partition分块消费记录Offset;
第二创建模块,用于在Redis的Hash结构中创建第二Key值,所述第二Key值用于存储所述任一Topic消息任一Partition分块内获取的批量的消息;
消息处理模块,用于通过第二创建模块获取的批量消息,存储于Redis的第二Key值中,消费者根据需求对所述存储的消息进行消费,并等待消息消费完毕后更新步骤S1中第一Key值中的消费记录Offset,并进行删除处理;
判断模块,用于当消费者消费中若发生宕机,重新启动后,需确认第二创建模块中Redis的第二Key值中是否有消息,若有消息则继续消费,若没有消息,则在消息处理模块中重复进行消息处理。
在上述技术方案中,所述消息处理模块还包括消费失败处理模块及消费成功更新模块;
消费失败处理模块,若消息消费失败,则根据失败消息的ID,通过第二Key值重新获取所述失败的消息并进行消费处理,直至消费成功;
消费成功更新模块,若批量消息全部消费成功,记录所述消费成功的MsgOffsetEnd,并删除Redis的第二Key值,并将MsgOffsetEnd消费成功的数据在所述第一Key值中对应管理的消费组的Topic的Partition的Offset进行更新。
在上述技术方案中,所述消费成功更新模块中,若MsgOffsetEnd消费记录数据在第一Key值中的Offset中需要更新的位置已经被其他Topic的消费数据更新,则不再更新MsgOffsetEnd消费记录数据,若未更新,则进行更新,并将更新后的第一Key值中的Offset值更新至Kaflka平台。
本发明还公开一种Kafka消息唯一消费系统的服务器,包括存储器、处理器以及存储在所述存储器中并可在所述处理器上运行的计算机程序,所述处理器执行所述计算机程序时实现上述任一项所述一种Kafka消息唯一消费方法的步骤。
本发明还公开一种计算机可读存储介质,所述计算机可读存储介质存储有计算机程序,所述计算机程序被处理器执行时实现上述任一项所述一种Kafka消息唯一消费方法的步骤。
本发明一种Kafka消息唯一消费方法、系统、服务器及存储介质,具有以下有益效果:基于Redis作为临时Offset管理,同时将批量消息临时存储于Redis中,保证每条消息能够被成功且唯一消费,且在消费者宕机恢复后,能够及时判断是否有未消费完成的消息且及时消费完成,避免了重启后消息重复消费。
附图说明
图1为本发明实施例一提供的一种Kafka消息唯一消费方法的流程图;
图2本发明实施例二提供一种Kafka消息唯一消费系统模块图;
图3为本发明实施例三提供的服务器的结构示意图。
具体实施方式
本发明提供一种Kafka消息唯一消费方法、系统、服务器及存储介质,将消费者从平台获取的消息保存在外部存储Redis中,同时将消息消费的Offset放置在Redis中,通过Redis托管消费者的消息消费状态,并结合一定的故障处理策略,实现kafka消费唯一消费。
为使得本发明的发明目的、特征、优点能够更加的明显和易懂,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,下面所描述的实施例仅仅是本发明一部分实施例,而非全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其它实施例,都属于本发明保护的范围。
本发明如图1所示实施例一提供一种Kafka消息唯一消费方法,所述方法包括以下步骤,如图1所示:
S1、Kafka消息分发平台包括多个Topic消息类,每个Topic消息类包括多个Partition分块,每个Partition分块包括消费者的消费记录Offset,通过Redis中Hash结构,创建Hash结构的多个第一Key值,所述第一Key值用于记录消费者对每个Topic消息类所有的Partition分块消费记录Offset;
可选的,所述每个Topic的每个消费组建立一个Redis第一Key值,结构为Topic_consumerGroup,所述Topic_consumerGroup结构中包括的多个第一Field与所述Topic的所有Partition一一对应,即Topic有多少个Partition,该Hash便会有多少个Field,第一Field的第一Value值为所述消费组消费所述Topic的所述Partition的Offset值;结构如下:Redis key:topic1_consumerGroup1
Hash field:partition1
Hash value:123
其中,Kafka是一种分布式的,基于发布/订阅的消息系统,以时间复杂度为O(1)的方式提供消息持久化能力,并保证即使对TB级以上数据也能保证常数时间的访问性能;高吞吐率即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输;支持KafkaServer间的消息分区,及分布式消息消费,同时保证每个Partition内的消息顺序传输,同时支持离线数据处理和实时数据处理。每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic,Parition是物理上的概念,每个Topic包含一个或多个partition,创建Topic时可指定Parition数量。每个Partition对应于一个文件夹,该文件夹下存储该Partition的数据和索引文件。Kafka消费者在会保存其消费的进度,也就是Offset,存储的位置根据选用的Kafka Api不同而不同。
一个Group中会包含多个consumer,这样不仅提高Topic中消息的并发消费能力,而且还能提高”故障容错”性,如果Group中的某个Consumer失效那么其消费的Partitions将会有其他Consumer自动接管,对于Topic中的一条特定的消息,会被订阅此Topic的每个Group中的其中一个Consumer消费,此消息不会发送给一个Group的多个Consumer;在kafka中,一个Partition中的消息会被Group中的一个Consumer消费(同一时刻),一个Topic中的每个Partions,会被一个”订阅者”中的一个Consumer消费,不过一个Consumer可以同时消费多个Partitions中的消息。
Consumer group是Kafka提供的可扩展且具有容错性的消费者机制。是一个组,组内有多个消费者或消费者实例(consumer instance),它们共享一个公共的ID,即groupID。组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一个消费组内的一个Consumer来消费。
Consumer group下有一个或多个Consumer Instance,Consumer Instance可以是一个进程,也可以是一个线程,Group.id是一个字符串,唯一标识一个Consumer Group,Consumer group下订阅的topic下的每个分区只能分配给某个Group下的一个Consumer(当然该分区还可以被分配给其他Group)。
Partition、Offset都是为Topic服务的,每个Topic可以分为多个Partition,一个Partition相当于一个大目录,Topic是消息归类的一个标志,一个Topic的消息为一类。Partition是一类消息的分块,及防止一类消息量存储过大,故切割分块存储。Offset指某个消费者针对某个Topic的某Partition的消息消费的最新位置。一个Topic会有多个Partition,每个Partition都供消费者消费,所以每个Partition都有各自的消费记录Offset,其中,消费者在消费的过程中需要记录自己消费了多少数据,即消费位置信息。在Kafka中这个位置信息有个专门的术语为位移offset。
具体的,Kafka中的Message是以Topic为基本单位组织的,不同的Topic之间是相互独立的。每个Topic又可以分成几个不同的Partition(每个Topic有几个Partition是在创建Topic时指定的),每个Partition存储一部分Message。
Partition是以文件的形式存储在文件系统中,例如,创建了一个名为Page_visits的Topic,其有5个Partition,在Kafka的数据目录中(由配置文件中的log.dirs指定的)中就有这样5个目录:Page_visits-0,Page_visits-1,Page_visits-2,Page_visits-3,Page_visits-4,其命名规则为<Topic_name>-<Partition_id>,里面存储的分别就是这5个Partition的数据。
Partition中的每条Message由Offset来表示它在这个Partition中的偏移量,这个Offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了Partition中的一条Message。因此,可以认为Offset是partition中Message的ID。Partition中的每条Message包含了以下三个属性:
offset
MessageSize
data
其中offset为long型,MessageSize为int32,表示Data有多大,Data为Message的具体内容。
S2、在Redis的Hash结构中创建第二Key值,所述第二Key值用于存储所述任一Topic消息任一Partition分块内获取的批量的消息;
可选的,所述每个Topic创建第二Key值,其结构为Topic_consumerGroup_partitionId_msgOffsetStart_msgOffsetEnd,其中MsgOffsetStart和MsgOffsetEnd为Kafka平台拉取消息的开始消费记录offset和结束消费记录offset,第二Key值中第二Field为所述当前消费记录offset的值,第二Value为消息的具体内容。所述建立第二Key值的目的是针对消息失败时,获取Redis消息再次消费,保证系统正常运行。结构如下:
Rediskey:topic1_consumerGroup1_partition1_100_200
Hash field:123
Hash value:i am message
S3、通过步骤S2获取的批量消息,存储于Redis的第二Key值中,消费者根据需求对所述存储的消息进行消费,并等待消息消费完毕后更新步骤S1中第一Key值中的消费记录Offset,并进行删除处理;
可选的,所述批量消息处理完后进行的后续处理包括以下步骤:
S31、若消息消费失败,则根据失败消息的ID,通过第二Key值重新获取所述失败的消息并进行消费处理,直至消费成功;
S32、若批量消息全部消费成功,记录所述消费成功的MsgOffsetEnd,并删除Redis的第二Key值,并将MsgOffsetEnd消费成功的数据在所述第一Key值中对应管理的消费组的Topic的Partition的Offset进行更新。
可选的,所述步骤S32中若MsgOffsetEnd消费记录数据在第一Key值中的Offset中需要更新的位置已经被其他Topic消费数据更新,则不再更新MsgOffsetEnd消费记录数据,若未更新,则进行更新,并将更新后的第一Key值中的Offset值更新至Kaflka平台。
S4、消费者消费中若发生宕机,重新启动后,需确认步骤S2中Redis的Key值中是否有消息,若有消息则继续消费,若没有消息,则重复步骤S3继续进行消息处理。
本发明实施例二还提供一种Kafka消息唯一消费系统,所述系统包括第一创建模块、第二创建模块、消息处理模块及判断模块;
第一创建模块,用于将Kafka消息分发平台包括多个Topic消息类,每个Topic消息类包括多个Partition分块,每个Partition分块包括消费者的消费记录Offset,通过Redis中Hash结构,创建Hash结构的多个第一Key值,所述第一Key值用于记录消费者对每个Topic消息类所有的Partition分块消费记录Offset;
第二创建模块,用于在Redis的Hash结构中创建第二Key值,所述第二Key值用于存储所述任一Topic消息任一Partition分块内获取的批量的消息;
消息处理模块,用于通过第二创建模块获取的批量消息,存储于Redis的第二Key值中,消费者根据需求对所述存储的消息进行消费,并等待消息消费完毕后更新步骤S1中第一Key值中的消费记录Offset,并进行删除处理;;
判断模块,用于当消费者消费中若发生宕机,重新启动后,需确认第二创建模块中Redis的第二Key值中是否有消息,若有消息则继续消费,若没有消息,则在消息处理模块中重复进行消息处理。
其中,所述消息处理模块还包括消费失败处理模块及消费成功更新模块;
消费失败处理模块,若消息消费失败,则根据失败消息的ID,通过第二Key值重新获取所述失败的消息并进行消费处理,直至消费成功;
消费成功更新模块,若批量消息全部消费成功,记录所述消费成功的MsgOffsetEnd,并删除Redis的第二Key值,并将MsgOffsetEnd消费成功的数据在所述第一Key值中对应管理的消费组的Topic的Partition的Offset进行更新。
其中,所述消费成功更新模块中,若MsgOffsetEnd消费记录数据在第一Key值中的Offset中需要更新的位置已经被其他Topic的消费数据更新,则不再更新MsgOffsetEnd消费记录数据,若未更新,则进行更新,并将更新后的第一Key值中的Offset值更新至Kaflka平台。
本发明实施例三如图3所示提供一种Kafka消息唯一消费系统的服务器结构示意图,所述实施例的服务器包括:处理器30、存储器31以及存储在所述存储器31中并可在所述处理器30上运行的计算机程序32。所述处理器30执行所述计算机程序32时实现上述各方法实施例中的步骤,所述处理器30执行所述计算机程序32时实现上述装置实施例中各模块的功能。
所述一种Kafka消息唯一消费系统的服务器可以是桌上型计算机、笔记本、掌上电脑及云端服务器等计算设备,所述一种Kafka消息唯一消费系统的服务器可包括,但不限于,处理器30、存储器31。图3仅仅是对此服务器的示例,并不构成对此服务器的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件,所述一种实现Redis的HASH键的域生命周期控制系统的服务器还可以包括输入输出设备33、显示设备34等。
所述处理器30可以是中央处理单元,还可以是其他通用处理器、数字信号处理器、专用集成电路、现成可编程门阵列或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等。
所述存储器31可以是所述一种Kafka消息唯一消费系统的服务器的内部存储单元、硬盘或内存。所述存储器31也可以是所述服务器的外部存储设备,或配备的插接式硬盘,智能存储卡,安全数字卡,闪存卡等。
进一步地,所述存储器31还可以既包括所述服务器的内部存储单元也包括外部存储设备。所述存储器31用于存储所述计算机程序以及所述电子设备所需的其他程序和数据。所述存储器31还可以用于暂时地存储已经输出或者将要输出的数据。
所述的输入输出设备33可用于接收输入的数字或字符信息,具体的,输入输出设备33还可以包括但不限于键盘、鼠标、操作杆等中的一种和多种。
所述的显示设备34可用于显示由用户输入的信息或提供给用户信息以及终端的各种菜单,显示设备34可包括显示面板,可选的,可采用液晶显示器。
所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。
本领域普通技术人员可以意识到,结合本文中所公开的实施例描述的各实施例的模块、方法步骤,能够以电子硬件、或者计算机软件和电子硬件的结合来实现。专业技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应认为超出本发明的范围。
所述集成的模块如果以软件功能模块的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明实现上述实施例方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、U盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器(ROM,Read-Only Memory)、随机存取存储器(RAM,RandomAccess Memory)、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读介质不包括电载波信号和电信信号。
以上所述,以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。