生成整数自增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 ...
随机推荐
- template_1
0: 模板是一些为多种类型而编写的函数和类,而且这些类型都没有指定.当使用模板的时候,只需要把所希望的类型作为一个(显示或隐示的)实参传递给模板.模板是语言本身所具有的特效,她完全支持类型检查和作用域 ...
- POJ 3928 Ping pong
题目链接:http://poj.org/problem?id=3928 乒乓比赛,有N个人参加,输入每个玩家的技能等级,对每个人设置一个特定ID和一个技能值,一场比赛需要两个选手和一个裁判,只有当裁判 ...
- 【转载】分享下多年积累的对JAVA程序员成长之路的总结
注:该文是从百度贴吧转载过来,之前看到觉得写得还不错,对Java开发学习者来说很有意义的,可以看看. 我也搞了几年JAVA了,由于一向懒惰,没有成为大牛,只是一普通程序猿,不爱玩社交网站,不爱玩微博, ...
- DTCMS视频模版更改,
1.去掉style.css中视频的高度 .video-box{ position:relative; width:100%; height:473px; _clear:both; _display:i ...
- WeX5与阿里内测的Weex与有何纠葛?快来看HTML5开发圈那些逗逼事儿!
4月21日~23日,由infoQ主办的2016 Qcon大会北京站如期举行. HTML5开发已经成为移动开发/前端专题中无可争议的焦点,核心议题已经由前几年的是否该用HTML5转向了如何高性能.高效率 ...
- js给数字加三位一逗号间隔的两种方法(面试题)
方法一: <script type= "text/javascript"> //保留三位小数,toLocaleString() 方法可把一个 Number 对象转换 ...
- 九度OJ做题记录 更新.....
2015年1月7日 20:34:23 题目1007:奥运排序问题 有点意思,以后想另外方法快速做出来 2015年1月7日 21:03:56 有一个技巧就是,写了三个比较函数cmp1,cmp2,cmp ...
- PL/SQL数据导入导出浅谈(1)
近来需要通过PL/SQL向Oracle中导数据,特此总结一下 试例表:test 字段:id;name;org; 1.直接复制粘贴(当数据量不是特别大的时候) 1)使用select * from tes ...
- 移动端webapp开发必备知识
移动设备的用户越来越多,每天android手机的激活量都已经超过130万台,所以我们面向移动终端的WebAPP也开始跟进了.本文主要介绍webapp的开发与调试的相关知识和经验,以及给出几种可选的解决 ...
- EXTJS 4.2 资料 控件之tabpanel 静态生成tabpanel
//**************页面主体开始***************** var tabpanel = Ext.createWidget('tabpanel', { activeTab: 0, ...