鐜鏄繖鏍風殑錛氭湇鍔″櫒鏄敤Java鍋氱殑錛?鏁版嵁搴撴槸MongoDB
闇姹傛槸榪欐牱鐨勶細鎴戜滑鐨勭郴緇熼噷瑕佺敓鎴愪竴涓敮涓ID錛屽墠闈㈢殑閮ㄥ垎鏈変竴瀹氱殑鏍煎紡錛屽茍鍜屾椂闂村叧鑱旓紝 綺劇‘鍒板井縐掞紝鑰冭檻鍒板悓涓寰鍐呮湁鍙兘瀛樺湪騫跺彂鎯呭喌錛? 鎵浠ュ悗闈㈠湪鍔犱袱浣嶅簭鍒楀彿錛?緋葷粺闇瑕佸畾涔変負1姣鍐呯殑騫跺彂灝忎簬100涓紝鎵浠ュ悗闈袱浣嶅氨澶熺敤浜嗐? Java鏈嶅姟鍣ㄧ鏈夊鍙版満鍣ㄩ兘鍙互鐢ㄦ潵鐢熸垚榪欎釜鍞竴ID錛屾墍浠ラ渶瑕佸湪涓嶅悓鐨勬満鍣ㄤ笂涓嶈兘鐢熸垚鐩稿悓鐨勫簭鍒楀彿錛屾墍浠ラ渶瑕佸湪鏌愪竴鐐逛笂鍋氬叏灞鐨勮寖鍥村悓姝ユ潵淇濆瓨榪欏簭鍒? 鍙風殑鍞竴鎬с?鍏跺疄濡傛灉涓嶈冭檻闇姹傞噷鐨勫敮涓ID鏄湁涓瀹氭剰涔夌殑鏍煎紡鐨勶紝 鐢║UID鎴朚ongoDB鐨凮bjectId閮芥槸鏇村ソ鐨勯夋嫨錛屽畬鍏ㄤ笉闇瑕佸湪鏌愪竴鐐逛笂榪涜鍚屾錛屾ц兘浼氭洿濂姐?/p>
榪欎釜鍙互鐢熸垚搴忓垪鍙風殑鐐癸紝 鎴戜滑鍙互鍋氫竴涓簭鍒楀彿鐢熸垚鏈嶅姟鍣ㄦ潵瀵瑰簲錛?涔熷彲浠ョ敤鏁版嵁搴撴潵瀵瑰簲銆? 鍗曞崟涓鴻繖涓畝鍗曠殑鍔熻兘鍑嗗涓涓湇鍔″櫒鏉ュ仛鏄劇劧涓嶅悎閫傘?浣嗘槸鎴戜滑鐢ㄧ殑MongoDB騫舵病鏈夌被浼間簬MySQL鎴朞racle涓殑SELECT FOR UPDATE榪欐牱鐨勯攣鏈哄埗銆?鎵浠ユ病鏈夊姙娉曠畝鍗曠殑瀵硅繖涓簭鍒楀彿鍋氬師瀛愭搷浣溿? 浣嗘槸MongoDB鐨勫鍗曚釜document榪涜update鎿嶄綔涓湁寰堟槸鍏鋒湁鍘熷瓙鎬х殑錛?渚嬪
- $set
- $unset
- $inc
- $push
- $pushAll
- $pull
- $pullAll
鎴戜滑鍙互鍒╃敤榪欎簺鍘熷瓙鎿嶄綔錛屽湪鏁版嵁搴撳眰浠ヤ箰瑙傞攣鐨勫艦寮忔潵瀹炵幇寰幆搴忓垪瀛楁銆備負浜嗘柟渚胯皟鐢ㄦ垜鎶婅繖孌甸昏緫鍋氭垚鏁版嵁搴撲腑鐨凧avascript鍑芥暟銆?綾諱技涓嶮ySQL涓殑瀛樺偍榪囩▼銆?/p>
棣栧厛鎴戜滑闇瑕佷竴涓猚ollection鏉ュ瓨鏀懼簭鍒楀彿錛屽茍瀵歸渶瑕佺殑闇瑕佺殑搴忓垪鍙瘋繘琛屽垵濮嬪寲銆傛垜浠彨瀹僣ounters銆?/p>
- db.counters.save({_id:"SerialNo1", val:0, maxval:99})
鐒跺悗鎴戜滑鎯硈ystem.js閲屾坊鍔犱竴涓狫avascript鍑芥暟
- db.system.js.save({_id:"getNextUniqueSeq",
- value:function (keyName) {
- var seqObj = db.counters.findOne({_id:keyName});
- if (seqObj == null) {
- print("can not find record with key: " + keyName);
- return -1;
- }
- // the max value of sequence
- var maxVal = seqObj.maxval;
- // the current value of sequence
- var curVal = seqObj.val;
- while(true){
- // if curVal reach max, reset it
- if(curVal >= maxVal){
- db.counters.update({_id : keyName, val : curVal}, { $set : { val : 0 }}, false, false);
- var err = db.getLastErrorObj();
- if( err && err.code ) {
- print( "unexpected error reset data: " + tojson( err ) );
- return -2;
- } else if (err.n == 0){
- // fail to reset value, may be reseted by others
- print("fail to reset value: ");
- }
- // get current value again.
- seqObj = db.counters.findOne({_id:keyName});
- maxVal = seqObj.maxval;
- curVal = seqObj.val;
- continue;
- }
- // if curVal not reach the max, inc it;
- // increase
- db.counters.update({_id : keyName, val : curVal}, { $inc : { val : 1 }}, false, false);
- var err = db.getLastErrorObj();
- if( err && err.code ) {
- print( "unexpected error inc val: " + tojson( err ) );
- return -3;
- } else if (err.n == 0){
- // fail to reset value, may be increased by others
- print("fail to inc value: ");
- // get current value again.
- seqObj = db.counters.findOne({_id:keyName});
- maxVal = seqObj.maxval;
- curVal = seqObj.val;
- continue;
- } else {
- var retVal = curVal + 1;
- print("success to get seq : " + retVal);
- // increase successful
- return retVal;
- }
- }
- }
- });
涓婇潰榪欐浼氭妸鎸囧畾鐨勫簭鍒楀彿鐨剉al鍊?1錛屽鏋渧al杈懼埌涓婇檺鍒欎粠0寮濮嬨傛墍浠ュ彨寰幆搴忓垪銆?/p>
鍏跺疄涓婇潰鐨勫疄鐜板湪鍘熺悊涓婂拰Java閲岀殑AtomicInteger緋誨垪鐨勫姛鑳藉疄鐜版槸綾諱技鐨勶紝鍒╃敤寰幆閲嶈瘯鍜屽師瀛愭х殑CAS鏉ュ疄鐜般傝繖縐嶅疄鐜版柟寮忓湪澶氱嚎紼嬬殑鐜閲岀敱浜庨攣錛圡onitor錛夌殑鑼冨洿寰堝皬錛屾墍浠ュ茍鍙戞т笂姣旀帓浠栭攣瑕佸ソ涓浜涖?/p>
涓嬮潰鎴戜滑鐢↗ava鏉ユ祴璇曚竴涓嬭繖涓嚱鏁扮殑姝g‘鎬с?鍗沖湪澶氱嚎紼嬬殑鎯呭喌涓嬩細涓嶄細寰楀埌閲嶅鐨勫簭鍒楀彿銆?/p>
絎竴涓祴璇曪紝val=0錛?maxval=2000錛?Java绔?0涓嚎紼嬫瘡涓嚎紼嬪驚鐜皟鐢?00嬈°?鍏?000嬈°?鎵浠ユ紜殑鎯呭喌涓嬶紝浠?鍒?999搴旇姣忎釜鏁板瓧鍙嚭鐜頒竴嬈°?/p>
- @Test
- public void testGetNextUniqueSeq1() throws Exception {
- final int THREAD_COUNT = 20;
- final int LOOP_COUNT = 100;
- Mongo mongoClient = new Mongo("172.17.2.100", 27017);
- DB db = mongoClient.getDB("im");
- db.authenticate("imadmin", "imadmin".toCharArray());
- BasicDBObject q = new BasicDBObject();
- q.put("_id", "UNIQUE_KEY");
- BasicDBObject upd = new BasicDBObject();
- BasicDBObject set = new BasicDBObject();
- set.put("val", 0);
- set.put("maxval", THREAD_COUNT * LOOP_COUNT);
- upd.put("$set", set);
- db.getCollection("counters").update(q, upd);
- Thread[] threads = new Thread[THREAD_COUNT];
- final int[][] results = new int[THREAD_COUNT][LOOP_COUNT];
- for (int i = 0; i < THREAD_COUNT; i++) {
- final int temp_i = i;
- threads[i] = new Thread("" + i) {
- @Override
- public void run() {
- try {
- Mongo mongoClient = new Mongo("172.17.2.100", 27017);
- DB db = mongoClient.getDB("im");
- db.authenticate("imadmin", "imadmin".toCharArray());
- for (int j = 0; j < LOOP_COUNT; j++) {
- Object result = db.eval("getNextUniqueSeq(\"UNIQUE_KEY\")");
- System.out.printf("Thread %s, seq=%d\n", Thread.currentThread().getName(), ((Double) result).intValue());
- results[temp_i][j] = ((Double) result).intValue();
- }
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- }
- };
- }
- for (Thread thread : threads) {
- thread.start();
- }
- for (Thread thread : threads) {
- thread.join();
- }
- for (int num = 1; num <= LOOP_COUNT * THREAD_COUNT; num++) {
- // every number appear 1 times only!
- int times = 0;
- for (int j = 0; j < THREAD_COUNT; j++) {
- for (int k = 0; k < LOOP_COUNT; k++) {
- if (results[j][k] == num)
- times++;
- }
- }
- assertEquals(1, times);
- }
- }
鐒跺悗鎴戜滑鍐嶆祴璇曚竴涓嬪驚鐜殑鎯呭喌銆?val=0, maxval=99銆?鍚屾牱鏄疛ava绔?0涓嚎紼嬫瘡涓嚎紼嬪驚鐜皟鐢?00嬈°?鍏?000嬈°傝繖嬈′粠0鍒?9鐨勬暟瀛楁瘡涓簲璇ュ彇寰?0嬈°?/p>
- @Test
- public void testGetNextUniqueSeq2() throws Exception {
- final int THREAD_COUNT = 20;
- final int LOOP_COUNT = 100;
- Mongo mongoClient = new Mongo("172.17.2.100", 27017);
- DB db = mongoClient.getDB("im");
- db.authenticate("imadmin", "imadmin".toCharArray());
- BasicDBObject q = new BasicDBObject();
- q.put("_id", "UNIQUE_KEY");
- BasicDBObject upd = new BasicDBObject();
- BasicDBObject set = new BasicDBObject();
- set.put("val", 0);
- set.put("maxval", LOOP_COUNT);
- upd.put("$set", set);
- db.getCollection("counters").update(q, upd);
- Thread[] threads = new Thread[THREAD_COUNT];
- final int[][] results = new int[THREAD_COUNT][LOOP_COUNT];
- for (int i = 0; i < THREAD_COUNT; i++) {
- final int temp_i = i;
- threads[i] = new Thread("" + i) {
- @Override
- public void run() {
- try {
- Mongo mongoClient = new Mongo("172.17.2.100", 27017);
- DB db = mongoClient.getDB("im");
- db.authenticate("imadmin", "imadmin".toCharArray());
- for (int j = 0; j < LOOP_COUNT; j++) {
- Object result = db.eval("getNextUniqueSeq(\"UNIQUE_KEY\")");
- System.out.printf("Thread %s, seq=%d\n", Thread.currentThread().getName(), ((Double) result).intValue());
- results[temp_i][j] = ((Double) result).intValue();
- }
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- }
- };
- }
- for (Thread thread : threads) {
- thread.start();
- }
- for (Thread thread : threads) {
- thread.join();
- }
- for (int num = 1; num <= LOOP_COUNT; num++) {
- // every number appear 20 times only!
- int times = 0;
- for (int j = 0; j < THREAD_COUNT; j++) {
- for (int k = 0; k < LOOP_COUNT; k++) {
- if (results[j][k] == num)
- times++;
- }
- }
- assertEquals(20, times);
- }
- }
榪欎釜嫻嬭瘯璺戜簡鍑犳閮芥槸姝g‘鐨勩?/p>
鐢變簬娌℃湁鍙互榪涜瀵規(guī)瘮鍏朵粬鐨勫疄鐜版柟寮忥紙渚嬪鎺掍粬閿侊級鎵浠ユ病鏈夊仛鎬ц兘嫻嬭瘯銆?/p>
鍐欏湪鏈鍚庛?铏界劧MongoDB鏀寔綾諱技浜庡瓨鍌ㄨ繃紼嬬殑Stored Javascript錛屼絾鏄叾瀹炰笉寤鴻浣跨敤榪欎釜鏉ヨВ鍐沖鏉傞棶棰樸備富瑕佸師鍥犳槸娌℃硶璋冭瘯錛岀淮鎶よ搗鏉ュお涓嶆柟渚褲傝屼笖鍦?.4涔嬪墠MongoDB瀵規(guī)湇鍔$ Javascript鏀寔騫朵笉鏄緢濂斤紝 涓涓猰ongod榪涚▼鍚屾椂鍙兘鎵ц涓孌礘avascript銆傚鏋滆兘鍦ㄥ簲鐢ㄥ眰瑙e喅鎺夎繕鏄湪搴旂敤灞傞噷瀹炵幇閫昏緫姣旇緝濂姐?/p>