幂等设计-2

206 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

五,案例
1,企业级的电商下单
2,2台服务,1台DB,要求用户信息手机号不重复(手机号不可以为空或者手机号可以为空)。

六,总结-如何保证幂等:
1,基于状态的幂等
这种情况比较简单,只有当满足前置条件时才允许操作,否则不允许更新(例如已经是终态),直接返回。
例子:订单支付成功后,不允许重复支付。

2,基于唯一键的幂等
幂等key的选取
与业务强相关,可以是商品id、订单id、用户id,或者日期等,或者是几个业务字段的组合。
全局的唯一性ID Snowflake
几个例子:
一个用户每天只能领一张优惠券,通过 用户id+优惠券类型+日期字符串 即可唯一标识
B端更新库存,商品id+该商品的版本号
C端扣库存,订单id
值得注意的是,需要区分新增和修改:修改时的幂等key往往需要带上版本号,才能区分是否同一次修改,每次修改对应一个唯一的版本号。(因为乐观锁存在ABA的问题,如果version版本一直是自增的就不会出现ABA的情况啦。)
实现方式
MySQL表中为幂等key建立唯一索引:强幂等,例如资金、订单,绝对不允许重复处理,当插入重复数据时报错。
不推荐用Redis实现幂等,一旦Redis出问题,比如节点宕机,可能出现2个client同时获取到锁的情况。

3、消息订阅和处理
MQ通常会保证消息至少发送一次(可能多次),并且在机器实例重启或发版时,consumer group会做rebalance,进而收到重复的消息。因此,消息的幂等处理必不可少。
实现方式:
在处理消息前加上锁:如果上锁成功,则继续处理,否则稍后重试。
不存在时才设置,时效即为锁的租期,否则忽略
接下来的业务处理,如果是自身逻辑需要强幂等则使用上述数据库幂等方式,如果全部依赖下游则依赖下游实现幂等