本发明涉及分布式消息发布-订阅系统,尤其是涉及一种基于Redis的Kafka消息唯一性方法。
背景技术:
Apache Kafka是分布式消息发布-订阅系统。与传统的消息服务RabbitMQ、Apache ActiveMQ相比吞吐量提高了几个数量级。目前Kafka已广泛在日志处理等系统中使用。
在Kafka使用中,消息的消费者必须自己维护当前消费的消息的位置,比如将位置保存在Zookeeper中。当消费者处理完一批消息后,先提交消息保存位置,然后再读取和处理下一批消息。这样就造成了一个问题,当消费者崩溃时,位置信息还没来得及保存,下一次读取位置会跟上一次提交之后的位置相同,这样就会导致消息重复消费。
在日志处理等系统中,消息重复消费并不是什么大问题,但对于如交易消息等却是不可接收的。这样就极大的限制了Kafka的使用范围。
技术实现要素:
本发明的目的是针对上述问题提供一种避免消息重复消费、吞吐量高以及可靠性高的基于Redis的Kafka消息唯一性方法方法。
本发明的目的可以通过以下技术方案来实现:
一种基于Redis的Kafka消息唯一性方法,利用Redis解决Kafka中消息重复消费的问题,所述方法包括下列步骤:
1)接收一组消息数据;
2)采用分布式选举算法,对步骤1)接收的消息数据进行过滤;
3)分别对过滤后的每条消息数据进行业务逻辑处理;
4)判断步骤3)中的业务逻辑处理是否出错,若是,则进入步骤5),若否,则正常结束;
5)删除出错的消息数据条目。
所述步骤2),采用分布式选举算法进行过滤具体为:
21)为接收到的每个消息数据设置对应的一个UUID;
22)将同一消息数据分别发送至N个Redis中;
23)对N个Redis中的同一消息数据分别调用SETNX命令,记m为大于N/2的最小整数;
24)判断是否有m或大于m个SETNX命令的返回值为0,若是,则过滤该消息数据,若否,则保留该消息数据。
所述Redis的个数N为奇数。
所述SETNX命令包括key和value,调用所述SETNX命令时,将消息数据对应的UUID赋值给key,将当前时间赋值给value。
所述步骤23),调用SETNX命令后,判断key在Redis中是否已存在,若是,则返回值为0,若否,则返回值为1。
与现有技术相比,本发明具有以下有益效果:
(1)解决了Kafka消息重复问题,并且应用逻辑层无需的修改。
(2)Redis具有高性能,整个系统可以保证极高的吞吐量。
(3)采用多Redis实例集群,可容忍N-1个实例故障,有极高的可靠性。
(4)采用分布式选举算法,保证了数据的可靠性。
(5)多个Redis分别部署在不同的物理实体机上,避免了硬件损坏导致该解决方法不可用。
(6)在消息数据业务逻辑处理出错时,删除对应的消息数据,可以允许系统对这条数据再次处理,提高可靠性。
附图说明
图1为本发明的方法示意图。
具体实施方式
下面结合附图和具体实施例对本发明进行详细说明。本实施例以本发明技术方案为前提进行实施,给出了详细的实施方式和具体的操作过程,但本发明的保护范围不限于下述的实施例。
如图1所示,本发明提供了一种基于Redis的Kafka消息唯一性方法,Redis是一个key-value存储系统。它支持多种value类型存储,包括string(字符串)、list(链表)、set(集合)、zset(有序集合)和hash(哈希类型)。利用Redis解决Kafka中消息重复消费的问题,该方法包括下列步骤:
1)Kafka接收一组消息数据。
2)采用分布式选举算法,利用Redis的SETNX命令对步骤1)接收的消息数据进行过滤,具体为:
21)为接收到的消息数据设置一个UUID;
22)将该消息数据分别发送至N个Redis中,N为奇数;
23)对N个Redis中的消息数据分别调用SETNX命令,记m为大于N/2的最小整数;
24)判断是否有m或大于m个SETNX命令的返回值为0,若是则保留该消息数据,若否则过滤该消息数据。
3)对过滤后的每条消息数据进行业务逻辑处理。
4)判断步骤3)中的业务逻辑处理是否出错,若是则进入步骤5),若否则正常结束。
5)调用Redis的DEL命令删除出错的消息数据条目。
SETNX命令包括key和value,调用所述SETNX命令时,将消息数据对应的UUID赋值给key,将当前时间赋值给value。SETNX命令具体为判断key在Redis中是否存在,若是则返回值为0,若否则返回值为1。
步骤2)中使用“分布式选举算法”保证数据可靠性。一份数据会同时写入多个Redis实例(N为奇数),只有当大于N/2个实例操作成功时,才算操作成功。比如N为3,只有当2个或者2个以上实例操作成功时,才算操作成功。多个Redis分别部署在不同的物理实体机上。此算法保证N/2个实例故障,以此来保证系统高可用性。
如取N为5,使用上述步骤解决Kafka重复消息的问题,具体的解决方案为:
由于N为5,因此N/2为2.5,则应使用3个实例。为每个消息都设置一个唯一的UUID。对3个Redis实例分别调用SETNX命令,命令Key为消息UUID,Value为当前时间。如果有2个或者2个以上命令调用返回0,则说明消息未被处理过,系统调用之后的业务逻辑处理代码;否则说明消息已经被处理过,无需执行业务逻辑处理代码。程序根据需求判断业务逻辑处理代码是否运行正常,如果业务逻辑代码处理出错(如调用某个接口失败等),调用Redis的DEL命令删除数据,允许系统对这条数据再次处理。