搞了个线上故障,被老板骂了….

网站建设4年前发布
87 0 0
搞了个线上故障,被老板骂了....,大家好,我是Tom哥。,前几天跟一位小伙伴聊天,心情特别沮丧,刚被老板骂完…..,差点丢了饭碗,还好老板没说 “滚”。,就今年这就业行情,满眼都是泪哇。,小伙伴在一家初创公司,团队规模很小,老板为了节省成本,也没配置什么豪华阵容。,他的工作时间也不长,负责交易订单,前几天接到用户投诉,「我的订单列表」有多条一模一样的订单。,虽没造成什么资损,但严重影响用户体验。,看到这里,有经验的同学可能猜到,应该是接口没做防重控制。,日常开发中,重复提交也是蛮常见问题。,比如:用户提交一个表单,鼠标点的太快,正好前端又是个新兵蛋子,没做任何控制,瞬间就会有多个请求发到后端系统。,如果后端同学也没做兜底方案的话,悲剧就发生了。,常见的解决方案是借助数据库自身的「唯一索引约束」,来保证数据的准确性,这种方案一般在插入场景用的多些。,变种方案可以考虑单独创建一个防重表。,本文的案例有点特殊,订单号是后端系统生成的,前后两次请求无法区分重复状态,所以系统会创建两条不同订单 ID 记录,绕过了「唯一索引约束」这个限制,这…..,另外,MySQL 性能也单薄了点,单机 QPS 在「千」维度,如果是面对一个高并发接口,性能也有点吃紧。,接下来,我们就来讲下,借助 Redis 来实现接口防重复提交。,首先,我们来看下整理的流程,如下图所示:,搞了个线上故障,被老板骂了....,大致步骤:,1、客户端发送请求到服务端。,2、服务端接收请求,然后从请求参数中提取唯一标识。这个标识可以没有什么特殊业务含义,client 端随机生成即可。,3、服务端系统将唯一标识先尝试写入 Redis 缓存中,可以认为是加锁操作。,4、加锁失败,说明请求还在处理,此次是重复请求,可以丢弃。,5、加锁成功,继续后面正常业务逻辑处理。,6、业务逻辑处理完成后,删除加锁的标记。,7、最后,将处理成功的结果返回给客户端。,实战的项目采用 Spring Boot 搭建,这里需要引入 Redis 相关依赖。,application.properties 配置文件中,添加redis相关服务配置。,定义一个注解,配置在需要防重复的接口方法上,提高开发效率,同时降低代码的耦合度。,上面定义了IdempotentRule​注解,需要通过拦截器对正常的业务方法做拦截,增加一些特殊逻辑处理。,这里,比较特殊的是提取请求的唯一标识,由于不同的业务请求唯一标识不一样。,所以,这里采用 SPEL 表达式,将规则设置能力开放出去,由业务方自己定义,比如:,拦截器根据 SPEL 表达式( 如 “#userParam.cardNumber”)以及请求参数对象,计算当前请求唯一标识的值,,然后将值写入 Redis 中,并设置过时间。,如果设置成功,说明是第一次请求,继续下面的业务逻辑处理;否则,判定为重复请求,直接丢弃。,1、构造客户端请求,第一次处理成功。,搞了个线上故障,被老板骂了....,2、 Redis 缓存中,能查到请求设置的锁标记。,搞了个线上故障,被老板骂了....,3、模拟重复,连续多次快速提交请求,请求会被拦截,并抛出异常。,搞了个线上故障,被老板骂了....
© 版权声明

相关文章