java 分布式id

分布式id总体思想:全局唯一 + 局部唯一

 1 基于UUID

  UUID的核心思想是使用「机器的网卡、当地时间、一个随机数」来生成UUID

  UUID.randomUUID().toString()就可以生成

2 基于DB数据库多种模式

数据库自增ID

  指定主键auto_increment(自增)

数据库水平拆分,设置初始值和相同的自增步长

  数据库自增ID出现的问题:ID重复、性能不好

  数据库水平拆分,设置初始值和相同的自增步长 和 批量申请自增ID

  

 批量申请自增ID

  一次性给对应的数据库上分配一批的id值进行消费,使用完了,再回来申请

  

 3 基于Redis

  Redis本身有incr和increby 这样自增的命令,保证原子性,生成的ID也是有序的

  使用Redis的方式还要考虑持久化,Redis的持久化有两种「RDB和AOF」「RDB是以快照的形式进行持久化,会丢失上一次快照至此时间的数据」

  第一种是使用RedisAtomicLong 原子类使用CAS操作来生成ID

@Service
public class RedisSequenceFactory {
    @Autowired
    RedisTemplate<String, String> redisTemplate;

    public void setSeq(String key, int value, Date expireTime) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        counter.set(value);
        counter.expireAt(expireTime);
    }

    public void setSeq(String key, int value, long timeout, TimeUnit unit) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        counter.set(value);
        counter.expire(timeout, unit);
    }

    public long generate(String key) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        return counter.incrementAndGet();
    }

    public long incr(String key, Date expireTime) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        counter.expireAt(expireTime);
        return counter.incrementAndGet();
    }

    public long incr(String key, int increment) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        return counter.addAndGet(increment);
    }

    public long incr(String key, int increment, Date expireTime) {
        RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        counter.expireAt(expireTime);
        return counter.addAndGet(increment);
    }
}

  第二种是使用redisTemplate.opsForHash()和结合UUID的方式来生成生成ID

public Long getSeq(String key,String hashKey,Long delta) throws BusinessException{
        try {
            if (null == delta) {
                delta=1L;
            }
            return redisTemplate.opsForHash().increment(key, hashKey, delta);
        } catch (Exception e) {  // 若是redis宕机就采用uuid的方式
            int first = new Random(10).nextInt(8) + 1;
            int randNo=UUID.randomUUID().toString().hashCode();
            if (randNo < 0) {
                randNo=-randNo;
            }
            return Long.valueOf(first + String.format("%16d", randNo));
        }
    }

 

5 基于雪花算法

  采用64bit作为id生成类型,并且将64bit划分为,如下图的几段

  

Leaf和UidGenerator

  美团Leaf算法需要依赖于数据库,ZK,并且也能保证去全局ID的唯一性,单项递增
  百度UidGenerator算法是基于雪花算法进行实现的,也是需要借助于数据库,与雪花算法不同的是,「UidGenerator支持自定义时间戳、主句中心ID和机器ID、序列号的位数」

参考:https://zhuanlan.zhihu.com/p/157978714 作者:Java程序员danni

不积跬步,无以至千里;不积小流,无以成江海
原文地址:https://www.cnblogs.com/hzzjj/p/15741213.html