SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的实现
作者:a_a\\\\\\ 发布时间:2022-03-27 10:47:08
标签:SpringBoot,分布式Id自增
场景
yitter-idgenerator 是基于雪花算法进行改造的分布式ID自增算法,集成时需要为每个服务设置唯一的机器号,才能保证生成的Id不会重复
实现方案
基于服务启动时指定唯一机器号
在程序服务启动时通过分布式锁 Redisson(基于Redis实现),对每台机器通过IP 对应一个 唯一的机器号(自增)映射,并保存在Redis中。缓存一次后,下次启动直接读取缓存即可
基于注册中心指定唯一机器号
从注册中心读取服务,增加多一个机器号服务来统一分配
基于第一种实现方案
Maven依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.10.6</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.7.19</version>
</dependency>
<dependency>
<groupId>com.github.yitter</groupId>
<artifactId>yitter-idgenerator</artifactId>
<version>1.0.6</version>
</dependency>
关键部分代码
/**
* Redisson分布式锁工具类
*/
@Component
public class RedissonUtil {
@Autowired
private RedissonClient redissonClient;
/**
* 加锁
* @param lockKey
* @return
*/
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
/**
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位:秒
*/
public RLock lock(String lockKey, long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
public RLock lock(String lockKey, TimeUnit unit ,long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 尝试获取锁
* @param lockKey
* @param waitTime 最多等待时间
* @param unit TimeUnit时间单位
* @return
*/
public boolean tryLock(String lockKey,long waitTime, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, unit);
} catch (InterruptedException e) {
return false;
}
}
/**
* 尝试获取锁
* @param lockKey
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
/**
* 尝试获取锁
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
/**
* 释放锁
* @param lockKey
*/
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/**
* 若没用锁情况下,就不调用释放锁的代码,若有锁情况下才调用释放锁
* @param lockKey
*/
public void unlockIgnore(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
if ( !lock.isLocked() ) {
return ;
}
lock.unlock();
}
/**
* 释放锁
* @param lock
*/
public void unlock(RLock lock) {
lock.unlock();
}
}
启动配置代码如下
@Slf4j
@Component
@Order(0)
public class SystemInitConfig implements CommandLineRunner {
@Autowired
private RedissonUtil redissonUtil;
@Autowired
private RedisTemplate redisTemplate;
/**
* 分布式锁Key
*/
private static final String CACHE_ID_GENERATOR = "LOCK_ID_GENERATOR";
/**
* 最大机器号Key
*/
private static final String CACHE_WORKERID_MAXID= "CACHE_WORKERID_MAXID";
/**
* 已分配的机器号Key
*/
private static final String CACHE_ID_IP = "CACHE_ID_IP";
@Override
public void run(String... args) throws Exception {
//获取mac地址
String macAddress = NetUtil.getLocalhost().getHostAddress();
log.info("{} 配置分布式Id Work缓存========开始",macAddress);
boolean existWorkerId = redisTemplate.opsForHash().hasKey(CACHE_ID_IP, macAddress);
//若已缓存在缓存中,直接跳过不设置
if (existWorkerId) {
log.info("{} 已配置分布式Id Work...",macAddress);
return ;
}
try {
//分布式锁等待120秒,执行时长最大120秒
boolean locked = redissonUtil.tryLock(CACHE_ID_GENERATOR, 120, 120);
if (!locked) {
throw new RuntimeException(macAddress+"设置分布式Id机器号失败");
}
ValueOperations <String,Integer> stringOperation = redisTemplate.opsForValue();
boolean initWorkerId = stringOperation.setIfAbsent(CACHE_WORKERID_MAXID, 1);
if( !initWorkerId ) {
//若已存在key,对最大的机器号自增1
stringOperation.increment(CACHE_WORKERID_MAXID);
}
Integer workerId = stringOperation.get(CACHE_WORKERID_MAXID);
IdGeneratorOptions options = new IdGeneratorOptions( workerId.shortValue());
YitIdHelper.setIdGenerator(options);
//设置mac地址 - workerid 到hash结构
redisTemplate.opsForHash().put(CACHE_ID_IP,macAddress,workerId);
log.info("已配置分布式Id Work,{} - {}",macAddress,workerId);
} finally {
redissonUtil.unlock(CACHE_ID_GENERATOR);
log.info("{} 配置分布式Id Work缓存========结束",macAddress);
}
}
}
直接在代码使用即可
YitIdHelper.nextId()
来源:https://blog.csdn.net/jie873440996/article/details/122459656
0
投稿
猜你喜欢
- 1. 准备工作需要提前安装好Elasticsearch,访问地址:http://127.0.0.1:9200/ 得到以下结果,得到clust
- 提几个问题,从问题中去了解去学习:他们之间有啥区别?如果我使用notify(),将通知哪个线程?我怎么知道有多少线程在等待,所以我可以使用n
- 使用spring框架实现数据库事务处理事务对于数据库来说是,是对sql语句的一系列操作,这些操作被组织成为一个事务。事务具有原子性的,要么全
- 一.以springboot为例,建立代码1.IExecCommandServer:public interface IExecCommand
- 什么是事务处理事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性 ( Consistency
- java简单模拟微信抢红包功能,本例发100元红包,有10个人抢,为了尽可能的公平,每个人的红包金额都要随机(保证结果的不确定性,本例抢红包
- 在工作中要求将图片上传至本地,如下代码将介绍如何将图片上传至本地准备工作:环境:eclipse4.5-x64,jdk1.7-x64,mave
- 没有结果时,去.First()时,会报错,所以一定要先.Count()判断一下而用FirstOrDefault(),如果集合中没有数据,则返
- 在开发 Web 项目的时候,经常需要过滤器来处理一些请求,包括字符集转换什么的,记录请求日志什么的等等。在之前的 Web 开发中,我们习惯把
- MyEclipse配置IDEA配置Tomcat环境IDEA:2020.2Tomcat:apache-tomcat-9.0.38创建Web项目
- 规则1(无继承情况下):对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、
- 1 修饰属性或者变量无论属性是基本类型还是引用类型,作用都是变量里面存放的“值”不可变经常和static关键字一起使用,作为常量1 基本类型
- 目录前言connectTimeout:callTimeout:pingIntervalwriteTimeoutreadTimeout总结前言
- java 实现随机数组输出及求和问题描述:随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息
- 第一步:后端简单建个SpringBoot项目,提供一个 helloWorld接口;版本选用 2.2.6.RELEASEpackage com
- 背景介绍你刚从学校毕业后,到新公司实习,试用期又被毕业,然后你又不得不出来面试,好在面试的时候碰到个美女面试官!面试官: 小伙子,
- java实现在线预览- -之poi实现word、excel、ppt转html,具体内容如下所示:###简介java实现在线预览功能是一个大家
- 概述在以下示例中,将介绍在PDF文档页面设置页面切换按钮的方法。示例中将页面切换按钮的添加分为了两种情况,一种是设置按钮跳转到首页、下页、上
- 项目场景:适用于接口数据敏感信息,比如 明文传输姓名、居住地址、手机号等信息,如果存在明文传输敏感数据问题、及数据泄漏风险,则可使用此方法加
- c#中Math类的方法Math.Abs 已重载。 返回指定数字的绝对值。Math.Acos 返回余弦值为指定数字的角度。Math.Asin