`
无量
  • 浏览: 1148442 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

全局主键生成器-支持单JVM1秒近1000万订单生成

阅读更多
全局主键生成器

介绍:
相对于DB自增序列的全局主键生成器,性能更高,同时保留业务需求的业务含义,
对于有分库分表需求的业务同时可以存储分库和分表的信息,对于高并发的互联网企业分库分表生成主键来说是一种很好的方法

package com.tongbanjie.trade.test.base;

import java.net.InetAddress;
import org.apache.commons.lang.StringUtils;
import com.tongbanjie.commons.util.TSS;

public class TestGenId {
	
	public static void main(String[] args) throws Exception {
		
		/**
		 * 项目:交易单分表
		 * 
		 *  需求
		 *  查询需求: 1. userId维度
		 *  		 2. 产品维度
		 *  		 3. 商户维度
		 *  		 4. 时间区间维度
		 *  
		 *  预计订单量:
		 *  	  一单平均10000, 一年交易额5000亿, 需要成功订单量 = 500000000000 / 10000 = 50000000 5000万订单
		 *  	 购买加回款应该是1亿订单量, 所以, 单表2000万, 一年需要5张表
		 *  
		 *  	最后扩展64库 + 64表, 共64*64 = 4096表, 4096 * 2000万 = 819亿订单够用了, 819亿 * 10000 = 8190000亿  819万亿,够用了
		 *  
		 *  全局唯一主键:
		 *  	15位时间戳 + 自增序号四位 + 机器后两段IP,6位 + 备用1位 + 分库信息两位 + 分表信息两位  共30位,  回款改造前
		 *  	15位时间戳 + 自增序号四位 + 机器后两段IP,6位 + 备用3位 + 分库信息两位 + 分表信息两位  共32位,  回款改造后
		 *      
		 *      单JVM支持最多1s  1000 * 9999 = 9999000, 999万9千笔订单,后续还可以扩展。
		 *  
		 *  分库规则:
		 *  	寻找到数据库  (userId/100) % 64 + 1 找到数据库    订单最多64个库    目前一个库   二分法裂变扩容
		 *  分表规则:
		 *  	寻找到表信息  userId % 64 + 1 找到表信息    一个库最多64个表   目前分8张表    以后二分法裂变扩容
		 *  
		 *  迁移规则:
		 *  	迁移方案同步写, 目前用动态表名, 以后分表中间件稳定后, 迁移过去
		 *  
		 *  查询改造:
		 *  	原接口不变,对用户无感知, 底层钩子遍历
		 */

		// 只获取本地局域网IP即可
		String ip = InetAddress.getLocalHost().getHostAddress();
		String[] ipArray = ip.split("\\.");

		final String lastTwoPhaseIp = StringUtils.rightPad(ipArray[2], 3, '0')
				+ StringUtils.leftPad(ipArray[3], 3, '0');
		
		for (int i = 0; i < 100000; i++) {
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					// TSS commons工具类
					String tss = TSS.getTimeStampSequence();
					String id = tss + lastTwoPhaseIp + "000" + "01" + "08";
					System.out.println(id);
				}
			}).start();
		}
	}
	
}

package com.tongbanjie.commons.util;

import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 时间戳序列器<br>
 * 
 * 支持同一毫秒最多生成9999笔序列号<br>
 * @author sanfeng
 *
 * 想象力就是生产力
 */
public class TSS {

	// 默认1个大小
	private static HashMap<String, AtomicInteger> tssCache
		= new HashMap<String, AtomicInteger>(1);
	
	private static final ReentrantLock lock = new ReentrantLock();

	// 因为有锁,所以是变成了线程安全的,省去每次 new 的消耗,耗时降低约一半
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
	
	public static String getTimeStampSequence() {
		
		String timestamp = null;
		String inc = null;
		
        lock.lock();
        try {
        	
        	timestamp = sdf.format(new Date());
        	AtomicInteger value = tssCache.get(timestamp);
			if(value == null) {
				tssCache.clear();
				int defaultStartValue = 0;
				tssCache.put(timestamp, new AtomicInteger(defaultStartValue));
				inc = String.valueOf(defaultStartValue);
			} else {
				inc = String.valueOf(value.addAndGet(1));
			}
        } finally {
            lock.unlock();
        }
		
		return timestamp + StringUtils.leftPad(inc, 4, '0');
	}

	
	public static void main(String[] args) throws Exception {
		
//		for (int i = 0; i < 1000; i++) {
//			new Thread(new Runnable() {
//				
//				@Override
//				public void run() {
//					for (int j = 0; j < 10; j++) {
//						System.out.println(TSS.getTimeStampSequence());
//					}
//				}
//			}).start();
//		}

		
		// 统计重复
		HashSet<String> set = new HashSet<String>();
		BufferedReader br = new BufferedReader(
				new InputStreamReader(new FileInputStream("C:/Users/Administrator/Desktop/1.txt")));
		String str = br.readLine();
		while(str != null) {
			if(set.contains(str)) {
				System.out.println(str);
			} else {
				set.add(str);
			}
			str = br.readLine();
		}

		br.close();

	}
}
0
0
分享到:
评论
2 楼 无量 2016-07-24  
一年e度的夏天 写道
敢问一句测试过了吗?我测试了十个线程就发现了大量一样的订单号

这个确实有问题,已经修改
1 楼 一年e度的夏天 2016-07-15  
敢问一句测试过了吗?我测试了十个线程就发现了大量一样的订单号

相关推荐

    nginx-upstream-jvm-route-1.15

    【标题】"nginx-upstream-jvm-route-1.15" 涉及的核心知识点是Nginx的upstream模块与JVM路由的整合,特别针对Nginx 1.15版本。这个项目旨在解决在配置Nginx时遇到的特定错误提示“nginx: [emerg] invalid parameter ...

    nginx-upstream-jvm-route 和 nginx 对应版本,亲测可用

    此资源有两个文件,含 nginx-upstream-jvm-route 和 nginx 对应版本,都是tar.gz文件。 安装方法网上很多就不写了,亲测可用。 不用担心版本不匹配造成安装失败,再浪费积分去到处下载尝试的烦恼。 此资源有两个文件...

    kotlinx-coroutines-io-jvm-0.1.1.jar

    kotlinx-coroutines-io-jvm-0.1.1.jar

    nginx-upstream-jvm-route-1.12.0.tar.gz

    nginx_upstream_jvm_route 是一个 Nginx 的扩展模块,用来实现基于 Cookie 的 Session Sticky 的功能。 安装方法(进入Nginx源码目录): #patch -p0 &lt; /path/to/this/directory/jvm_route.patch # ./configure -...

    nginx-upstream-jvm-route-0.1.tar.gz

    "nginx-upstream-jvm-route-0.1.tar.gz"正是为了解决这个问题而设计的一个解决方案。 首先,让我们了解一下Nginx的Upstream模块。Upstream模块允许Nginx将接收到的请求转发到一组后端服务器,可以根据配置的策略...

    02-VIP-JVM内存模型深度剖析(1)1

    1. JVM整体结构及内存模型: - **堆内存**:这是Java应用中最大的内存区域,主要存储对象实例和数组。堆被分为新生代(Young Generation)和老年代(Old Generation),新生代又分为Eden区、Survivor区(通常两个)...

    面试总结-JVM .png

    JVM 的运行机制 多线程 JVM 的内存区域 JVM 会创建操作系统的接口创建一个原生线程。JVM 线程和操作系统线程是一一对应的

    JVM调优总结 -Xms -Xmx -Xmn -Xss

    JVM调优总结 -Xms -Xmx -Xmn -Xss JVM 调优是 Java virtual machine 的性能优化,通过调整 JVM 的参数来提高 Java 应用程序的性能。其中,-Xms、-Xmx、-Xmn、-Xss 是四个重要的参数,分别控制 JVM 的初始堆大小、...

    2015-09-12-Java虚拟机详解----JVM常见问题总结【面试必问】

    1. **双亲委派模型**:类加载器首先尝试由父加载器加载,如果父加载器无法加载,则由当前加载器加载。这样保证了核心类库的唯一性。 2. **自定义类加载器**:可以实现特定的类加载逻辑,例如从网络、数据库加载类。...

    深入JVM---JVM命令---invokespecial

    《深入JVM---JVM命令---invokespecial》 在Java虚拟机(JVM)的世界里,`invokespecial`指令扮演着至关重要的角色。它主要用于执行对象的构造方法(即`&lt;init&gt;`方法),以及调用私有方法和父类非静态方法。本文将...

    kotlin-logging-jvm-2.1.21.jar

    kotlin-logging-jvm-2.1.21.jar

    java课件-7-JVM

    1. **JVM内存模型**: JVM内存主要分为堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(PC Register)和本地方法栈(Native Method Stack)。堆是所有线程共享的区域,用于存储对象实例;栈则与线程...

    ktor-utils-jvm-1.0.1.jar

    ktor-utils-jvm-1.0.1.jar

    kotlinx-io-jvm-0.1.1.jar

    kotlinx-io-jvm-0.1.1.jar

    hibernate主键生成策略

    【hibernate主键生成策略】是Hibernate框架中用于生成持久化对象主键的重要机制,它决定了如何在数据库中创建唯一的标识符。在SSH(Spring、Struts、Hibernate)架构中,Hibernate作为持久层框架,主键生成策略的...

    kotlin-scripting-jvm.jar

    kotlin-scripting-jvm.jar

    JVM-MANAGEMENT-MIB,jvm mib库

    JVM,MIB,可通过SNMP协议监控JVM运行情况

    JVM 参数调优-optimization-jvm.zip

    1. **JVM内存模型**:JVM内存主要分为堆内存(Heap)、方法区(Method Area)、虚拟机栈(JVM Stack)、本地方法栈(Native Method Stack)和程序计数器(Program Counter Register)。了解每个区域的作用和配置参数...

    Swift-to-JVM字节码编译器JetANTLR.zip

    Jet 是 Swift-to-JVM 字节码编译器,为 Java 8 Runtime 而准备。Jet 使用 ANTLR 编写。 标签:JetANTLR

    mat(mac)---jvm内存分析工具

    MAT,全称Memory Analyzer Tool,是IBM开发的一款强大的Java虚拟机(JVM)内存分析工具,尤其适用于Mac OS X平台。这款工具可以帮助开发者诊断和解决Java应用中的内存泄漏问题,提高应用性能。MAT通过深入分析堆转储...

Global site tag (gtag.js) - Google Analytics