redis+定时 模拟滑动窗口实现熔断降级

业务背景

公司业务现用的通道为 A、B,为了降本,引入新的支付通道 Y,但 Y 通道的稳定性要低于 A、B,系统要能在 Y 通道故障时自动切回到 A、B,等 Y 恢复正常后,再切换到 Y。

乍一看很简单,不就是熔断降级、故障恢复吗,有很多成熟的解决方案了。

但有个特殊的业务场景,在支付通道的页面中(也就是输入密码的这一步)可能因为商户原因,无法继续支付。这一步已经脱离了我们自己业务的页面,所以也无法获知这个失败场景。

还有一个场景是到输密码这一步,由于种种原因,用户返回了,终止了 支付流程。这种我们系统也无法获知,更无法区分是商户还是用户的原因,导致这笔支付没有完成。

这个业务场景很重要,虽然发生的概率极低,但必须要解决,否则真有问题等用户反馈过来,其影响是不能接受的。

调研

现成的技术方案,像 Sentinel 等框架,都需要告诉框架一个明确的采样规则及触发点。

比如1分钟内异常的数量、超时的数量、请求失败的数量,或者调用量达到多少后触发。

由于业务场景的特殊性,没找到可以直接满足业务需求的现成方案,只能自己想办法解决。

方案设计

如上所述,需要解决的2个关键点是采样规则和触发点。

采样规则可细分为 采样窗口、采样数量、采样数据。

根据我们业务的支付量,我们确定了采样窗口为最近半小时内,依次向后滑动;

采样数量为走 Y 通道的全量;

采样数据为支付成功数据、总数据。

上面交代了系统无法直接准确获知 Y 通道失败,所以就换了解决思路。

我们可以从系统现有的 A、B 通道的数据分析出用户原因未支付的比例(A、B 通道非常稳定,通道导致的失败率可以忽略不计),这样一来就可以得出支付成功的比例。

如果切换到 Y 通道后,低于这个比例,大概率是商户问题导致支付中断。

这个比例就可以作为我们的触发点。

简单画个草图

db99b611a6f4e93d8bc068dcace7df02.png

通过这个方案就可以尽早发现商户问题导致的支付中断,满足业务诉求。

扯两句

用低成本满足业务诉求;

任何方案都要权衡取舍。

原创不易,多多关注,一键三连,感谢支持!

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,在pom.xml文件中添加redis和quartz依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> ``` 然后在application.properties文件中添加redis和quartz的配置: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.database=0 # Quartz Configuration org.quartz.scheduler.instanceName = QuartzScheduler org.quartz.scheduler.instanceId = AUTO org.quartz.threadPool.threadCount = 10 ``` 接着,创建一个RedisService类来操作Redis: ```java @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; public Long incr(String key) { return redisTemplate.opsForValue().increment(key); } public Long decr(String key) { return redisTemplate.opsForValue().decrement(key); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } } ``` 然后,创建一个LikeJob类来定时将点赞次数写入数据库: ```java public class LikeJob implements Job { @Autowired private RedisService redisService; @Autowired private LikeService likeService; @Override public void execute(JobExecutionContext context) throws JobExecutionException { Object likeCount = redisService.get("like_count"); if (likeCount != null) { int count = Integer.parseInt(likeCount.toString()); likeService.writeLikeCount(count); redisService.set("like_count", 0); } } } ``` 最后,创建一个LikeController类来接收点赞请求: ```java @RestController public class LikeController { @Autowired private RedisService redisService; @GetMapping("/like") public String like() { redisService.incr("like_count"); return "success"; } } ``` 这样,每次访问 /like 接口时,Redis中的like_count计数器就会加1,而定时任务会在固定时间将计数器的值写入数据库,并将计数器重置为0。这样就实现了点赞功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值