其他
阿里一面:如何保障消息100%投递成功、消息幂等性?
1、《往期精选优秀博文都在这里了!》 2、在 IDE 中玩转 GitHub 3、死磕18个Java8日期处理,工作必用! 4、Netflix创始人:我不要求996,一样市值1万亿! 5、2021年 我辞职了! 来源:toutiao.com/i6672235084336071179
前言
(1)订单服务投递消息给MQ中间件 (2)物流服务监听MQ中间件消息,从而进行消费
分析问题
持久化
confirm机制
(1)消息生产者把消息发送给MQ,如果接收成功,MQ会返回一个ack消息给生产者; (2)如果消息接收不成功,MQ会返回一个nack消息给生产者;
消息提前持久化 + 定时任务
(1)订单服务生产者在投递消息之前,先把消息持久化到Redis或DB中,建议Redis,高性能。消息的状态为发送中。 (2)confirm机制监听消息是否发送成功?如ack成功消息,删除Redis中此消息。 (3)如果nack不成功的消息,这个可以根据自身的业务选择是否重发此消息。也可以删除此消息,由自己的业务决定。 (4)这边加了个定时任务,来拉取隔一定时间了,消息状态还是为发送中的,这个状态就表明,订单服务是没有收到ack成功消息。 (5)定时任务会作补偿性的投递消息。这个时候如果MQ回调ack成功接收了,再把Redis中此消息删除。
幂等含义
为什么要有幂等这种场景?
乐观锁方案
唯一ID + 指纹码
唯一ID就是业务表的唯一的主键,如商品ID
指纹码就是为了区别每次正常操作的码,每次操作时生成指纹码;可以用时间戳+业务编号的方式。
返回如果为0 表示没有操作过,那业务操作后就可以insert into t_check(唯一ID+指纹码)
返回如果大于0 表示操作过,就直接返回
Redis原子操作
这个意思就是库存减1了,但redis进行操作完成标记时,失败了怎么办?也就是一定要保证落库和redis 要么一起成功,要么一起失败
这个意思就是库存减1,不落库,直接先操作redis操作完成标记,然后由另外的同步服务进行库存落库,这个就是增加了系统复杂性,而且同步策略如何设置