为了防止消息重复消费导致业务处理异常,轻量消息队列(原 MNS)的消费者在接收到消息后,需要根据业务唯一标识对消息做幂等处理。本文介绍消费幂等的概念、适用场景以及处理方法。
什么是消费幂等
在消息队列场景中,消费幂等处理是指即使因为某些原因(如网络问题、系统故障等)导致同一条消息被多次发送给消费者,通过幂等性设计也能保证最终的业务逻辑只被执行一次,避免因为重复消费而导致数据错误或业务结果不一致的情况。
例如,在支付场景下,Consumer消费扣款消息,对一笔订单执行扣款操作,扣款金额为100美元。如果因网络不稳定、系统故障等原因导致扣款消息重复投递,Consumer重复消费了该扣款消息,但最终的业务结果是只扣款一次,扣费100美元,且用户的扣款记录中对应的订单只有一条扣款流水,不会多次扣除费用。那么这次扣款操作是符合要求的,整个消费过程实现了幂等处理。
适用场景
幂等性在分布式系统中尤为重要,当系统出现网络抖动、系统故障、重复发送等异常时,消息可能会被重复消费,幂等性可以在消息重复时提高系统的可靠性和一致性。消息重复的可能原因如下:
消费处理耗时超过消息不可见时间:当某个消费者A处理消息的时长超过了不可见时间,消息会重新被投递给消费者B,这种情况下会导致消费者A和B重复处理同一条消息。
网络异常或抖动:消息已被消费者处理成功,但网络异常导致
DeleteMessage
请求异常,消息在不可见时间之后会被重新投递给消费者。消息队列服务器或消费者服务重启:消息已被消费者处理成功,但消息队列服务器或者消费者服务重启导致
DeleteMessage
请求处理失败,消息在不可见时间之后会被重新投递给消费者。
处理方法
在消息队列中,通常以Message ID为幂等键对消息进行幂等处理,但是由于不同的Message ID对应的消息内容可能相同,有可能出现冲突(重复)的情况,所以真正安全的幂等处理不建议以Message ID作为处理依据。轻量消息队列(原 MNS)建议您以业务唯一标识作为幂等处理的关键依据。
唯一标识符:为每个消息分配一个唯一的标识符,消费者在处理消息时,记录已处理的业务唯一标识,当再次收到相同的消息时,消费者可以直接跳过不再处理。
数据库约束:在数据库中设置唯一约束,当尝试插入重复数据时会因为违反约束而失败,从而实现幂等性。
业务状态机检查:在处理消息之前,消费者先检查数据的当前状态,比如数据是否已存在或已被处理。如果是,则直接返回,不再执行后续操作。
合并操作:对于某些操作,可以通过合并的方式来确保幂等性,即使执行多次,也只会产生一次最终结果。