多並發時保證單號唯一
❶ 400分求ASP.NET實現多用戶並發產生不重復遞增單號源碼
有幾種方法,我感覺最好的是在sqlserver里將你的單號設為自增型的,起始值為1001,默認增長1,當然如果你自己寫的話,你可以每次插入新數據的時候都先查詢一下這個欄位的最大值然後+1,select top id from yourtable orderby id desc,然後把這個取到的值+1,插入到新的數據中去,不過這樣會有小問題,比如你剛生成一個1005,有個別的表的數據外鍵指向了這個1005,此時你刪除了1005這個值,但外鍵數據沒有刪除,你又添加了一個新數據,新數據id也是1005,會使數據混亂,所以感覺最好還是用第一種方法,資料庫會自動替你遞增並保證不沖突 追問當然不是簡單的增加就能做到,如果是按日期例如2011102601(當天的日期加後面的兩位流水碼或者有字母和數字組合A1001等)
回答那你可以自己寫一個專門用來生成單號的類,這個類負責用來生成你所規定格式的一個ID,並將此id保存下來,在下次需要生成的時候就按你的規律遞加,為了執行效率,你的保存另起一線程去做,程序不關閉是使用一個靜態變數來維護,當程序啟動的時候載入這個靜態變數,使用的時候跟據這個變數來生成後面的新變數,同時再將它保存起來就可以了
可以試試用文件 把第一個單號的整數往文件里寫 在增加的時候去文件里去讀 讀出來轉型把可用的整數部分取出來去疊加 在拼接前面的字元串
//新增單據方法
//單號
string newid = "";
FileStream fs = new FileStream("path", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string id = sr.ReadToEnd();
sr.Close();
fs.Close();
int number = 0;
if (id!="")
{
number = Convert.ToInt32(id) + 1; //這里以加一為例
}
newid = "A" + number;//用你要的字元串去憑借 我以A為列
這個前提是第一次你要往文件裡面去寫開始的那個單號 只寫整數部分 用substring 去截取
❷ 在高並發的情況下,不使用自增方式怎麼生成唯一主鍵
自己建個表存儲主鍵的當前值,然後每次從這里獲取主鍵值,並增加1。
自增長其實也是有地方保存當前值的。
❸ 如何保證資料庫集群中id的唯一性,假設每秒鍾並發20萬次
用雪花演算法的工具類,1秒內可以生成26萬不重復的值,資料庫的主鍵不要自增,手動設置
packageentity;
importjava.lang.management.ManagementFactory;
importjava.net.InetAddress;
importjava.net.NetworkInterface;
/**
*<p>名稱:IdWorker.java</p>
*<p>描述:分布式自增長ID</p>
*<pre>
*Twitter的SnowflakeJAVA實現方案
*</pre>
*核心代碼為其IdWorker這個類實現,其原理結構如下,我分別用一個0表示一位,用—分割開部分的作用:
*1||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(重復累加))
*
*@authorPolim
*/
publicclassIdWorker{
//時間起始標記點,作為基準,一般取系統的最近時間(一旦確定不能變動)
privatefinalstaticlongtwepoch=1288834974657L;
//機器標識位數
=5L;
//數據中心標識位數
=5L;
//機器ID最大值
=-1L^(-1L<<workerIdBits);
//數據中心ID最大值
=-1L^(-1L<<datacenterIdBits);
//毫秒內自增位
=12L;
//機器ID偏左移12位
=sequenceBits;
//數據中心ID左移17位
=sequenceBits+workerIdBits;
//時間毫秒左移22位
=sequenceBits+workerIdBits+datacenterIdBits;
=-1L^(-1L<<sequenceBits);
/*上次生產id時間戳*/
=-1L;
//0,並發控制
privatelongsequence=0L;
privatefinallongworkerId;
//數據標識id部分
privatefinallongdatacenterId;
publicIdWorker(){
this.datacenterId=getDatacenterId(maxDatacenterId);
this.workerId=getMaxWorkerId(datacenterId,maxWorkerId);
}
/**
*@paramworkerId
*工作機器ID
*@paramdatacenterId
*序列號
*/
publicIdWorker(longworkerId,longdatacenterId){
if(workerId>maxWorkerId||workerId<0){
(String.format("workerIdcan'tbegreaterthan%dorlessthan0",maxWorkerId));
}
if(datacenterId>maxDatacenterId||datacenterId<0){
(String.format("datacenterIdcan'tbegreaterthan%dorlessthan0",maxDatacenterId));
}
this.workerId=workerId;
this.datacenterId=datacenterId;
}
/**
*獲取下一個ID
*
*@return
*/
publicsynchronizedlongnextId(){
longtimestamp=timeGen();
if(timestamp<lastTimestamp){
thrownewRuntimeException(String.format("Clockmovedbackwards.Refusingtogenerateidfor%dmilliseconds",lastTimestamp-timestamp));
}
if(lastTimestamp==timestamp){
//當前毫秒內,則+1
sequence=(sequence+1)&sequenceMask;
if(sequence==0){
//當前毫秒內計數滿了,則等待下一秒
timestamp=tilNextMillis(lastTimestamp);
}
}else{
sequence=0L;
}
lastTimestamp=timestamp;
//ID偏移組合生成最終的ID,並返回ID
longnextId=((timestamp-twepoch)<<timestampLeftShift)
|(datacenterId<<datacenterIdShift)
|(workerId<<workerIdShift)|sequence;
returnnextId;
}
privatelongtilNextMillis(finallonglastTimestamp){
longtimestamp=this.timeGen();
while(timestamp<=lastTimestamp){
timestamp=this.timeGen();
}
returntimestamp;
}
privatelongtimeGen(){
returnSystem.currentTimeMillis();
}
/**
*<p>
*獲取maxWorkerId
*</p>
*/
(longdatacenterId,longmaxWorkerId){
StringBuffermpid=newStringBuffer();
mpid.append(datacenterId);
Stringname=ManagementFactory.getRuntimeMXBean().getName();
if(!name.isEmpty()){
/*
*GETjvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
*MAC+PID的hashcode獲取16個低位
*/
return(mpid.toString().hashCode()&0xffff)%(maxWorkerId+1);
}
/**
*<p>
*數據標識id部分
*</p>
*/
(longmaxDatacenterId){
longid=0L;
try{
InetAddressip=InetAddress.getLocalHost();
NetworkInterfacenetwork=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(Exceptione){
System.out.println("getDatacenterId:"+e.getMessage());
}
returnid;
}
publicstaticvoidmain(String[]args){
//推特26萬個不重復的ID
IdWorkeridWorker=newIdWorker(0,0);
for(inti=0;i<2600;i++){
System.out.println(idWorker.nextId());
}
}
}
❹ 並發,怎麼保證資料庫的數據唯一性
1、可考慮將獲取主鍵那個方法設置成同步的方式,所有的線程都需要同步獲取主鍵。
2、負責主鍵的類一次生成100個主鍵(根據需要自己設定),放到一個Queue里,一個線程拿走一個就從Queue里移除一個,同時生成新的主鍵放入到Queue里。
❺ 如何在高並發分布式系統中生成全局唯一Id
c# 中的 Guid 就是唯一的,它保證對在同一時空中的所有機器都是唯一的.
據我所知,它也會產生碰撞,但是概率極小,完全可以不用理會的小。
可以用現有的支持原子操作的分布式資料庫,
例:Redis 很多網站用Redis 的原子性來生成唯一標識符
我們可以用本機的Mac地址,硬碟序列號,本地最大標識符來拼接出唯一。
Mac 可被修改,硬碟序列號也有可能不唯一,但是這三樣拼接在一起,碰撞的概率很小的
Md5 也會碰撞,不是么?
❻ java web項目 訂單號問題
有啥困難么?資料庫中的訂單號為主鍵,設置為自增(恕我不知道是否有此功能),這樣就可以了。
拿Hibernate操作Oracle資料庫,對於訂單的主鍵訂單號使用sequence,然後在資料庫中定義對應的sequence就可以了啊。。。。
其他的資料庫我不清楚。或者調用存儲過程,在存儲過程中實現類似的功能即可。
思路就是這樣的。因為資料庫是唯一的,因此可以通過資料庫本身的唯一性避免多服務的沖突
❼ mysql 利用唯一索引Unique 高並發創建不重復唯一訂單號是否和興
訂單號建索引挺好的啊 ,這樣查詢還快
❽ 如何保證生成的訂單號的唯一性
訂單號不能採用時間戳的形式,因為不可能精確到秒,那樣訂單號過長 這種情況下只能在資料庫這端進行控制,但是也沒有看到資料庫有類似oracle的序列 問題補充:如果每次都去資料庫中查詢的話效率就有問題了 問題補充:guoxu0514 寫道擔心效率問題的話,你可以考慮用緩存來解決,不會有什麼事兒都有兩全其美的解決辦法。緩存也有問題,比如無法保證集群環境下訂單號的唯一性 問題補充:nixiangyan 寫道直接交個資料庫管理不久行了嗎這種情況下只能在資料庫這端進行控制,但是也沒有看到資料庫有類似oracle的序列 如果將用過的訂單號插到資料庫中,每次取最大的,效率上會不會有問題 問題補充:nixiangyan 寫道其實 我感覺吧,效率是相對的,當你提出某種要求的時候實質上很大的可能是在犧牲效率,交個資料庫管理如果是自增的話,你可能會說訂單號太單一,如果使用時間你說太長,還有使用時間為什麼不能精確到秒?可以解釋一下嗎? 我感覺做軟體不能太在意效率了,呵呵,主要是客戶給一定的規則,精確到秒的話訂單太長了,效率問題倒是可以先不考慮 問題補充:hu437 寫道可以這樣做的,取最大的,不一定要是從源表裡面取的,比如現在有一個訂單表,我再加一個計數表 當每生成一個訂單,我就同時將這個最大的訂單號存到計數表裡面,計數表裡面可以只有兩個欄位,一個叫計數內容,一個叫計數值
❾ 高並發時如何生成唯一編號
使用uuid。uuid的演算法是生成全球唯一的id