我相信你会经常遇到要生成唯一 ID 的场景,比如标识每次请求、生成一个订单编号、创建用户需要创建一个用户 ID。
UUID 确实是个好东西,生成的 ID 全球唯一,但是有两个致命缺陷。
别急,今天我就给大家带来一个神器级的解决方案——Redis 分布式 ID 生成器!配合 SpringBoot3.0,让你的 ID 生成变得既简单又高效。
分布式 ID 要满足什么要求
分布式 ID 生成器需要满足以下特性。
Redis 集群能保证高可用和高性能,为了节省内存,ID 可以使用数字的形式,并且通过递增的方式来创建新的 ID。
防止重启数据丢失,你还需要把 Redis AOF 持久化开启。
好主意,在生成 ID 之后发送一条消息到 MQ 消息队列中,把值持久化到 MySQL 中。
我们可以使用 Redis String 数据类型来实现,key 用于区分不同业务场景的 ID 生成器,value 存储 ID。
String 数据类型提供了INCR指令,它能把 key 中存储的数字加 1 并返回客户端。如果 key 不存在,那么 key 的 value 先被初始化成 0,再执行加 1 操作并返回给客户端。
Redis,作为一个高性能的内存数据库,天生就适合处理高并发的场景。它的“单线程”模型更是让它在处理 ID 生成时如鱼得水。
Redis 的操作是原子性的,这就意味着在整个过程中,不会有任何的并发问题出现,从而确保了 ID 的唯一性。
设计思路如下图所示。
图 2-4
接下来,我们结合 SpringBoot3.0 来打造一个强大且易用的 Redis 分布式 ID 生成器。
首先,我们需要在 SpringBoot 项目中引入 redis 的依赖。在pom.xml文件中添上这行代码:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
搞定依赖后,我们得告诉 SpringBoot 怎么连接到 Redis。打开application.yml文件,填上 Redis 的服务地址和端口:
spring:application:name: redisredis:host: 127.0.0.1port: 6379password: magebytetimeout: 6000
万事俱备,只欠东风!接下来,我们编写一个 ID 生成器工具类。这个工具类负责与 Redis 交互,生成唯一的 ID。这里我们使用 Redis 的INCR命令,它能让 ID 自增,确保每次获取的 ID 都是唯一的。
@Componentpublic class OrderIdGenerator implements InitializingBean {private final StringRedisTemplate redisTemplate;/*** 操作数据库 dao*/private final IdGeneratorMapper idGeneratorMapper;private static final String KEY = "counter:order";/*** 数据库中的 ID 值*/private String dbId;@Autowiredpublic OrderIdGenerator(StringRedisTemplate redisTemplate, IdGeneratorMapper idGeneratorMapper) {this.redisTemplate = redisTemplate;this.idGeneratorMapper = idGeneratorMapper;}public Long generateId(String key) {return redisTemplate.opsForValue().increment(key, 1);}@Overridepublic void afterPropertiesSet() throws Exception {// 从数据库查询最大 IDthis.dbId = idGeneratorMapper.getMaxID(KEY);Boolean hasKey = redisTemplate.hasKey(KEY);if (Boolean.TRUE.equals(hasKey)) {// key 存在,比较 dbId 与 redisValue,取出最大值String redisValue = redisTemplate.opsForValue().get(KEY);String targetValue = max(this.dbId, redisValue);} else {
public String generateCustomId(String key, String prefix, String datePattern) {long sequence = redisTemplate.opsForValue().increment(key, 1);return String.format("%s-%s-%04d", prefix, new SimpleDateFormat(datePattern).format(new Date()), sequence);}
那具体怎么用呢?让我们在业务代码中一探究竟!想象一下,在一个电商系统中,当一个新的订单如流星般划过天际,我们迫不及待地想要一个独一无二的 ID 来标记它时——很简单,只需调用我们的
generateCustomId
方法,传入订单相关的参数即可。
@Servicepublic class OrderService {private final RedisIdGenerator idGenerator;@Autowiredpublic OrderService(RedisIdGenerator idGenerator) {this.idGenerator = idativeIdGenerator;}public Order createOrder(OrderRequest request) {String orderId = idGenerator.generateCustomId("order:id", "ORD", "yyyyMMdd");Order order = new Order();order.setId(orderId);// 其他业务逻辑...return order;}}
本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载者并注明出处:https://jmbhsh.com/shenghuozixun/34394.html