• 使用REDIS的INCREMENT方法生成自增主键,并发量每秒一万


    redis是单线程的,他提供了一个单线程的自增方法increment供我们使用。

    现在有一个业务需求,id需要自增生成,且生成速度要求一秒一千以上。废话不多说,直接上代码

    public class IncrIdUtils {
    
        private final String REDIS_KEY_TASK_ID = "AUTO_TASK_ID";
    
        private final String REDIS_KEY_PRO_INS_ID = "AUTO_PRO_INS_ID";
    
        @Resource
        private RedisUtils redisUtils;
    
    
        @Value("${task.id.last}")
        private Long taskIdLast = 900000000000L;
    
        @Value("${pro.ins.id.last}")
        private Long proInsIdLast = 900000000000L;
    
        /**
         * 生成一个长度为12的纯数字字符串作为任务id,规则如下
         * 1.以9开头
         * 2.后11位数字从1开始自增
         *
         * @return 如:"900000000001"
         */
        public String getTaskId() {
            String taskIdRedis;
            long incr = redisUtils.incr(REDIS_KEY_TASK_ID, 1);
            taskIdRedis = String.valueOf(incr + taskIdLast);
            return taskIdRedis;
        }
    
    }
    
    下面是测试代码
    
    
    @Resource
    IncrIdUtils incrIdUtils;
     
    
    public Response testTaskIdCreate(@ApiParam(name = "num", value = "生成数量", required = true) @RequestParam("num") Integer num) throws InterruptedException {
        long start = System.currentTimeMillis();
    
        Map dataMap = new ConcurrentHashMap<>();
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        for (int i = 0; i < num; i++) {
            executorService.submit(() -> {
                String taskId = "";
                taskId = incrIdUtils.getTaskId();
                System.out.println(taskId);
                dataMap.put(taskId, 1);
            });
        }
        executorService.shutdown();
        while (true) {
            if (executorService.isTerminated()) {
                Map resultMap = new HashMap<>();
                resultMap.put("map", dataMap.size());
                resultMap.put("time", (int) (System.currentTimeMillis() - start));
                return Response.success(resultMap);
            }
        }
    }
    运行代码测试,并发量可以达到每秒一万以上,并且生成的id不会重复,搞定
    
    
    
    开发过程中遇到的坑:注意在测试的时候一定不能用hashmap,hashmap是线程不安全的,因为一开始用了hashmap,老师出现数量对不上的情况,换了concurrenthashmap马上好了
    
    用过的其他方法:
    在代码中进行自增运算,然后写入的时候用cas算法校验。
      这种方法效率低,增加了redis的读写次数,并且单纯的cas算法并没有保证线程安全,还容易导致内存溢出。再加上synchronized代码锁之后,效率更低,每秒只能生成150个左右。
    换成lock锁之后效率更低,只有每秒100个左右。频繁的加锁释放锁也是很浪费时间
  • 相关阅读:
    spark sql(四)物理计划解析
    Java 截取字符串的几种操作,你必须要知道哦
    C++ 算法教程
    UE4自动打包工具编写
    Apache DolphinScheduler 4月简报:社区发展与技术革新速递
    html实训大作业《基于HTML+CSS+JavaScript红色文化传媒网站(20页)》
    [HDLBits] Edgecapture
    hadoop大数据原理与应用-----初识hadoop习题集
    易点易动固定资产管理系统:RFID出入监控,保障固定资产安全
    vue3怎么创建项目
  • 原文地址:https://blog.csdn.net/zccmp20/article/details/127612020