首页>国内 > 正文

简单实用!利用Redis轻松实现高并发全局ID生成器

2022-12-29 09:02:28来源:今日头条


【资料图】

Redis作为高性能的KV数据库,并且操作还是原子性的,所以用来做支持高并发的发号器十分合适。

本文给大家介绍3种常见的全局ID生成方式。

1、全局递增ID

目标:一直递增的全局ID。

/** * 一直递增的全局id * * @param redisTemplate redis客户端对象 * @param busId         业务id,可以按需配置 * @param step          步长,即每次递增的间隔 */public static String getNo(RedisTemplate redisTemplate, String busId, int step) {  //保存redis中的key,注意不要重复  String redisKey = "uniqueNo_";  //利用increment即redis原生incrBy命令的原子性特性生成递增的序列号  Long increment = redisTemplate.opsForValue().increment(redisKey, step);  if (increment == null) {    throw new RuntimeException("redis命令执行失败");  }  //业务id+递增id,如果需要纯数字,去掉业务id即可  return busId + increment;}
2、以天为分割的全局ID

目标:生成格式为 yyyyMMdd + 递增序列号的全局ID。

/** * 以天为间隔的递增序列号 * @param redisTemplate redis客户端对象 * @param busId 业务id,可以按需配置 * @param step 步长,即每次递增的间隔*/public static String getNo(RedisTemplate redisTemplate, String busId, int step) {  //当天日期,比如20221226  String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));  //保存redis中的key,注意不要重复  String redisKey = "uniqueNo_" + date;  //利用increment即redis原生incrBy命令的原子性特性生成递增的序列号  Long increment = redisTemplate.opsForValue().increment(redisKey, step);  if (increment == null) {    throw new RuntimeException("redis命令执行失败");  }  if (step == increment.intValue()) {    //首次执行时,给redisKey设置ttl,第二天这个key就可以被redis自动删除    redisTemplate.expire(redisKey, 25, TimeUnit.HOURS);  }  //组合  20221226 + 业务id + 0001(可以根据需要自由调整序列号的长度)  return date + busId + String.format("%04d", increment);}
3、批量获取ID

有时我们需要批量的获取递增ID,比如给一批订单号设置ID。

/** * 批量获取id * * @param redisTemplate redis客户端对象 * @param busId         业务id,可以按需配置 * @param size          获取的id个数,与步长类似 */public static List getNoByGroup(RedisTemplate redisTemplate, String busId, int size) {  //保存redis中的key,注意不要重复  String redisKey = "uniqueNo_group";  //设置步长为size,相当于一次性申请size个id  Long increment = redisTemplate.opsForValue().increment(redisKey, size);  if (increment == null) {    throw new RuntimeException("redis命令执行失败");  }  long begin = increment - Long.parseLong(size + "");  List rs = new ArrayList<>();  for (long i = begin + 1; i <= increment; i++) {    rs.add(busId + i);  }  return rs;}
总结

无论我们需要什么格式的ID,其实只要我们把握住其中的核心:incrBy命令,根据其原子性的特性,就可以生成我们需要的全局ID。

但是需要注意的是,虽然incrBy命令是原子性的,但是通过组合键进行组合时,其实是破坏了这种原子性。如果有特殊的ID格式要求,务必要进行充分的测试。

关键词: 我们需要 给大家介绍 生成方式 高性能的 轻松实现

相关新闻

Copyright 2015-2020   三好网  版权所有 联系邮箱:435 22 640@qq.com  备案号: 京ICP备2022022245号-21