ID生成方案

1. 无序型id

1. 优点

无序,无规律,不容易被遍历

2. 缺点

无顺序,没有实际意义,不容易记忆

3. 方案

1. UUID

2. 根据自己的规则生成例如数字+字母的唯一id

2. 自增型id

1. 优点

  • InnoDB 使用两种索引来组织数据,Clustered Index 和 Second Index  Clustered Index  与 主键有千丝万缕的关系,可以简单认为是相等关系,数据存储会按照主键来进行排序。如果在建表的时候不提供主键,InnoDB  会自动生成一个主键,这个主键是字符式的,所以当有新数据进来的时候,原先的排序会被打乱,中间的开销会很高。简单说就是那棵树的左旋右旋,很麻烦。使用自增 ID 充当主键,就可以解决这个问题了,相应的 Second Index  的查询效率也会变高。
  • 而且自增型id可以根据id快捷的判断数据产生的先后顺序

2. 缺点

  • 自增型id容易被人用程序遍历,如果拿到一个id,根据递增规律就可以遍历到所有数据,不安全

3. 实现方案

1. 数据库自增id

比如mysql的AUTO_INCREMENT

2. 根据自身的业务规则

比如年月日,时分秒,加上几位数字递增,这适合每天数据量小的场景。可以直接记录数据的日期

或者时间毫秒加上递增数字


3. 推特的分布式id生成方案

twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局唯一ID生成服务:Snowflake。
  • 41位的时间序列(精确到毫秒,41位的长度可以使用69年)
  • 10位的机器标识(10位的长度最多支持部署1024个节点) 
  • 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) 最高位是符号位,始终为0。
优点:高性能,低延迟;独立的应用;按时间有序。 缺点:需要独立的开发和部署。
public class IdWorker {

	private final long workerId;
	private final static long twepoch = 1288834974657L;
	private long sequence = 0L;
	private final static long workerIdBits = 4L;
	public final static long maxWorkerId = -1L ^ -1L << workerIdBits;
	private final static long sequenceBits = 10L;
	private final static long workerIdShift = sequenceBits;
	private final static long timestampLeftShift = sequenceBits + workerIdBits;
	public final static long sequenceMask = -1L ^ -1L << sequenceBits;
	private long lastTimestamp = -1L;

	public IdWorker(final long workerId) {
		super();
		if (workerId > this.maxWorkerId || workerId < 0) {
			throw new IllegalArgumentException(
					String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
		}
		this.workerId = workerId;
	}

	public synchronized long nextId() {
		long timestamp = this.timeGen();
		if (this.lastTimestamp == timestamp) {
			this.sequence = (this.sequence + 1) & this.sequenceMask;
			if (this.sequence == 0) {
				System.out.println("###########" + sequenceMask);
				timestamp = this.tilNextMillis(this.lastTimestamp);
			}
		} else {
			this.sequence = 0;
		}
		if (timestamp < this.lastTimestamp) {
			try {
				throw new Exception(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
						this.lastTimestamp - timestamp));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		this.lastTimestamp = timestamp;
		long nextId = ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << this.workerIdShift)
				| (this.sequence);
		System.out.println("timestamp:" + timestamp + ",timestampLeftShift:" + timestampLeftShift + ",nextId:" + nextId
				+ ",workerId:" + workerId + ",sequence:" + sequence);
		return nextId;
	}

	private long tilNextMillis(final long lastTimestamp) {
		long timestamp = this.timeGen();
		while (timestamp <= lastTimestamp) {
			timestamp = this.timeGen();
		}
		return timestamp;
	}

	private long timeGen() {
		return System.currentTimeMillis();
	}

	public static void main(String[] args) {
		IdWorker worker2 = new IdWorker(2);
		System.out.println(worker2.nextId());
	}

}

你可能感兴趣的:(微服务与架构)