跳至主要內容

幂等设计

HeChuangJun约 432 字大约 1 分钟

幂等?问题?解决方案?

多次执行同一个操作得到的结果一样
订单支付成功回调通知多次应该每次结果一致

前段重复提交、接口超时重试、mq消费读到重复消息

insert前先select:保存数据前先判断数据是否已存在,存在则直接返回,不存在才执行insert操作
建防重表并加唯一索引,捕获重复插入数据抛出的异常。java捕获DuplicateKeyException异常,spring捕获MySQLIntegrityConstraintViolationException异常

mysqlduplicateremove.png
mysqlduplicateremove.png

加悲观锁:同一时刻只允许一个请求获得锁,获取不到锁则返回失败,难保证接口返回相同值。如锁住账户余额select * from user id=xx for update;
加乐观锁:性能好。表添加timestamp或version字段,更新前查询数据,~作为更新条件,更新后version增加,重复更新请求失败:update user set amount=amount+1,version=version+1 where id=1 and version=1
状态机:有状态的业务,限制状态的流动,如订单表中状态1-下单、2-已支付、3-完成、4-撤销等
分布式锁:用Redission框架

redisduplicateremove.png
redisduplicateremove.png

token机制
客户端发送请求获取token,服务端生成全局唯一id作为token保存在redis中并返回给客户端
客户端调用业务请求时携带token
服务端校验token是否存在,存在则执行业务并删除redis中的token
不存在则表示重复操作,返回指定的结果给客户端

redis中是否存在token、删除token用Lua脚本保证原子性

token.png
token.png