生成整数自增ID(集群主键生成服务)

Web服务器集群调用这个整数生成服务,然后根据各种规则,插入指定的数据库.
一般来说,整数自增可以通过几个方式实现.
1.MySQL 单独建一个表,使用Auto_increment特性.
- CREATE TABLE `test` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
如果需要生成ID,则Insert一个记录,然后获取last_insert_id()得到ID值
这种方式的优点是简单,而且比较快.
缺点是这个表会越来越大,需要定期进行清理.
2.Oracle 序列
优点很明显,足够快,而且不占用空间.
缺点..你需要有Oracle
3.mysql 单行更新自增
需要生成ID的时候,进行如下调用
以上三种数据库方式的效率对比如下(都是测试的虚拟环境,作为趋势参考,数值是每秒生成的ID个数)
单线程 | 5线程 | 10线程 | 20线程 | |
MySQL Auto_increment | 340-390 | 277 | 229 | 178 |
Oracle序列 | 714 | 555 | 454 | 454 |
MySQL 单行更新 | 303 | 136 | 66 | 19 |
4.使用Redis自增
使用两个Redis实例,一个分发奇数ID,一个分发偶数ID
任何一个Redis损坏,都可以切换到另外一个Redis实例.
5.使用程序模拟序列
下面的ID生成服务,初始化先从数据库拿到一段ID,然后分发。
一旦ID耗尽,再从数据库获取一段ID。
可以启动多个ID生成服务,避免单点故障.
ID生成服务本身应该串行化,避免锁竞争.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class SeqGenerator {
private static ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); private static int currentVal = -1;
private static int maxVal = -1;
private static int fetchSize = 10000;//每次生成一万个id static{
try {
fetchFromDB();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public static int getSeq() throws InterruptedException, ExecutionException {
Callable<Integer> c = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int result = currentVal;
if (currentVal > maxVal) {//如果当前值>数据库最大值,重新生成id
fetchFromDB();
result = currentVal;
}
currentVal++;
return result; }
};
Future<Integer> task = singleThreadExecutor.submit(c);
return task.get().intValue();
} private static void fetchFromDB() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "xx", "xx");
connection.setAutoCommit(false);
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery("select * from test for update");
rs.next();
currentVal = rs.getInt(1) + 1;//当前值
rs.close();
st.executeUpdate("update test set id=id+" + fetchSize);//更新db中最大值
rs = st.executeQuery("select * from test for update");
rs.next();
maxVal = rs.getInt(1);//最大值
connection.commit();
rs.close();
st.close();
connection.close();
} public static void main(String[] args) throws Exception {
int i = 1000000;
long start = System.currentTimeMillis(); while (i > 0) {
System.out.println(SeqGenerator.getSeq());
i--;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
使用这种自定义序列,1百万ID的生成时间是14s.效果非常明显.
生成整数自增ID(集群主键生成服务)的更多相关文章
- Hibernate(4)——主键生成策略、CRUD 基础API区别的总结 和 注解的使用
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: hibernate的主键生成策略 UUID 配置的补充:hbm2ddl.auto属性用法 注解还是配置文件 h ...
- Hibernate主键生成策略及选择
1 .increment:适用于short,int,long作为主键,不是使用数据库自动增长机制 这是hibernate中提供的一种增长机制 在程序运行时,先进行查询:select max(id) f ...
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Hibernate学习笔记(三)Hibernate生成表单ID主键生成策略
一. Xml方式 <id>标签必须配置在<class>标签内第一个位置.由一个字段构成主键,如果是复杂主键<composite-id>标签 被映射的类必须定义对应数 ...
- Centos7.6部署k8s v1.16.4高可用集群(主备模式)
一.部署环境 主机列表: 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注 master01 7.6. ...
- 4.ID主键生成策略
保证唯一性(auto_increment) 一.xml方式 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping P ...
- SpringJPA主键生成采用自定义ID,自定义ID采用年月日时间格式
自定义主键生成策略 在entity类上添加注解 @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "custom ...
- EF中更新操作 ID自增但不是主键 ;根据ViewModel更新实体的部分属性
//ID自增但不是主键的情况 public int Update_join<TEntity>(TEntity entity) where TEntity : class { dbconte ...
- mybatis plus 主键生成 Twitter雪花算法 id 及修改id为字符型
mybatis plus配置主键生成策略为2,就是 使用Twitter雪花算法 生成id spring boot中配置为: GlobalConfiguration conf = new GlobalC ...
随机推荐
- random between [a,b]、(a,b]、[a,b)
#include <iostream> #include <ctime> #include <cstdlib> using namespace std; ; /*c ...
- IAR:Error [Li005]:no definition for"***" 问题之连接
对于 IAR 出现的 Error[Li005] 链接错误,网上已经给出了比较详尽的解决方法,而对于这次记录,主要是记录解决问题的思路. 网上给出的方法:http://blog.csdn.net/yue ...
- H5全景视频VR视频
公司的有个专题页面涉及到全景视频展示这个技术点,找到一个相关的库. http://www.utovr.com/sdk/download 这里有个免费的SDK可以下载. 里面也有案例可以看,代码就照着 ...
- YII千万级PV架构经验分享--理论篇
hello,大家好,我是方少,现在想象一下这样一个情景,这是一个很惬意的季节,是一个可以随意乱穿的季节,两个人,一个穿羽绒服,一个穿热裤,小胡同里两人迎面走来,看到对方都哈哈大笑,前仰后合,笑完都甩一 ...
- Ecshop实现仿Taobao地区运费模板
目录: 1.Ecshop后台配送方式创建 2.商品绑定配送方式的运费模板 2.1 数据表“ecs_goods”增加一个字段,执行下面SQL语句: 2.2 后台添加/编辑 商品 调出已经安装配送方式 & ...
- Linux ps同时查找多个进程
1.显示当前所有进程 SDCxM-SDCAM-root-root> ps aux USER PID %CPU %MEM VSZ RSS TTY STAT STAR ...
- pyunit实现数据测试框架
PyUnit提供的动态方法,只编写一个测试类来完成对整个软件模块的测试,这样对象的初始化工作可以在setUp()方法中完成,而资源的释放则可以在tearDown()方法中完成. 使用PyUnit可以像 ...
- 2014年辛星完全解读Javascript第六节 对象
随着面向对象的普及,现在很多语言都在支持面向对象,Javascript也不例外,所谓对象,就是拥有属性和方法的数据.这里的属性其实就是变量,这里的方法,其实就是函数.但是Javascript的面向对象 ...
- JAVA中的各种 哈希码(HashCode) 与 equals方法在HIBERNATE的实际应用[转载]
1.什么是哈希码(HashCode) 在Java中,哈希码代表对象的特征.例如对象 Java代码 String str1 = “aa”, str1.hashCode= 3104 String str2 ...
- fineui框架
http://fineui.com/demo/#/demo/layout/fit.aspx 虽然比较丑陋,但功能实用 此框架比较简单, 框架的作用你懂的,重点是要有帮助文档, 进阶型的容易上手的帮助文 ...