分布式id生成

建表

CREATE TABLE `sequence_generator_table` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `stub` varchar(50) NOT NULL COMMENT '服务器ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_stub` (`stub`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

设置自增步长,按需设置,影响全库,目前好像没有实例或者是表级别

SET @@auto_increment_increment=10;
SHOW VARIABLES LIKE 'auto_inc%';

获取自增分布式主键

REPLACE INTO sequence_generator_table (stub) VALUES ("192.168.1.1");
SELECT id FROM sequence_generator_table WHERE stub = "192.168.1.1";

java代码


Map<String, Object> map = new HashMap<>();
map.put("stub", "192.168.1.1");
int row = storeFileMapper.getDistributedID(map);
System.out.println(row);
System.out.println(JSON.toJSONString(map));

Integer getDistributedID(Map<String, Object> map);

"getDistributedID" parameterType="java.util.Map" useGeneratedKeys="true">
REPLACE INTO sequence_generator_table (stub) VALUES (#{stub})
"java.lang.Integer" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID() as id

LAST_INSERT_ID是基于单个数据库连接的,它会返回的ID是当前连
接最后一次insert操作的ID,并不是整个数据库最后一次insert操作。

控制台打印

row = 2
map = {"stub":"192.168.1.1","id":14}

id值就是所需获取的自增id。

高并发获取

可以通过设置mysql步长,或者直接取id值乘以步长的方式,做大并发id获取,前者需要在单独的数据库中,否则步长设置会影响其他库表实例,推荐使用后者。

实现方式

        int id = Integer.valueOf(String.valueOf(map.getOrDefault("id", 0)));
        // 取范围
        int stepSize = 1000;
        AtomicLong atomicLong = new AtomicLong();
        atomicLong.set(id * stepSize);
        int currentMaxId = (id + 1) * stepSize;
        Long currentId = atomicLong.incrementAndGet();
        // 到达了最后一个号码,那么阻塞住其他请求线程,最早的那个线程去db取个号段,再更新一下号段的两个值,就可以了。

你可能感兴趣的:(Java)