精华内容
下载资源
问答
  • 分布式数据库唯一主键设计
  • Java生成唯一主键

    千次阅读 2019-05-10 09:39:43
    一般有时候我们需要生成唯一主键id,如果数据库是mysql我们可以使用主键自增,如果是oracle我们可以创建触发器或者序列,如果不借助数据库我们也可以在java层面自己生成唯一主键。 代码如下: /* 生成唯一主键 ...

    一般有时候我们需要生成唯一主键id,如果数据库是mysql我们可以使用主键自增,如果是oracle我们可以创建触发器或者序列,如果不借助数据库我们也可以在java层面自己生成唯一主键。

    1. 使用随机数:
    /*
        生成唯一主键
        格式:时间+随机数
         */
        public static synchronized String genUniqueKey() {
            Random random = new Random();
            Integer number = random.nextInt(900000) + 100000;
            return System.currentTimeMillis() + String.valueOf(number);
        }
    
    1. 使用UUID
    public static String getUUID(){
    
            UUID uuid=UUID.randomUUID();
            String uuidStr=uuid.toString();
            return uuidStr;
    }
    
    展开全文
  • Redis生成唯一主键

    2019-12-25 11:42:36
    title toc layout categories tags date Redis生成唯一主键 true blog blog Java Blog 2019-04-24 02:11:17 -0700 使用Redis生成自定义...
    title toc layout categories tags date
    Redis生成唯一主键
    true
    blog
    blog
    Java
    Blog
    2019-04-24 02:11:17 -0700

    使用Redis生成自定义前缀/日期格式自增的唯一主键,例如HTG201810120001201810120001等自增数。同时每天的零点重新开始生成个位为1的主键

    前提:

    • 需要连接到Redis

    工具类代码

    package com.sanss.city.util;
    
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.support.atomic.RedisAtomicLong;
    import org.springframework.stereotype.Service;
    
    /**
     * 
     * @ClassName: RedisGeneratorCode
     * @Description: 生成日期开头加0001,0002,0003的工具类
     * @author Dew
     * @date 2018/10/09
     * {@link https://www.cnblogs.com/jbml-154312/p/7490810.html}
     */
    @Service
    public class RedisGeneratorCode {
    
    	private static final Logger logger = LoggerFactory.getLogger(RedisGeneratorCode.class);
    
    	private RedisTemplate<String, Object> redisTemplate;
    
    	@Autowired
    	public RedisGeneratorCode(RedisTemplate<String, Object> redisTemplate) {
    		this.redisTemplate = redisTemplate;
    	}
    
    	/**
    	 * 
    	 * @Title: generateCode
    	 * @Description: 生成自定义前缀的类似 HTG201810120001格式的自增数
    	 * @param key redis中的key值
    	 * @param prefix  最后编码的前缀
    	 * @param hasExpire redis 是否使用过期时间设置自增id
    	 * @param minLength redis 生成的自增id的最小长度,如果小于这个长度前面补0
    	 * @return
    	 * String
    	 */
    	public String generateCode(String key, String prefix, boolean hasExpire, Integer minLength) {
    		return this.createGenerateCode(key, prefix, hasExpire, minLength);
    	}
    
    	/**
    	 * 
    	 * @Title: generateCode
    	 * @Description: 生成 类似 201810120001格式的自增数
    	 * @param key redis 中的key值
    	 * @param hasExpire redis 是否使用过期时间设置自增id
    	 * @param minLength redis 生成的自增id的最小长度,如果小于这个长度前面补0
    	 * @return
    	 * String
    	 */
    	public String generateCode(String key, boolean hasExpire, Integer minLength) {
    		return this.createGenerateCode(key, "", hasExpire, minLength);
    	}
    
    	/**
    	 * 
    	 * @Title: generateCode
    	 * @Description: 组装符合自己规则的id并设置过期时间
    	 * @param key	redis中的key值
    	 * @param prefix	最后编码的前缀
    	 * @param hasExpire	redis 是否使用过期时间设置自增id
    	 * @param minLength	redis生成的自增id的最小长度,如果小于这个长度前面补0
    	 * @return
    	 * String
    	 */
    	public String createGenerateCode(String key, String prefix, boolean hasExpire, Integer minLength) {
    		try {
    			Date date = null;
    			Long id = null;
    			Calendar calendar = Calendar.getInstance();
    			if (hasExpire) {
    				calendar.set(Calendar.HOUR_OF_DAY, 23);
    				calendar.set(Calendar.MINUTE, 59);
    				calendar.set(Calendar.SECOND, 59);
    				calendar.set(Calendar.MILLISECOND, 9999);
    				date = calendar.getTime();
    			} else {
    				calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 10);
    				date = calendar.getTime();
    			}
    			id = this.generateId(key, date);
    			if (id != null) {
    				return this.format(id, prefix, minLength);
    			}
    		} catch (Exception e) {
    			logger.info("error --> redis 生成自增id出现异常");
    			logger.error(e.getMessage(), e);
    		}
    		return null;
    	}
    
    	/**
    	 * 
    	 * @Title: generateId
    	 * @Description: 使用RedisAtomicLong自增
    	 * @param key redis中的key值
    	 * @param date 过期时间
    	 * @return
    	 * Long
    	 */
    	private Long generateId(String key, Date date) {
    		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
    		// 通过key获取自增并设定过期时间
    		counter.expireAt(date);
    		return counter.incrementAndGet();
    	}
    
    	/**
    	 * 
    	 * @Title: format
    	 * @Description: 获取 redis 自增后,生成自定义格式的id
    	 * @param id	redis 获取的 id值
    	 * @param prefix	自定义前缀
    	 * @param minLength	生成数的长度,不满足时 0 补齐
    	 * @return
    	 * String
    	 */
    	private String format(Long id, String prefix, Integer minLength) {
    
    		// 拼接的字符串
    		StringBuffer sb = new StringBuffer();
    		// 当前日期
    		Date date = new Date();
    		// 自定义前缀
    		sb.append(prefix);
    		if (date != null) {
    			DateFormat df = new SimpleDateFormat("yyyyMMdd");
    			sb.append(df.format(date));
    		}
    
    		/* 对不满足长度的id值,使用0补齐 */
    		// redis 生成的id值
    		String strId = String.valueOf(id);
    		// redis 生成id 的长度
    		int length = strId.length();
    		if (length < minLength) {
    			for (int i = 0; i < minLength - length; i++) {
    				sb.append("0");
    			}
    			sb.append(strId);
    		} else {
    			sb.append(strId);
    		}
    		return sb.toString();
    	}
    
    }

    方法中调用

    /**
      * 
      * @Title: getGeneratorId
      * @Description: 获取 yyyyMMdd0001格式,的自增工单id,并每天00:23:59 初始化化为0001
      * @return
      * Long
      */
    private Long getGeneratorId() {
      boolean flag = true;
      String code = null;
      int count = 0;
      while (flag) {
        System.err.println(++count);
        code = redisGeneratorCode.generateCode("worksheet_id", "", true, 4);
        flag = code == null ? true : false;
      }
      return Long.parseLong(code);
    }
    展开全文
  • mysql生成唯一主键的方法

    千次阅读 2019-05-28 15:00:57
    UUID.randomUUID(); 或者获取时间到秒获取唯一主键 或者写算法获取唯一主键

    UUID.randomUUID();

    或者获取时间到秒获取唯一主键

    或者写算法获取唯一主键

    展开全文
  • 分布式全局唯一主键

    2020-05-15 09:53:39
    分布式全局唯一主键数据页关于UUID与snowflake分布式主键另一种实现形式:redis 数据页 1.mysql的数据插入后,实际的存储都是放在数据页上面 2.按照B+Tree算法,新增加一个数据页,叫做页分裂 会出现性能下降 空间利用...

    数据页

    1.mysql的数据插入后,实际的存储都是放在数据页上面
    2.按照B+Tree算法,新增加一个数据页,叫做页分裂 会出现性能下降 空间利用率降
    3.查询时也会先看数据页是否在内存中,不在才会去硬盘加载
    4.有序主键能够保证写入的性能,避免频繁页分列
    附:
    主键是包含索引的,mysql的索引是通过b+树来实现,每次新的UUID数据插入,为了查询优化,会对底层的B+树进行修改,
    因为UUID无序,所以每次插入都会很大的修改,造成页分列,这一点很不友好
    mysql的官网已经不推荐UUID长的做主键

    关于UUID与snowflake

    1.而UUID本身是一个字符串并且32位而且无序,不仅能使聚簇索引空间大,还频繁的数据页分列导致的性能差
    2.雪花是趋势递增并且是长整形java中的long 能够避免频繁的数据页分裂
    3.雪花会用最后12位来表示每毫秒最大的并发数即能2^12=4096几乎够用了毫秒并发
    4.雪花的坏处是2039年9月7日
    雪花的缺点:
    依赖机器时钟,如果机器时钟回拨,会导致重复ID生成
    每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况 (此缺点可以认为无所谓,一般分布式ID只要求趋势递增,并不会严格要求递增,90%的需求都只要求趋势递增)

    分布式主键另一种实现形式:redis

    一个集群中5台Redis,初始化1,2,3.4,5,然后步长都为5
    各个Redis生成的ID为:
    A: 1,6,11,16,21
    B: 2,7,12,17,22
    C: 3,8,13,18,23
    D: 4,9,14,19,24
    E: 5,10,15,20,25

    缺点:
    1.引入5个节点redis集群太重,功能到是能实现
    2.由于顺序的规律性很容易猜出,因次不能防爬虫,竟争对手容易猜出

    mysql自增主键

    在分布式里面,数据库的自增ID机制的主要原理是:数据库自增ID和mysq|数据库的replace into实现的。
    关于 replace into说明:
    与insert into 功能相似 ,replae into 会看是否存在该记录存在则删除后再插入 如果不存在则直接插入

    CREATE TABLED t_test(
    id BIGINT(20) UNSIGNED NOT NULL AUTO NCREMENT PRIMARY KEY,
    stub CHAR(1) NOT NULL DEFAULT,
    UNIQUE KEY stub (stub)
    SELECT" FROMt_ ftest;
    I
    REPLACE INTO t_test (stub) VALUES(D);
    

    工具包hutool

    github地址
    https://github.com/looly/hutool/
    pom.xml

    <!----这个是全集-->
    <dependency>
    	<groupId>cn.hutool</groupId>
    	<artifactId>hutool-al1</artifactId>
    	<version>5.0.1</version>
    </dependency>
    <!----这个里面包含雪花算法-->
    <dependency>
    <groupId>cn.hutool</ groupId>
    <artifactId>hutool-captcha</ artifactId>
    <version>4.6.8</version>
    </dependency>
    

    雪花算法

    import javax.annotation.PostConstruct;
    
    @Slf4j
    @Component
    public class IdGeneratorSnowflake
    private 1ong workerId = 0;//工作ID
    private 1ong datacenterId = 1;//数据中心ID
    private Snowflake snowflake = IdUtil.createSnowflake(workerId,datacenterId);
    @PostConstruct
    public void init()
    	workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
    	log.info("当前机器的workerId: {}" ,workerId); I
    }
    
    public synchronized long snowflakeId( )
        return snowflake.nextId();
    }
    
    展开全文
  • 随机生成唯一主键

    千次阅读 2018-10-30 22:35:21
    * 生成随机唯一主键 * 格式:时间 + 随机数 */ public class KeyUtil { public static synchronized String genUniqueKey(){ Random random = new Random(); Integer number = random.nextInt(9000...
  • Oracle唯一主键ID的生成

    千次阅读 2019-04-22 18:10:24
    Oracle唯一主键ID的生成
  • 数据库唯一主键的实现主要是利用数据库中主键唯一约束的特性,一般来说唯一主键比较适用于“插入”时的幂等性,其能保证一张表中只能存在一条带该唯一主键的记录。 使用数据库唯一主键完成幂等性时需要注意的是,该...
  • 在平时开发时,如果没有定义数据库自动生成ID的机制,可以使用java自带的uuid生成随机唯一主键,在插入数据库时,可以直接给ID主键赋值;这个uuid方法,在java自带的utils包里,就可以直接调用:示例:public static...
  • mysql生成唯一主键

    千次阅读 2016-12-26 17:16:24
    使用mysql的UUID()函数,但因为UUID()生成的数值是含有"-"的,因此使用REPLACE(UUID(),'-',''),生成32位唯一主键
  • 生成唯一主键工具类

    千次阅读 2017-12-09 19:32:32
    * 生成唯一主键 * 格式:时间+随机数 */ public class KeyUtil { public static synchronized String genUniqueKey() { Random random=new Random(); Integer number=random.nextInt(900000)+100000;
  • 《分布式数据库中全局唯一主键生成策略的设计与实现》 《activiti5.10解决分布式集群部署的主键问题》 《分布式环境下数据库主键方案》 《如何在高并发分布式系统中生成全局唯一Id》 《分布式环境下ID生成方法总结》...
  • 三、Sharding JDBC 使用Snowflake生成唯一主键ID 配置文件制定 使用DefaultKeyGenerator 类获取 Snowflake时钟回拨问题 一、 Sharding-JDBC主键 软件项目开发中,主键自动生成是基本需求。而各个数据库对于该...
  • 【oracle唯一主键SYS_GUID()】

    千次阅读 2018-10-31 10:02:00
    唯一主键使用SYS_GUID() 生成32位的唯一编码。来生成唯一主键例如:create table test ( id raw(16) default sys_guid() primary key, filler varchar2(100) ) 这样就能生成唯一的主键id了,插入数据时不用插入...
  • 如何压力测试一个唯一主键函数是否真的不会生成重复主键得方法
  • 数据库分库分表就会引申出分布式系统中唯一主键ID的生成问题。一般我们唯一ID的有以下特性: 整个系统ID唯一 ID是数字类型,而且是趋势递增的 ID简短,查询效率快 下面我们看下常见的几种ID生成方式 UUID/GUID ...
  • 主键关联和唯一主键

    千次阅读 2014-10-11 09:14:27
    Hibernate 一对一关联映射(主键关联VS唯一外键关联) 博客分类:  Hibernate HibernateXMLSQL生活  一对一关联映射有两种:一种是主键关联,一种是“唯一”外键关联。  主键关联:原理是两张表的...
  • oracle唯一主键SYS_GUID()

    2015-02-03 14:12:55
    前面的博客介绍了用序列和触发器实现自增主键...唯一主键   使用 SYS_GUID() 生成32位的唯一编码。来生成唯一主键   例如:   create table test ( id raw(16) default sys_guid() primary key, fil...
  • db2中常用的生成唯一主键的几种方式 一、generate_unique() 这个方法类似于Oracle中的sys_guid(),用于生成一个随机不重复的13个字节的字符串。常常用来作为表的主键使用。 create table customers ( custno ...
  • 环境: ArcGIS 10 ,Oracle 11g 使用ArcCatalog粘帖数据的时候,ArcGIS报唯一主键错误: 没找到原因,估计SDE全局序列有冲突,多粘帖几次,错误没有了,郁闷~~
  • 主要通过对base64的处理以及 UUID的唯一主键对图片文件进行保存以及处理 package baseoflearn.learn; import java.io.*; import java.util.Base64; /** * @author :zhaofuh * @date :Created in 2020/10/26 ...
  • 唯一主键随机生成通过UUID生成类生成后可以去除中间的短线通过?String的replace方法然后对其进行hash调用String的hashCode方法获取hash码通过三元关系使其为正 package baseoflearn.learn; import java.util....
  • 分布式场景下,经常需要做分库分表,master和master结构,那么此时就会用到全局的唯一主键id。 如果使用mysql的分区策略,master到master的复制,那么此时就需要保证分区的唯一性避免主键冲突。 我们可以使用mysql

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,341
精华内容 10,536
关键字:

唯一主键