本發(fā)明涉及分布式消息發(fā)布-訂閱系統(tǒng),尤其是涉及一種基于Redis的Kafka消息唯一性方法。
背景技術:
Apache Kafka是分布式消息發(fā)布-訂閱系統(tǒng)。與傳統(tǒng)的消息服務RabbitMQ、Apache ActiveMQ相比吞吐量提高了幾個數(shù)量級。目前Kafka已廣泛在日志處理等系統(tǒng)中使用。
在Kafka使用中,消息的消費者必須自己維護當前消費的消息的位置,比如將位置保存在Zookeeper中。當消費者處理完一批消息后,先提交消息保存位置,然后再讀取和處理下一批消息。這樣就造成了一個問題,當消費者崩潰時,位置信息還沒來得及保存,下一次讀取位置會跟上一次提交之后的位置相同,這樣就會導致消息重復消費。
在日志處理等系統(tǒng)中,消息重復消費并不是什么大問題,但對于如交易消息等卻是不可接收的。這樣就極大的限制了Kafka的使用范圍。
技術實現(xiàn)要素:
本發(fā)明的目的是針對上述問題提供一種避免消息重復消費、吞吐量高以及可靠性高的基于Redis的Kafka消息唯一性方法方法。
本發(fā)明的目的可以通過以下技術方案來實現(xiàn):
一種基于Redis的Kafka消息唯一性方法,利用Redis解決Kafka中消息重復消費的問題,所述方法包括下列步驟:
1)接收一組消息數(shù)據(jù);
2)采用分布式選舉算法,對步驟1)接收的消息數(shù)據(jù)進行過濾;
3)分別對過濾后的每條消息數(shù)據(jù)進行業(yè)務邏輯處理;
4)判斷步驟3)中的業(yè)務邏輯處理是否出錯,若是,則進入步驟5),若否,則正常結束;
5)刪除出錯的消息數(shù)據(jù)條目。
所述步驟2),采用分布式選舉算法進行過濾具體為:
21)為接收到的每個消息數(shù)據(jù)設置對應的一個UUID;
22)將同一消息數(shù)據(jù)分別發(fā)送至N個Redis中;
23)對N個Redis中的同一消息數(shù)據(jù)分別調(diào)用SETNX命令,記m為大于N/2的最小整數(shù);
24)判斷是否有m或大于m個SETNX命令的返回值為0,若是,則過濾該消息數(shù)據(jù),若否,則保留該消息數(shù)據(jù)。
所述Redis的個數(shù)N為奇數(shù)。
所述SETNX命令包括key和value,調(diào)用所述SETNX命令時,將消息數(shù)據(jù)對應的UUID賦值給key,將當前時間賦值給value。
所述步驟23),調(diào)用SETNX命令后,判斷key在Redis中是否已存在,若是,則返回值為0,若否,則返回值為1。
與現(xiàn)有技術相比,本發(fā)明具有以下有益效果:
(1)解決了Kafka消息重復問題,并且應用邏輯層無需的修改。
(2)Redis具有高性能,整個系統(tǒng)可以保證極高的吞吐量。
(3)采用多Redis實例集群,可容忍N-1個實例故障,有極高的可靠性。
(4)采用分布式選舉算法,保證了數(shù)據(jù)的可靠性。
(5)多個Redis分別部署在不同的物理實體機上,避免了硬件損壞導致該解決方法不可用。
(6)在消息數(shù)據(jù)業(yè)務邏輯處理出錯時,刪除對應的消息數(shù)據(jù),可以允許系統(tǒng)對這條數(shù)據(jù)再次處理,提高可靠性。
附圖說明
圖1為本發(fā)明的方法示意圖。
具體實施方式
下面結合附圖和具體實施例對本發(fā)明進行詳細說明。本實施例以本發(fā)明技術方案為前提進行實施,給出了詳細的實施方式和具體的操作過程,但本發(fā)明的保護范圍不限于下述的實施例。
如圖1所示,本發(fā)明提供了一種基于Redis的Kafka消息唯一性方法,Redis是一個key-value存儲系統(tǒng)。它支持多種value類型存儲,包括string(字符串)、list(鏈表)、set(集合)、zset(有序集合)和hash(哈希類型)。利用Redis解決Kafka中消息重復消費的問題,該方法包括下列步驟:
1)Kafka接收一組消息數(shù)據(jù)。
2)采用分布式選舉算法,利用Redis的SETNX命令對步驟1)接收的消息數(shù)據(jù)進行過濾,具體為:
21)為接收到的消息數(shù)據(jù)設置一個UUID;
22)將該消息數(shù)據(jù)分別發(fā)送至N個Redis中,N為奇數(shù);
23)對N個Redis中的消息數(shù)據(jù)分別調(diào)用SETNX命令,記m為大于N/2的最小整數(shù);
24)判斷是否有m或大于m個SETNX命令的返回值為0,若是則保留該消息數(shù)據(jù),若否則過濾該消息數(shù)據(jù)。
3)對過濾后的每條消息數(shù)據(jù)進行業(yè)務邏輯處理。
4)判斷步驟3)中的業(yè)務邏輯處理是否出錯,若是則進入步驟5),若否則正常結束。
5)調(diào)用Redis的DEL命令刪除出錯的消息數(shù)據(jù)條目。
SETNX命令包括key和value,調(diào)用所述SETNX命令時,將消息數(shù)據(jù)對應的UUID賦值給key,將當前時間賦值給value。SETNX命令具體為判斷key在Redis中是否存在,若是則返回值為0,若否則返回值為1。
步驟2)中使用“分布式選舉算法”保證數(shù)據(jù)可靠性。一份數(shù)據(jù)會同時寫入多個Redis實例(N為奇數(shù)),只有當大于N/2個實例操作成功時,才算操作成功。比如N為3,只有當2個或者2個以上實例操作成功時,才算操作成功。多個Redis分別部署在不同的物理實體機上。此算法保證N/2個實例故障,以此來保證系統(tǒng)高可用性。
如取N為5,使用上述步驟解決Kafka重復消息的問題,具體的解決方案為:
由于N為5,因此N/2為2.5,則應使用3個實例。為每個消息都設置一個唯一的UUID。對3個Redis實例分別調(diào)用SETNX命令,命令Key為消息UUID,Value為當前時間。如果有2個或者2個以上命令調(diào)用返回0,則說明消息未被處理過,系統(tǒng)調(diào)用之后的業(yè)務邏輯處理代碼;否則說明消息已經(jīng)被處理過,無需執(zhí)行業(yè)務邏輯處理代碼。程序根據(jù)需求判斷業(yè)務邏輯處理代碼是否運行正常,如果業(yè)務邏輯代碼處理出錯(如調(diào)用某個接口失敗等),調(diào)用Redis的DEL命令刪除數(shù)據(jù),允許系統(tǒng)對這條數(shù)據(jù)再次處理。