幂等性是什么?
我们可以借鉴数据的乐观锁机制:
比如我们执行一条更新库存的SQL语句
update t_reps set count = count - 1, version = version + 1 where version = 1 and id = 100
幂等性就是对一件事情进行一个操作,这个操作执行100次,1000次,可他的结果还是相同的!比如结果是10,然后这个执行100次,1000次,可这个结果还是10
消费端-幂等性保障
在海量订单产生的业务高峰期,如何避免消息的重复消费问题?
就是可能在极端情况下,出现导致消息重复投递,或者因为网络问题导致的闪断!导致Callback进行触发重复发消息!这种情况下就要做幂等处理!
消费端实现幂等性,就意味着,我们的消息永远不会消费多次,即时我们收到了多条一样的消息!
主流的幂等性操作:
-
唯一ID + 指纹码 机制, 利用数据库主键去重
-
利用Redis的原子性
唯一ID + 指纹码 机制, 利用数据库主键去重
唯一ID + 指纹码 机制, 利用数据库主键去重
select count(*) from t_order where id = 唯一ID + 指纹码
好处:实现简单
坏处:高并发情况下有数据库写入的性能瓶颈
解决方案:跟进ID 进行分库分表进行算法路由
指纹码:可以是具体的规则生成的标记,也可以是时间戳,或者是银行返给我们的流水号
比如 消费端接收到消息后 ,执行 select count(*) from t_order where id = 唯一ID + 指纹码 操作,如果查询到有数据,就返回失败,表示这个消息已经处理过!如果没有查询到,就进行 insert 插入操作!
利用Redis的原子性实现
使用redis进行幂等,需要考虑的问题
比如 set 一个key,然后在 set 第二个的话,就覆盖前面一个!
或者说做一个预先判断这个 key 是否存在,存在则不执行,不存在则执行
等等
但是在使用Redis完成这个幂等事情的时候,需要考虑什么事情
- 我们是否要进行数据库落库,如果落库的话,关键解决的问题是数据库和缓存如何做到原子性?
如果接到消息后,这个消息记录要入库,该怎么保证redis和数据库的同时成功,同时失败?也就是redis进行set这个key后,成功了,然后数据库要记录一条消息的执行记录,如果保证 redis 进行 set 操作和数据库insert操作的同时成功,同时失败!
- 如果不进行落库,那么都存储到缓存中,如何设置定时同步的策略?
也就是消息记录,也放进redis里面,然后设置一个同步的策略,把消息记录的数据同步到数据库中进行持久化!因为缓存宕机后, 可能会丢失一些数据
网友评论