一、利用nacos等注册中心,实例启动的时把自身workerid注册到nacos等
二、利用redis,把workerid注册到redis中
三、利用ip转long取模(该方法存在取值后重复的问题,暂不在此处讨论)
方案一实现:
/** * @author cboy * @date 2022/02/28 16:50:48 */ @Configuration @Slf4j public class IdWorkerConfig { @Value("${spring.application.name}") private String serviceName; @Value("${spring.cloud.nacos.discovery.group:DEFAULT_GROUP}") private String groupName; @Resource private NacosServiceManager nacosServiceManager; @Resource private NacosDiscoveryProperties nacosDiscoveryProperties; public byte workerIdBitLength = 6; public static final String WORKER_ID = "worker_id"; /** * 注册服务的时候同时注册worker_id */ @PostConstruct public void setWorkerId() { Map<String, String> metadata = nacosDiscoveryProperties.getMetadata(); int workerId = getWorkerId(); metadata.put(IdWorkerConfig.WORKER_ID, String.valueOf(workerId)); nacosDiscoveryProperties.setMetadata(metadata); log.info("注册workerId[" + workerId + "]到Nacos"); //设置分布式id生成方式 IdGeneratorOptions options = new IdGeneratorOptions((short) workerId); IdHelper.setIdGenerator(options); } /** * 获取所有实例 * * @return */ private List<Instance> getAllInstances() { try { NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties()); return namingService.getAllInstances(serviceName, groupName); } catch (NacosException e) { log.error("获取Nacos实例出错:{}", e); throw new RuntimeException(e); } } /** * 获取已使用的所有workerId * * @return */ private List<String> getAllUsedWorkerId() { List<Instance> allInstances = getAllInstances(); List<String> workerIds = new ArrayList<>(); for (Instance instance : allInstances) { String workerId = instance.getMetadata().get(WORKER_ID); if (workerId != null) { workerIds.add(workerId); } } return workerIds; } /** * 获取可用的的workerId * * @return */ public int getWorkerId() { int maxWorkerId = (1 << workerIdBitLength) - 1; List<String> allUsedWorkerId = getAllUsedWorkerId(); log.info("workerId:{},{}个已被注册使用,可注册workerId为0-{}", allUsedWorkerId, allUsedWorkerId.size(), maxWorkerId); if (allUsedWorkerId.isEmpty()) { return 0; } for (int i = 0; i <= maxWorkerId; i++) { if (!allUsedWorkerId.contains(String.valueOf(i))) { return i; } } throw new RuntimeException("worker_id已用完请重新分配!"); } } 方案二实现:
该图来自网络,拿来直接用了