SpringBoot集成yitter-idgenerator(雪花漂移)分布式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() 

到此这篇关于SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的实现的文章就介绍到这了,更多相关SpringBoot 分布式Id自增内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot 使用Mongo的GridFs实现分布式文件存储操作

    目录 前言 GridFs介绍 什么时候使用GridFs GridFs的原理 环境 引入依赖和项目配置 使用GridFsTemplate操作GridFs 前言 这段时间在公司实习,安排给我一个任务,让在系统里实现一个知识库的模块,产品说,就像百度网盘那样...我tm-,这不就是应了那句话,"这个需求很简单,怎么实现我不管". 可是我google小能手怎么会认输呢,本来还说研究一下FastDFS啥的,但是因为我们项目用的Mongo作为数据库,了解到Mongo自带分布式文件系统GridFs,

  • 详解如何使用MongoDB+Springboot实现分布式ID的方法

    一.背景 如何实现分布式id,搜索相关的资料,一般会给出这几种方案: 使用数据库自增Id 使用reids的incr命令 使用UUID Twitter的snowflake算法 利用zookeeper生成唯一ID MongoDB的ObjectId 另外,在我通过爬取知乎用户id发现,知乎的用户id是32位的,初步断定知乎采用的是md5加密,然后全部转换成小写.至于如何爬取知乎用户信息,见我之前分享的文章.本文采取的技术方案采取的是mogoodb的objectId. 二.mongodb如何实现分布式I

  • SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的实现

    目录 场景 实现方案 基于第一种实现方案 关键部分代码 场景 yitter-idgenerator 是基于雪花算法进行改造的分布式ID自增算法,集成时需要为每个服务设置唯一的机器号,才能保证生成的Id不会重复 实现方案 基于服务启动时指定唯一机器号 在程序服务启动时通过分布式锁 Redisson(基于Redis实现),对每台机器通过IP 对应一个 唯一的机器号(自增)映射,并保存在Redis中.缓存一次后,下次启动直接读取缓存即可 基于注册中心指定唯一机器号 从注册中心读取服务,增加多一个机器号

  • SpringBoot集成redis与session实现分布式单点登录

    目录 单点登录 SSO(Single Sign On) 什么是单点登录? 实现方式 开发技术 单点登录实现流程 实现案例 看效果 前言: 由于考虑到cookie的安全性问题,就有了下面这个版本的sso 单点登录 SSO(Single Sign On) 什么是单点登录? 单点登录的英文名叫做:Single Sign On(简称SSO),指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的系统.简而言之,多个系统,统一登陆. 我们可以这样理解,在一个服务模块登录后,其他模块无

  • springboot集成redis并使用redis生成全局唯一索引ID

    部署redis Windows下搭建Reids本地集群,可参考https://www.jb51.net/article/242520.htm springboot集成 redis pom文件 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency&

  • SpringBoot集成Zipkin实现分布式全链路监控

    Zipkin 简介 Zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in service architectures. Features include both the collection and lookup of this data. If you have a trace ID in a log file, you ca

  • springboot 集成redission 以及分布式锁的使用详解

    目录 springboot集成redission及分布式锁的使用 1.引入jar包 2.增加Configuration类 3.使用redission分布式锁 Springboot整合Redisson 锁 一.依赖 二.配置文件 三.锁的使用 四.分布式秒杀 五.redis锁 单机版可用,分布式用Redisson springboot集成redission及分布式锁的使用 1.引入jar包 <dependency> <groupId>org.redisson</groupId&

  • SpringBoot集成Redisson实现分布式锁的方法示例

    上篇 <SpringBoot 集成 redis 分布式锁优化>对死锁的问题进行了优化,今天介绍的是 redis 官方推荐使用的 Redisson ,Redisson 架设在 redis 基础上的 Java 驻内存数据网格(In-Memory Data Grid),基于NIO的 Netty 框架上,利用了 redis 键值数据库.功能非常强大,解决了很多分布式架构中的问题. Github的wiki地址: https://github.com/redisson/redisson/wiki 官方文档

  • SpringBoot集成redis实现分布式锁的示例代码

    1.准备 使用redis实现分布式锁,需要用的setnx(),所以需要集成Jedis 需要引入jar,jar最好和redis的jar版本对应上,不然会出现版本冲突,使用的时候会报异常redis.clients.jedis.Jedis.set(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String; 我使用的redis版本是2.3.0,Jedis使用的是3.3.0 <de

  • Java 基于雪花算法生成分布式id

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯一的,同时我们基本上都会将它作为查询条件:出于系统安全考虑不应当让其它人轻易的就猜出我们的订单号,同时也要防止公司的竞争对手直接通过订单号猜测出公司业务体量:为了保证系统的快速响应那么生成算法不能太耗时.而雪花算法正好解决了这些问题. SnowFlake 算法(雪花算法), 是Twitter开源的分

  • SpringBoot 集成 ShedLock 分布式锁的示例详解

    目录 一:ShedLock 简介 二:配置maven 依赖 三:SchedulerLock 基于 Redis 的配置 四:在启动类中添加 @EnableScheduling 标签 五:test 测试案例 一:ShedLock 简介 ShedLock是一个在分布式环境中使用的定时任务框架,用于解决在分布式环境中的多个实例的相同定时任务在同一时间点重复执行的问题.ShedLock确保计划的任务最多同时执行一次.如果一个任务正在一个节点上执行,它会获得一个锁,该锁将阻止从另一个节点(或线程)执行同一任

随机推荐