升級mongo3.2.1後遇到的數據重複的問題

因爲5分鐘的uv數據1分鐘更新一次mongo,

所以使用了mongo的update方法(db.collection.update(query,update,true,false)),

設置第三個參數upsert爲true,以實現數據不存在的時候直接寫入,存在的時候更新的場景。

最近,在由mongo3.0.7升級到mongo3.2.1之後,發現,同樣查詢條件的數據,存在重複的情況。比如id=x是查詢條件,根據update方法,找這條數據,往後面添加別的字段,如果那個字段已經存在,就往上面累加值,如果那個字段不存在,就加進去,如果找不到id=x的數據就直接插入,也就是id=x這個條件的數據,始終只有一條。可實際卻出現了多條數據。

 

通過java代碼起兩個線程調用update的api,在表中不存在符合查詢條件的數據的前提下,針對mongo3.2.1操作的時候,偶爾會發生符合更新條件的數據,寫入兩條的情況;針對mongo3.0.7在相同的測試次數下,未發生寫入兩條的情況。

 

public  void run(){
    try {
        MongoURI uri = new MongoURI("mongodb://IP地址:端口號/test");
        Mongo mongo = newMongo(uri);
        DB db = mongo.getDB(uri.getDatabase());
        DBCollection collection = db.getCollection("test1");

        BasicDBObject query = new BasicDBObject();
        query.put("ts", Long.valueOf("1455426000000"));
        query.put("lid", "102016021");
        query.put("type", "uv");

        String p1="pc";
        DBObject mappedUpdateObject =BasicDBObjectBuilder.start().push("$inc").add(p1,2).get();


        collection.update(query,mappedUpdateObject, true,false);

        mongo.close();
    } catch (Exception e) {
        // Die fast
       
throw new RuntimeException(e);
    }
}

 

 

publicstatic void main(String[]args){
    Test7 m=new Test7();//本類的名字
    Test5 n=new Test5();//功能相同的另外一個類,只不過,要寫入的數據有差別,pc改成mobile,或者2改成3這樣
    Thread t1 = new Thread(m);
    Thread t2= new Thread(n);
    t1.start();
    t2.start();

}

執行結果,在3.0.7的mongo上,不管起幾個線程,結果始終只有一條。

而在3.2.1上,有時候是多條,有時候是一條。

根據網上搜索的資料,找到一個遇到類似情況的人,有人拋出一段mongo文檔,

If all update() operations complete the query portionbefore any client successfully inserts data,and there is no uniqueindex on the name field, then each update operation may perform an insert.

 

指明瞭可能會發生此類問題,規避的措施是,在查詢條件上建立唯一索引,

試着建了另外一張表,在lid,ts,type上建了唯一索引,

發現數據是不會重複多條了,但是是在偶發多條的時候,只有一條成功寫入,另外一條不是更新上去,而是扔掉了。

 

以下爲在網絡上找到的資料:

在用C++MongoDB執行update操作的時候,如果設置了upsert參數爲true,則會自動插入不存在的數據。在高併發環境下,會導致數據重複。

解決方法是爲查詢條件添加unique index,參考官方文檔:

http://docs.mongodb.org/manual/core/write-operations-atomicity/

http://docs.mongodb.org/manual/core/index-unique/#index-type-unique

 

經過高壓測試後,證明這個解決方案是靠譜的。

 


作者:達一夫
鏈接:http://www.zhihu.com/question/21703021/answer/20694219
來源:知乎

木有人回答,我自己來答吧。
首先mongodb的文檔有解釋:
If all update() operations complete the query portion before any clientsuccessfully inserts data,and there is no unique index on the namefield, then each update operation may perform an insert.

但這個解釋不完全,在當前文檔已經存在的情況下,多併發upsert,也可能插入多條,並且我們驗證了這個可能性的存在。

嗯。。。我再添加一個問題吧。
find到的數據可能不是最新的,下一次find纔是,這造成我們一些詭異的問題。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章