zoukankan      html  css  js  c++  java
  • 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

    不积跬步,无以至千里;不积小流,无以成江海
  • 相关阅读:
    用图片来代替字符串
    下载网页时的 有gzip压缩的处理
    位置不固定验证码的识别
    CookieContainer 与 Session
    Thread Pool 备忘
    用 SGMLReader把子HTML 转 XML
    非asp.net控件实现回发 button
    ajax.net ??= 回车
    如何写需求分析
    jsp中地址
  • 原文地址:https://www.cnblogs.com/hzzjj/p/15741213.html
Copyright © 2011-2022 走看看