弹性伸缩设计 Java+MySQL实现支持横向扩展的分布式ID生成服务

分布式ID生成服务设计

分布式ID生成服务需要满足高可用、高性能、全局唯一、趋势递增等特性。以下是基于Java和MySQL的实现方案,支持横向扩展。

数据库设计

使用MySQL的InnoDB表存储ID段分配信息,避免单点故障。表结构如下:

CREATE TABLE `id_generator` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `biz_tag` varchar(64) NOT NULL COMMENT '业务标识',
  `max_id` bigint(20) NOT NULL COMMENT '当前最大ID',
  `step` int(11) NOT NULL COMMENT '号段步长',
  `version` bigint(20) NOT NULL COMMENT '乐观锁版本号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_biz_tag` (`biz_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

号段模式实现

采用号段分配方式降低数据库压力。每个业务标识获取一个ID段,缓存到本地内存中。

public class SegmentIdGenerator {
    private volatile Segment currentSegment;
    private volatile Segment nextSegment;
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    
    public synchronized Long getNextId(String bizTag) {
        if (currentSegment == null || !currentSegment.hasRemaining()) {
            if (nextSegment != null && nextSegment.hasRemaining()) {
                currentSegment = nextSegment;
                nextSegment = null;
            } else {
                currentSegment = loadSegmentFromDb(bizTag);
            }
            preloadNextSegment(bizTag);
        }
        return currentSegment.getNextId();
    }
    
    private void preloadNextSegment(String bizTag) {
        executor.execute(() -> {
            if (nextSegment == null || !nextSegment.hasRemaining()) {
                nextSegment = loadSegmentFromDb(bizTag);
            }
        });
    }
    
    private Segment loadSegmentFromDb(String bizTag) {
        // 数据库操作获取新号段
    }
}

数据库更新策略

使用乐观锁保证并发安全,避免ID重复:

public boolean updateMaxId(String bizTag, long newMaxId, long oldVersion) {
    String sql = "UPDATE id_generator SET max_id=max_id+step, version=version+1 " 
               + "WHERE biz_tag=? AND version=?";
    try (Connection conn = dataSource.getConnection();
         PreparedStatement stmt = conn.prepareStatement(sql)) {
        stmt.setString(1, bizTag);
        stmt.setLong(2, oldVersion);
        return stmt.executeUpdate() > 0;
    }
}

服务层设计

构建Spring Boot服务提供RESTful API:

@RestController
@RequestMapping("/api/id")
public class IdController {
    
    @GetMapping("/next")
    public Response<Long> nextId(@RequestParam String bizTag) {
        Long id = idGenerator.getNextId(bizTag);
        return Response.success(id);
    }
}

横向扩展方案

采用多实例部署时,可通过以下方式保证扩展性:

每个实例初始化时注册到Zookeeper或Redis,获取唯一实例标识 将实例标识作为ID高位部分,结合数据库生成的ID低位部分 例如:64位ID = 16位实例标识 + 48位数据库生成ID

public class DistributedIdGenerator {
    private final int instanceIdBits = 16;
    private final long instanceId;
    
    public DistributedIdGenerator() {
        this.instanceId = registerInstanceAndGetId();
    }
    
    public long generateId() {
        long sequenceId = segmentIdGenerator.getNextId();
        return (instanceId << (64 - instanceIdBits)) | sequenceId;
    }
}

性能优化措施

适当增大号段步长,减少数据库访问频率 使用双缓冲机制预加载下一个号段 添加本地缓存应对突发流量 监控号段消耗速度,动态调整步长

public class DynamicStepAdjuster {
    public int calculateNewStep(int currentStep, long usedTime) {
        // 根据历史消耗时间动态计算新步长
        return Math.min(currentStep * 2, MAX_STEP);
    }
}

容灾方案

数据库主从部署,故障时自动切换 添加本地文件备份,数据库不可用时降级处理 定期检查ID使用情况,避免号段浪费 实现监控报警机制,及时发现异常

监控指标

实现以下监控项保证服务健康: ID生成速率 号段消耗时间 数据库更新成功率 服务响应时间 实例负载情况

这种设计结合了数据库的可靠性和内存的高性能,通过号段分配和实例标识支持横向扩展,适合中等规模分布式系统。对于超大规模系统,可考虑雪花算法等完全分布式方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值