今天遇到需求要统计每次执行成功的个数和失败的个数,但是项目部署的是多实例的而且每个实例还是多线程的。
只使用多线程的计数器,没有很好的方法去实现多实例的数据汇总,想到使用redis或者mysql,由于是多线程的对统计字段变化频繁所以果断放弃mysql选择redis,
之前使用mysql遇到过多线程情况下数据出现ABA问题,所以在选择redis的时候不能只是单纯的更新数据,还要考虑多线程情况下数据的同步问题。

同时参考了:https://my.oschina.net/sxwailyc/blog/1973427

在此处记录一下,以后自己使用同时方便他人查看

public class CounterUtil {
    static {
        redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
    }

    private static RedisTemplate redisTemplate;

   public static void counter(String key){

       List<Object> result =null;

       do{
           redisTemplate.setEnableTransactionSupport(true);//不可少
           int count = 0;
           redisTemplate.watch(key); //watch某个key,当该key被其它客户端改变时,则会中断当前的操作

           String value = (String) redisTemplate.opsForValue().get(key);
           if (!StringUtils.isEmpty(value)) {
               count = Integer.parseInt(value);
           }
           count = count + 1;

           redisTemplate.multi(); //开始事务
           redisTemplate.opsForValue().set(key, String.valueOf(count));

           try{
               result = redisTemplate.exec();//执行事务
           }catch(Exception e){
               //如果key被改变,提交事务时这里会报异常
           }
       }while(result == null || result.size()<=0);

   }
}

测试方法:使用多线程调用工具类,同时在自己的redis中查看对应key值的变化是否达到预期(我这里实在springboot项目的junit测试,其他测试方法可自己重写)

@Test
void contextLoads() {
        Runnable runable = new Runnable() {
            @Override
            public void run() {
            	String key = "test:success:count";
                CounterUtil.counter(key);
            }
        };

        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(runable, "thread-" + (i + 1));
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐