分布式系统内集成雪花算法的实践 您所在的位置:网站首页 雪花算法和guid 分布式系统内集成雪花算法的实践

分布式系统内集成雪花算法的实践

2023-02-25 23:16| 来源: 网络整理| 查看: 265

分布式系统内集成雪花算法的实践

文章目录 前言一、什么是雪花算法?二、实现1.思路2.使用集成MybatisPlus的雪花算法实现 总结

前言

之前业务系统一致使用UUID来作为生成唯一标识,由于是分布式业务并且是多机器多节点,所以可能会存在重复情况,之前的业务也只是用捕获入库失败异常来for循环三次去实现减少失败情况,但是小概率还是会存在失败,尽管非常小概率…所以对代码进行优化,使用雪花算法进行修改。

如下开始雪花算法的实现

一、什么是雪花算法?

雪花算法是64位的二进制组成,展示如下: 在这里插入图片描述 具体算法实现可以百度,不讲算法。我们能自定义的就只剩下机器id和服务id号。

二、实现 1.思路

一般在分布式环境下,以应用名+机器号存入redis,服务初始化时,参照Redission实现分布式锁一样,开一个线程做完看门狗来续期,用lua脚本获取一个唯一且有效的序列号,设置过期时间为30秒 获取序列化之后,开启一个守护线程,每20秒延长过期时间为30秒,机器id就一直占用,服务关闭,这个Id会自动释放

import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * @Classname SnowFlakeIDWorker * @Description 分布式雪花算法workerId维护 * @Version 1.0.0 * @Date 2023/2/17 10:47 * @Created by WFX1024 */ @Slf4j @Component public class SnowFlakeIDWorker { /** * key标识 */ private final String idWorker = "SnowFlakeWorkerId"; /** * lua 脚本 */ private final String script = "redis.replicate_commands();local now = redis.call('TIME')[1]\n" + "local idWordsKey = KEYS[1]\n" + "local serviceName = KEYS[2]\n" + "local sp = ':'\n" + "for i = 0, 100 do\n" + " local serviceKey = idWordsKey..sp..serviceName..sp..i\n" + " if redis.call('SETNX', serviceKey, now) == 1 then\n" + " redis.call('Expire', serviceKey, 30)\n" + " return i;\n" + " end\n" + "end\n" + "return -1"; @Resource private RedisTemplate redisTemplate; /** * 获取机器标识号 * @param serviceName 服务名称 */ public Long getWorkerIdNum(String serviceName) { // 实例化脚本对象 DefaultRedisScript lua = new DefaultRedisScript(); lua.setResultType(Long.class); lua.setScriptText(script); List keys = Lists.newArrayList(idWorker, serviceName); // 获取序列号 Long num = (Long)redisTemplate.execute(lua, keys, keys.size()); String key = String.join(":", keys) + ":" + num; // -1 代表workerId用完了 if (num ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("id_auto_expire-%d").daemon(true).build()); executorService.scheduleAtFixedRate(() -> { redisTemplate.expire(key, 30, TimeUnit.SECONDS); log.info("SnowFlakeIDWorker-自动续期id成功:{}", key); }, 0, 20, TimeUnit.SECONDS); } } 2.使用集成MybatisPlus的雪花算法实现

代码如下(示例):

/** * @Classname MybatisPlusConfig * @Description mybatisplus配置 * @Version 1.0.0 * @Date 2023/2/17 10:47 * @Created by WFX1024 */ @EnableTransactionManagement @Configuration @MapperScan(basePackages = { "com.*.*.mapper"}) public class MybatisPlusConfig { /** * 分页插件,自动识别数据库类型 多租户,请参考官网【插件扩展】 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } @Autowired private SnowFlakeIDWorker snowFlakeIDWorker; /** * 初始化雪花ID */ @PostConstruct public void initMybatisPlus(){ long num = snowFlakeIDWorker.getWorkerIdNum("activity"); // 获取前5位 long workerId = num >> 5; // 获取后5位 long dataCenterId = num & (~(-1L


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有