
用雪花算法的工具类,1秒内可以生成26万不重复的值,数据库的主键不要自增,手动设置
package entityimport java.lang.management.ManagementFactory
import java.net.InetAddress
import java.net.NetworkInterface
/**
* <p>名称:IdWorker.java</p>
* <p>描述:分布式自增长ID</p>
* <pre>
* Twitter的 Snowflake JAVA实现方案
* </pre>
* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
* 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
* <p>
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
*
* @author Polim
*/
public class IdWorker {
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
private final static long twepoch = 1288834974657L
// 机器标识位数
private final static long workerIdBits = 5L
// 数据中心标识位数
private final static long datacenterIdBits = 5L
// 机器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits)
// 数据中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits)
// 毫秒内自增位
private final static long sequenceBits = 12L
// 机器ID偏左移12位
private final static long workerIdShift = sequenceBits
// 数据中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits
// 时间毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits
private final static long sequenceMask = -1L ^ (-1L << sequenceBits)
/* 上次生产id时间戳 */
private static long lastTimestamp = -1L
// 0,并发控制
private long sequence = 0L
private final long workerId
// 数据标识id部分
private final long datacenterId
public IdWorker(){
this.datacenterId = getDatacenterId(maxDatacenterId)
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId)
}
/**
* @param workerId
* 工作机器ID
* @param datacenterId
* 序列号
*/
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId))
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId))
}
this.workerId = workerId
this.datacenterId = datacenterId
}
/**
* 获取下一个ID
*
* @return
*/
public synchronized long nextId() {
long timestamp = timeGen()
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp))
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & sequenceMask
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp)
}
} else {
sequence = 0L
}
lastTimestamp = timestamp
// ID偏移组合生成最终的ID,并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence
return nextId
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen()
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen()
}
return timestamp
}
private long timeGen() {
return System.currentTimeMillis()
}
/**
* <p>
* 获取 maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer()
mpid.append(datacenterId)
String name = ManagementFactory.getRuntimeMXBean().getName()
if (!name.isEmpty()) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0])
}
/*
* MAC + PID 的 hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1)
}
/**
* <p>
* 数据标识id部分
* </p>
*/
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L
try {
InetAddress ip = InetAddress.getLocalHost()
NetworkInterface network = NetworkInterface.getByInetAddress(ip)
if (network == null) {
id = 1L
} else {
byte[] mac = network.getHardwareAddress()
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6
id = id % (maxDatacenterId + 1)
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage())
}
return id
}
public static void main(String[] args) {
//推特 26万个不重复的ID
IdWorker idWorker = new IdWorker(0,0)
for (int i = 0 i <2600 i++) {
System.out.println(idWorker.nextId())
}
}
}
以serversql为例:if exists(select * from sysobjects where name='DepartmentTab')
drop table DepartmentTab
create table DepartmentTab--创建一个表
(
DepartID int primary key identity(1,1),--identity自增 ,primary key主键
DepartName nvarchar(50) unique,--unique唯一的,并且不能为空
condition int default('0') --default 默认为0
)
数据库约束是程序开发中常用的重要知识点,建立约束的数据,在输入中有两个一样的保存就会出错,需要建立唯一约束。
那就给大家详细的列举一下如何在 sql server表中设置字段为唯一约束。
具体 *** 作步骤:新建数据库并设置可写权限
打开SQL Server管理器窗口,用本地用户登录;然后点击右键——新建数据库;完成之后将数据库文件及日志文件设置为可读可写:
新建数据表
展开数据库,点击表——新建表,输入名称及数据类型。
设置主键约束
点击表右键——设计——选中id——右键——设置主键,将id设置为主键,主键默认唯一。
测试主键约束
在数据表中输入数据,为测试主键的约束,输入两行一模一样的id,保存;
如图所示,保存会提示主键不允许重复。
设置非主键唯一值约束
选中表,点击菜单栏——新建查询,将IDcard设为非主键唯一值,输入以下代码:ALTER TABLE Users ADD unique(IDcard),然后点击执行。
测试非主唯一约束
在数据表中输入两行id不同,IDCard相同的数据,并保存;若出现错误提示,将IDCard修改之后再检测。
关闭数据库并断开连接
由于数据库会在后台运行,所以测试完之后,本地数据库一定要断开连接,然后关闭。
以上就是具体的 *** 作办法了。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)