• Spring-retry重试框架怎么用?看这里


    一. 问题

    近日有学生问壹哥,应该怎样理解【阿里巴巴开发规约中提到的乐观锁至少要重试三次】的规定,为了让大家更好的理解这一点,壹哥先来引用一下阿里巴巴开发规约中的相关规定。

    强制】并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。

    说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁乐观锁的重试次数不得小于 3 次。

    二. 解答

    对于这个问题,壹哥是这么认为的。【乐观锁采用CAS机制,在事务的最后才会根据version来判断事务是否能够提交成功。很多时候仅仅只是因为其他的事务快一步更新了version,就导致整个事务提交失败,这样给用户的体验并不好,所以咱们要在这里让事务重试几次,提升用户的使用体验】。

    其实重试的方式有很多,今天壹哥来给大家介绍一款Spring自带的重试框架 【spring-retry】

    三. spring-retry 框架介绍

    2.1 spring-retry框架是什么

    spring-retry是spring提供的一个重试框架,它通过几个注解就可以优雅的实现重试的功能。

    2.2 怎样使用spring-retry框架

    导入依赖

    1. <dependency>
    2. <groupId>org.springframework.retrygroupId>
    3. <artifactId>spring-retryartifactId>
    4. dependency>

    在主程序能够扫描到的类上,或者直接在主程序上添加@EnableRetry注解,开启重试。

    1. @SpringBootApplication
    2. @EnableRetry
    3. public class BankApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(BankApplication .class, args);
    6. }
    7. }

    在有可能需要重试的方法上添加注解。

    1. @Transactional
    2. @Retryable(value = { RetryException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000l, multiplier = 2,maxDelay = 10000l))
    3. // @Retryable 加上此注解 那么这个方法就有可能重试
    4. // value = { RetryException.class } 当方法中抛出RetryException异常就要重试
    5. // maxAttempts 最大重试的次数
    6. // Backoff 回避策略
    7. // delay 第一次重试的延迟时间
    8. // multiplier 下一次重试的延迟时间,公式为:上一次delay* multiplier
    9. // maxDelay:最长延迟时间
    10. public void getMoney(String ano, BigDecimal money){
    11. // 1 查询账号是否存在
    12. TbAccount tbAccount = accountMapper.selectByPrimaryKey(ano);
    13. if (tbAccount == null) {
    14. throw new AppException(ResponseEnum.ACCOUNT_NOT_FOUND);
    15. }
    16. // 2 余下额度是否够
    17. if(tbAccount.getAccountMoney().compareTo(money)<0){
    18. throw new AppException(ResponseEnum.ACCOUNT_MONEY_NOT_ENOUTH);
    19. }
    20. // 3 更新取钱
    21. int count = accountMapper.updateMoney(ano, money, tbAccount.getVersion());
    22. if(count==0){
    23. throw new RetryException("");
    24. }
    25. System.out.println("取钱成功");
    26. }

    如果最大重试次数也重试完了,但还是失败的话,添加我们将要执行的逻辑。

    1. @Recover
    2. public void recover(RetryException e) {
    3. throw new AppException(ResponseEnum.ACCOUNT_EXCEPTION);
    4. }

    四. 小结

    到此,细心的同学应该已经能发现,spring-retry这个框架的底层原理其实就是aop的异常增强。当方法中抛出指定类型异常的时候,我们就给予一定次数的重试。

    另外,重试的业务场景也不一定就局限在乐观锁上面,其他很多业务场景也需要使用到重试。

    比如说:

    • 由于网络波动或者系统太忙,造成远程调用失败需要重试;
    • 秒杀时使用分布式锁时,当一个事务锁住商品,导致其他的购买请求不能正常进行时也需要重试。
  • 相关阅读:
    华为机试真题 C++ 实现【连接器问题】【2022.11 Q4新题】
    基于大数据的学习资源推送系统
    ESP8266-Arduino编程实例-VEML6040颜色传感器驱动
    GC过程初步
    2023MathorCup(妈妈杯) 数学建模挑战赛 解题思路
    SAP ABAP根据网址跳转至对应的网页
    ROS(0)命令及学习资源汇总
    任务系统之Jenkins子任务
    MySQL MVCC 多版本并发控制机制 工作原理
    EIGRP_协议知识点
  • 原文地址:https://blog.csdn.net/syc000666/article/details/127682263