主頁 > 資料庫 > MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理

MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理

2020-09-14 13:51:01 資料庫

MongoDB 是一個基于分布式檔案存盤的資料庫,由 C++ 語言撰寫,一般生產上建議以共享分片的形式來部署, 但是MongoDB官方也提供了其它語言的客戶端操作API,如下圖所示:

提供了C、C++、C#、.net、GO、java、Node.js、PHP、python、scala等各種語言的版本,如下圖所示:

MongoDB的操作分為同步操作和異步操作以及回應式編程操作
一、同步操作API

官方JAVA API的路徑:https://docs.mongodb.com/ecosystem/drivers/java/  我們這里以3.11的java 版本為例,各個版本的API對MongoDB服務的支持情況,

使用API時,先引入maven依賴

<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.11.1</version>
</dependency>

  

 1、關于MongoDB Client的初始化和關閉,

從官方介紹來看,一般建議Client只需要一個建立一個長連接實體,然后使用時,都使用這個實體就可以,也就是可以用java的單例模式來創建連接實體,

 

//mongoClient連接
protected static MongoClient mongoClient;
 public synchronized static MongodbClient getInstance(String mongodbUrl) {
        if (null == mongoClient) {
            mongoClient = MongoClients.create(mongodbUrl);
            if(null != mongoClient){
                log.info("mongoClient init success!");
            }
            else{
                log.info("mongoClient init failed!");
            }
        }
        return mongodbClient;
    } 

  

直接通過mongodb的host和port來創建client: 

MongoClient mongoClient = MongoClients.create("mongodb://host1:27017");

client連接到一個 Replica Set:

本文作者:張永清,轉載請注明出處:MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理

MongoClient mongoClient = MongoClients.create("mongodb://host1:27017,host2:27017,host3:27017");

MongoClient mongoClient = MongoClients.create("mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myReplicaSet");

 或者通過MongoClientSettings.builder() 來輔助生成連接字串來創建client:

MongoClient mongoClient = MongoClients.create( MongoClientSettings.builder() .applyToClusterSettings(builder -> builder.hosts(Arrays.asList( new ServerAddress("host1", 27017), new ServerAddress("host2", 27017), new ServerAddress("host3", 27017)))) .build());

  連接關閉:

    public void close() {
        if(null!=mongoClient){
            mongoClient.close();
            mongoClient=null;
        }
    }

  2、關于MongoDB 的基本操作

//創建Collection

public void createCollection(String dataBaseName,String collectionName){ getDatabase(dataBaseName).createCollection(collectionName); }
//查詢
dataBaseName
public MongoDatabase getDatabase(String dataBaseName){ return mongoClient.getDatabase(dataBaseName); }
//查詢
Collection
public List<String> listCollectionNames(String dataBaseName){
List
<String> stringList = new ArrayList<String>();
mongoClient.getDatabase(dataBaseName).listCollectionNames().forEach((Consumer
<? super String>) t->{ stringList.add(t); });
return stringList; }

public MongoCollection<Document> getCollectionByName(String dataBaseName, String collectionName){ return getDatabase(dataBaseName).getCollection(collectionName); }

 3、關于MongoDB 的查詢操作

    //通過id(objectid)精確查詢
	public FindIterable<Document>  findMongoDbDocById(String dataBaseName, String collectionName, String id){
        BasicDBObject searchDoc = new BasicDBObject().append("_id", id);
       return getCollectionByName(dataBaseName,collectionName).find(searchDoc);
    }
    //通過id(objectid)模糊查詢
    public FindIterable<Document>  findMongoDbDocByIdRegex(String dataBaseName, String collectionName, String id){
        BasicDBObject searchDoc = new BasicDBObject().append("_id", new BasicDBObject("$regex",id));
        return getCollectionByName(dataBaseName,collectionName).find(searchDoc);
    }
	//通過開始id和結束id 查詢(根據objectId范圍查詢)
    public FindIterable<Document>  findMongoDbDocById(String dataBaseName, String collectionName, String startId,String endId){
        BasicDBObject searchDoc = new BasicDBObject().append("_id", new BasicDBObject("$gte", startId).append("$lte", endId));
        return getCollectionByName(dataBaseName,collectionName).find(searchDoc);
    }
    public FindIterable<Document> findMongoDbDoc(String dataBaseName, String collectionName,BasicDBObject basicDBObject){
        return getCollectionByName(dataBaseName,collectionName).find(basicDBObject);
    }
	//限制查詢回傳的條數
    public FindIterable<Document> findMongoDbDoc(String dataBaseName, String collectionName,BasicDBObject basicDBObject,Integer limitNum){
        return findMongoDbDoc(dataBaseName,collectionName,basicDBObject).limit(limitNum) ;
    }
    public FindIterable<Document>  findMongoDbDocById(String dataBaseName, String collectionName, String startId,String endId,Integer limitNum){
        return findMongoDbDocById(dataBaseName,collectionName,startId,endId).limit(limitNum);
    }

    /**
     * 降序查詢(排序)
     * @param dataBaseName
     * @param collectionName
     * @param startId
     * @param endId
     * @param sortField  排序欄位
     * @return
     */
    public FindIterable<Document>  findMongoDbDocByIdDescSort(String dataBaseName, String collectionName, String startId,String endId,String sortField){
      return findMongoDbDocById(dataBaseName,collectionName,startId,endId).sort(new Document().append(sortField, -1));
    }
    public FindIterable<Document>  findMongoDbDocByIdDescSort(String dataBaseName, String collectionName, String startId,String endId,String sortField,Integer limitNum){
        return findMongoDbDocByIdDescSort(dataBaseName,collectionName,startId,endId,sortField).limit(limitNum);
    }

    /**
     * 降序查詢(排序)
     * @param dataBaseName
     * @param collectionName
     * @param startId
     * @param endId
     * @param sortField  排序欄位
     * @return
     */
    public FindIterable<Document>  findMongoDbDocByIdAscSort(String dataBaseName, String collectionName, String startId,String endId,String sortField){
        return findMongoDbDocById(dataBaseName,collectionName,startId,endId).sort(new Document().append(sortField, 1));
    }
    public FindIterable<Document>  findMongoDbDocByIdAscSort(String dataBaseName, String collectionName, String startId,String endId,String sortField,Integer limitNum){
        return findMongoDbDocByIdAscSort(dataBaseName,collectionName,startId,endId,sortField).limit(limitNum);
    }

   4、關于MongoDB 的插入操作

   //插入操作,注意插入時,如果資料已經存在會報錯,插入時必須資料不存在,不會自動進行覆寫
   //插入單條記錄   
   public void insertDoc(String dataBaseName, String collectionName, Document document){
        getCollectionByName(dataBaseName,collectionName).insertOne(document);
    }
	//插入多條記錄
    public void insertDoc(String dataBaseName, String collectionName,List<? extends Document> listData){
        getCollectionByName(dataBaseName,collectionName).insertMany(listData);
    }

   5、關于MongoDB 的更新操作

	//更新單條
    public void updateDoc(String dataBaseName, String collectionName, Bson var1, Bson var2){
        getCollectionByName(dataBaseName,collectionName).updateOne(var1,var2);
    }
    public void updateDoc(String dataBaseName, String collectionName, Bson var1, List<? extends Bson> list){
        getCollectionByName(dataBaseName,collectionName).updateOne(var1,list);
    }
	//批量更新
    public void updateDocs(String dataBaseName, String collectionName, Bson var1, Bson var2){
        getCollectionByName(dataBaseName,collectionName).updateMany(var1,var2);
    }
    public void updateDocs(String dataBaseName, String collectionName, Bson var1, List<? extends Bson> list){
        getCollectionByName(dataBaseName,collectionName).updateMany(var1,list);
    }

  6、關于MongoDB 的洗掉操作 

//單條洗掉  
  public DeleteResult deleteDoc(String dataBaseName, String collectionName, Bson var1){
        return getCollectionByName(dataBaseName,collectionName).deleteOne(var1);
    }
//批量洗掉	
    public DeleteResult deleteDocs(String dataBaseName, String collectionName,Bson var1){
       return getCollectionByName(dataBaseName,collectionName).deleteMany(var1);
    }

7、關于MongoDB 的替換操作

本文作者:張永清,轉載請注明出處:MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理

//存在就替換,不存在的話就插入
public UpdateResult replaceDoc(String dataBaseName, String collectionName, Bson var1, Document var2,ReplaceOptions var3){
    return getCollectionByName(dataBaseName,collectionName).replaceOne(var1,var2,var3);
}
public UpdateResult replaceDoc(String dataBaseName, String collectionName, Bson var1, Document var2){ return getCollectionByName(dataBaseName,collectionName).replaceOne(var1,var2); }
//呼叫示例(設定存在就替換,不存在的話就插入)
                            Document documentQuery = new Document("_id", docId);
                            Document document = new Document("_id", docId);
                            ReplaceOptions replaceOptions = new ReplaceOptions();
                            replaceOptions.upsert(true);
String dataBaseName="zhangyonqing";
String collectionName="zhangyonqing";
replaceDoc(dataBaseName,collectionName,documentQuery,document,replaceOptions);

  

8、關于MongoDB 的bulkWrite操作 (批量寫入),對于資料很多時,效率很高

    public BulkWriteResult bulkWrite(String dataBaseName, String collectionName, List<? extends WriteModel<? extends Document>> listData){
       return getCollectionByName(dataBaseName,collectionName).bulkWrite(listData);
    }

 9、關于MongoDB 的分頁查詢

mongodb的分頁查詢可以有多種思路來實作,

思路一:采用類似mysql的limit start end 的這種,

獲取到總的數量:

    //查詢總數
    public long countDocs(String dataBaseName, String collectionName,Bson var1){
        if(null==var1){
            return getCollectionByName(dataBaseName,collectionName).countDocuments();
        }
       return getCollectionByName(dataBaseName,collectionName).countDocuments(var1);
    }

//  分頁查詢,采用skip+limit的方式,在用了總數后,就可以分頁了,skip的意思是前面跳過多少資料,但是這種方式在資料量大的時候效率不高,因為skip會導致全表掃描,

    public FindIterable<Document> findMongoDbDoc(String dataBaseName, String collectionName,BasicDBObject basicDBObject,Integer skip,Integer limit){
        return getCollectionByName(dataBaseName,collectionName).find(basicDBObject).skip(skip).limit(limit);
    }

思路二:利用limit 以及排序的方式,獲取分頁的上一頁的最后一條記錄的objectId,然后使用排序+$gte操作(大于)+limit 來獲取當頁的資料,找到一個可以排序的欄位,比如objectId或者時間欄位都可以排序,這個也是mongodb官方推薦的方式,這種做飯可以避免全表掃描,

思路三:在資料量不大的時候,使用代碼進行分頁,比如從mongodb中查詢出一個list物件后,對list物件做代碼分頁,

public class ListUtil {
    public static List getPagingList(List list,Integer start,Integer length){
        start = start<0?0:start;
        //默認為10
        length = length<=0?10:length;
        Integer size = list.size();
        if(start>size){
            start = size;
        }
        Integer toIndex = (start+length-1)>=size?size:(start+length-1);
        if(toIndex<=0){
            toIndex = size;
        }
        return list.subList(start,toIndex);
    }

  

二、異步操作API  

 mongodb異步驅動程式提供了異步api,可以利用netty或java 7的asynchronoussocketchannel實作快速、無阻塞的i/o,maven依賴

<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>3.11.1</version>
</dependency>
</dependencies>

官方地址:http://mongodb.github.io/mongo-java-driver/3.11/driver-async/getting-started/installation/

異步操作必然會涉及到回呼,回呼時采用ResultCallback<Document>

本文作者:張永清,轉載請注明出處:MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理

SingleResultCallback<Document> callbackPrintDocuments = new SingleResultCallback<Document>() {
   @Override
   public void onResult(final Document document, final Throwable t) {
       System.out.println(document.toJson());
   }
};

SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
    @Override
    public void onResult(final Void result, final Throwable t) {
        System.out.println("Operation Finished!");
    }
};

  異步insert操作

collection.insertMany(documents, new SingleResultCallback<Void>() {
    @Override
    public void onResult(final Void result, final Throwable t) {
        System.out.println("Documents inserted!");
    }
});

  異步洗掉操作

collection.deleteMany(gte("i", 100), new SingleResultCallback<DeleteResult>() {
    @Override
    public void onResult(final DeleteResult result, final Throwable t) {
        System.out.println(result.getDeletedCount());
    }
});

  異步更新操作

collection.updateMany(lt("i", 100), inc("i", 100),
    new SingleResultCallback<UpdateResult>() {
        @Override
        public void onResult(final UpdateResult result, final Throwable t) {
            System.out.println(result.getModifiedCount());
        }
    });

  異步統計操作

collection.countDocuments(
  new SingleResultCallback<Long>() {
      @Override
      public void onResult(final Long count, final Throwable t) {
          System.out.println(count);
      }
  });

  

三、MongoDB Reactive Streams 操作API

官方的MongoDB reactive streams Java驅動程式,為MongoDB提供異步流處理和無阻塞處理,

完全實作reactive streams api,以提供與jvm生態系統中其他reactive streams的互操作,一般適合于大資料的處理,比如spark,flink,storm等,

<dependencies>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-reactivestreams</artifactId>
        <version>1.12.0</version>
    </dependency>
</dependencies>

  官方地址:http://mongodb.github.io/mongo-java-driver-reactivestreams/

會包含如下三部分:

  1. Publisher:Publisher 是資料的發布者,Publisher 介面只有一個方法 subscribe,用于添加資料的訂閱者,也就是 Subscriber,
  2. Subscriber: 是資料的訂閱者,Subscriber 介面有4個方法,都是作為不同事件的處理器,在訂閱者成功訂閱到發布者之后,其 onSubscribe(Subscription s) 方法會被呼叫,
  3. Subscription:表示的是當前的訂閱關系,

API問的地址:http://mongodb.github.io/mongo-java-driver-reactivestreams/1.12/javadoc/

 

 

 

代碼示例:

//建立連接
MongoClient mongoClient = MongoClients.create(mongodbUrl);
//獲得資料庫物件
MongoDatabase database = client.getDatabase(databaseName);
//獲得集合
MongoCollection collection = database.getCollection(collectionName);

//異步回傳Publisher
FindPublisher publisher = collection.find();

//訂閱實作
publisher.subscribe(new Subscriber() {
    @Override
    public void onSubscribe(Subscription str) {
        System.out.println("start...");
        //執行請求
        str.request(Integer.MAX_VALUE);
    }
    @Override
    public void onNext(Document document) {
        //獲得檔案
        System.out.println("Document:" + document.toJson());
    }

    @Override
    public void one rror(Throwable t) {
        System.out.println("error occurs.");
    }

    @Override
    public void onComplete() {
        System.out.println("finished.");
    }
});

個人github參考代碼:https://github.com/597365581/bigdata_tools/tree/master/yongqing-bigdata-tools/yongqing-mongodb-tool

、MongoDB 共享分片模式安裝

這里以mongodb4.2.0版本和作業系統CentOS Linux release 7.6.1810 (Core) 為例:

1、從官網下載mongodb-linux-x86_64-rhel7的安裝包,

分片模式安裝包括三部分:shard、config、router 

MongoDB分片模式下的架構圖如下:

 (1)mongos :資料路由,和客戶端打交道的模塊,mongos本身沒有任何資料,他也不知道該怎么處理這資料,去找config server

(2)config server:所有存、取資料的方式,所有shard節點的資訊,分片功能的一些配置資訊,可以理解為真實資料的元資料,

 (3)shard:真正的資料存盤位置,以chunk為單位存資料,

Mongos本身并不持久化資料,Sharded cluster所有的元資料都會存盤到Config Server,而用戶的資料會分散存盤到各個shard,Mongos啟動后,會從配置服務器加載元資料,開始提供服務,將用戶的請求正確路由到對應的碎片,

Mongos的路由功能

  當資料寫入時,MongoDB Cluster根據分片鍵設計寫入資料,

  當外部陳述句發起資料查詢時,MongoDB根據資料分布自動路由至指定節點回傳資料,

 分片的主要目的:

高資料量和吞吐量的資料庫應用會對單機的性能造成較大壓力,大的查詢量會將單機的CPU耗盡,大的資料量對單機的存盤壓力較大,最侄訓耗盡系統的記憶體而將壓力轉移到磁盤IO上,

  為了解決這些問題,有兩個基本的方法: 垂直擴展和水平擴展,

    垂直擴展:增加更多的CPU和存盤資源來擴展容量,

    水平擴展:將資料集分布在多個服務器上,水平擴展即分片,

分片設計思想:

分片為應對高吞吐量與大資料量提供了方法,使用分片減少了每個分片需要處理的請求數,因此,通過水平擴展,集群可以提高自己的存盤容量和吞吐量,舉例來說,當插入一條資料時,應用只需要訪問存盤這條資料的分片,使用分片減少了每個分片存盤的資料,

分片的好處:

1.對集群進行抽象,讓集群“不可見”:

  MongoDB自帶了一個叫做mongos的專有路由行程,mongos就是掌握統一路口的路由器,其會將客戶端發來的請求準確無誤的路由到集群中的一個或者一組服務器上,同時會把接收到的回應拼裝起來發回到客戶端,

2.保證集群總是可讀寫:

  MongoDB通過多種途徑來確保集群的可用性和可靠性,將MongoDB的分片和復制功能結合使用,在確保資料分片到多臺服務器的同時,也確保了每分資料都有相應的備份,這樣就可以確保有服務器換掉時,其他的從庫可以立即接替壞掉的部分繼續作業,

3.使集群易于擴展:

  當系統需要更多的空間和資源的時候,MongoDB使我們可以按需方便的擴充系統容量,

2、部署shard,這里我們部署3個shard

創建shard1.config 組態檔,檔案內容:

#資料路徑

dbpath=/data3/mongodb/data/shard1

#日志路徑
logpath=/opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/logs/shard1.log
port=37017
logappend=true

#是否后臺運行
fork=true
quiet=true
journal=true
shardsvr=true
replSet=shard1RS/10.100.xx.xx:37017
bind_ip=0.0.0.0

創建shard2.config 組態檔,檔案內容:

dbpath=/data1/mongodb/data/shard2
logpath=/opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/logs/shard2.log
port=47017
logappend=true
fork=true
quiet=true
journal=true
shardsvr=true
replSet=shard2RS/10.100.xx.xx:47017
bind_ip=0.0.0.0

創建shard3.config 組態檔,檔案內容:

 

dbpath=/data1/mongodb/data/shard3
logpath=/opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/logs/shard3.log
port=57017
logappend=true
fork=true
quiet=true
journal=true
shardsvr=true
replSet=shard3RS/10.100.xx.xx:57017
bind_ip=0.0.0.0

分別啟動上面的3個共享分片

啟動方式:mongod -f 組態檔對應的路徑

mongod -f /opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/shard1.config

mongod -f /opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/shard2.config

mongod -f /opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/shard/shard3.config

如果需要限制記憶體的大小,可以在啟動引數后面增加--wiredTigerCacheSizeGB 0.2   ,這里的0.2 代表快取的大小,

關于MongoDB快取的介紹:

With WiredTiger, MongoDB utilizes both the WiredTiger internal cache and the filesystem cache.

Starting in MongoDB 3.4, the default WiredTiger internal cache size is the larger of either:

  • 50% of (RAM - 1 GB), or
  • 256 MB.

For example, on a system with a total of 4GB of RAM the WiredTiger cache will use 1.5GB of RAM (0.5 (4 GB GB) 1.5 GB). Conversely, a system with a total of 1.25 GB of RAM will allocate 256 MB to the WiredTiger cache because that is more than half of the total RAM minus one gigabyte (0.5 (1.25 GB GB) 128 MB 256 MB).

By default, WiredTiger uses Snappy block compression for all collections and prefix compression for all indexes. Compression defaults are configurable at a global level and can also be set on a per-collection and per-index basis during collection and index creation.

Different representations are used for data in the WiredTiger internal cache versus the on-disk format:

  • Data in the filesystem cache is the same as the on-disk format, including benefits of any compression for data files. The filesystem cache is used by the operating system to reduce disk I/O.
  • Indexes loaded in the WiredTiger internal cache have a different data representation to the on-disk format, but can still take advantage of index prefix compression to reduce RAM usage. Index prefix compression deduplicates common prefixes from indexed fields.
  • Collection data in the WiredTiger internal cache is uncompressed and uses a different representation from the on-disk format. Block compression can provide significant on-disk storage savings, but data must be uncompressed to be manipulated by the server.

Via the filesystem cache, MongoDB automatically uses all free memory that is not used by the WiredTiger cache or by other processes.

To adjust the size of the WiredTiger internal cache, see storage.wiredTiger.engineConfig.cacheSizeGB and --wiredTigerCacheSizeGB. Avoid increasing the WiredTiger internal cache size above its default value.

NOTE

The storage.wiredTiger.engineConfig.cacheSizeGB limits the size of the WiredTiger internal cache. The operating system will use the available free memory for filesystem cache, which allows the compressed MongoDB data files to stay in memory. In addition, the operating system will use any free RAM to buffer file system blocks and file system cache.

To accommodate the additional consumers of RAM, you may have to decrease WiredTiger internal cache size.

The default WiredTiger internal cache size value assumes that there is a single mongod instance per machine. If a single machine contains multiple MongoDB instances, then you should decrease the setting to accommodate the other mongod instances.

If you run mongod in a container (e.g. lxccgroups, Docker, etc.) that does not have access to all of the RAM available in a system, you must set storage.wiredTiger.engineConfig.cacheSizeGB to a value less than the amount of RAM available in the container. The exact amount depends on the other processes running in the container. See memLimitMB.

To view statistics on the cache and eviction rate, see the wiredTiger.cache field returned from the serverStatus command.

更多資訊,可以參考http://docs.mongodb.com/manual/faq/diagnostics/#memory-diagnostics-for-the-wiredtiger-storage-engine

3、部署config,這里我們部署1個config

創建mongo.config組態檔,檔案內容:

dbpath=/data3/mongodb/config/data
logpath=/opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/config/logs/mongoconfig.log
port=27017
logappend=true
fork=true
quiet=true
journal=true
configsvr=true
replSet=configRS/10.100.xx.xx:27017
bind_ip=0.0.0.0
maxConns=100

啟動config :mongod -f  組態檔對應的路徑

mongod -f /opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/config/mongo.config

4、部署router,這里我們部署1個router

創建router.config組態檔,檔案內容:

logpath=/opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/router/logs/mongorouter.log
port=17017
logappend=true
fork=true
quiet=true
configdb=configRS/10.100.xx.xx:27017
bind_ip=0.0.0.0

啟動router:mongos -f 組態檔對應的路徑

mongos -f /opt/mongodb/mongodb-linux-x86_64-rhel70-4.2.0/router/router.config

5、 初始化shard server,配置每個shard的副本集

連接到每一臺共享分片

mongo 10.100.xx.xx:37017

備注有每個分片配置幾個副本集是可以自己選擇的,下面這個是配置1個副本集

rs.initiate({_id:"shard1RS",members:[{_id:1,host:"10.100.xx.xx:37017",priority:2},{_id:2,host:"192.168.xx.xx:37017"}]})

mongo 10.100.xx.xx:47017

rs.initiate({_id:"shard2RS",members:[{_id:1,host:"10.100.xx.xx:47017",priority:2},{_id:2,host:"192.168.xx.xx:47017"}]})

mongo 10.100.xx.xx:57017

rs.initiate({_id:"shard2RS",members:[{_id:1,host:"10.100.xx.xx:57017",priority:2},{_id:2,host:"192.168.xx.xx:57017"}]})

6、 配置分片

通過路由連接到mongo:mongo 10.100.xx.xx:17017   

連接成功后切換到admin模式:use admin 

添加對應的3個分片

db.runCommand({"addShard":"shard1RS/10.100.xx.xx:37017" ,"maxsize":1024}) 

db.runCommand({"addShard":"shard2RS/10.100.xx.xx2:47017" ,"maxsize":1024}) 

db.runCommand({"addShard":"shard3RS/10.100.xx.xx:57017" ,"maxsize":1024})

判斷當前是否是shard集群:db.runCommand({isdbgrid:1});

查看分片的狀態資訊:可用命令db.runCommand({listshards:1})

7、 其他操作

洗掉分片:

use admin

db.runCommand( { removeShard: "shard1RS" } )

給集群新增用戶:

 

首先使用帶有“userAdmin”角色的用戶登錄集群,執行如下命令

 

use admin
db.createUser(
  {
    "user" : "backupUser",
    "pwd" : "123",
    roles: [{role:"backup", db:"admin"}]
  }
)
db.auth("backupUser","123")  //使新增的用戶生效

 

至此,就完成了新增一個用戶備份整個集群的用戶

給集群用戶新增權限:

use admin

db.grantRolesToUser(
"pubUser",
[{role:"readWrite", db:"Philippines"},
{role:"readWrite", db:"Italy"},
{role:"readWrite", db:"India"},
{role:"readWrite", db:"Japan"}]
)

查詢所有DB的分片存盤資訊,包括chunks數、shard key資訊:

db.printShardingStatus()

獲取collection各個分片的資料存盤情況:

db.collection.getShardDistribution() 

顯示本mongos集群所有DB的資訊, 包含了Shard Key資訊:

sh.status()

僅顯示分片:

use config

db.shards.find()

balancer是sharded集群的負載均衡工具,新建集群的時候默認開啟,除非你在config里把它關閉掉:

db.settings.find()

手動啟動balancer:

sh.startBalancer()

判斷當前balancer是否在跑:

sh.isBalancerRunning()

 

 五、MongoDB 分片模式下如何選擇分片鍵

分片鍵shard key:

MongoDB中資料的分片是以集合為基本單位的,集合中的資料通過片鍵(Shard key)被分成多部分,其實片鍵就是在集合中選一個鍵,用該鍵的值作為資料拆分的依據,

  所以一個好的片鍵對分片至關重要,片鍵必須是一個索引,通過sh.shardCollection加會自動創建索引(前提是此集合不存在的情況下),一個自增的片鍵對寫入和資料均勻分布就不是很好,因為自增的片鍵總會在一個分片上寫入,后續達到某個閥值可能會寫到別的分片,但是按照片鍵查詢會非常高效,

  隨機片鍵對資料的均勻分布效果很好,注意盡量避免在多個分片上進行查詢,在所有分片上查詢,mongos會對結果進行歸并排序,

  對集合進行分片時,你需要選擇一個片鍵,片鍵是每條記錄都必須包含的,且建立了索引的單個欄位或復合欄位,MongoDB按照片鍵將資料劃分到不同的資料塊中,并將資料塊均衡地分布到所有分片中,

  為了按照片鍵劃分資料塊,MongoDB使用基于范圍的分片方式或者 基于哈希的分片方式,

注意:

分片鍵是不可變,

分片鍵必須有索引,

分片鍵大小限制512bytes,

分片鍵用于路由查詢,

MongoDB不接受已進行collection級分片的collection上插入無分片

鍵的檔案(也不支持空值插入)

 

以范圍為基礎的分片Sharded Cluster:

Sharded Cluster支持將單個集合的資料分散存盤在多shard上,用戶可以指定根據集合內檔案的某個欄位即shard key來進行范圍分片(range sharding),

 

 

  對于基于范圍的分片,MongoDB按照片鍵的范圍把資料分成不同部分,

  假設有一個數字的片鍵:想象一個從負無窮到正無窮的直線,每一個片鍵的值都在直線上畫了一個點,MongoDB把這條直線劃分為更短的不重疊的片段,并稱之為資料塊,每個資料塊包含了片鍵在一定范圍內的資料,在使用片鍵做范圍劃分的系統中,擁有”相近”片鍵的檔案很可能存盤在同一個資料塊中,因此也會存盤在同一個分片中,

基于哈希的分片:

分片程序中利用哈希索引作為分片的單個鍵,且哈希分片的片鍵只能使用一個欄位,而基于哈希片鍵最大的好處就是保證資料在各個節點分布基本均勻,

 

 

  對于基于哈希的分片,MongoDB計算一個欄位的哈希值,并用這個哈希值來創建資料塊,在使用基于哈希分片的系統中,擁有”相近”片鍵的檔案很可能不會存盤在同一個資料塊中,因此資料的分離性更好一些,

  Hash分片與范圍分片互補,能將檔案隨機的分散到各個chunk,充分的擴展寫能力,彌補了范圍分片的不足,但不能高效的服務范圍查詢,所有的范圍查詢要分發到后端所有的Shard才能找出滿足條件的檔案,

分片鍵選擇建議:

1、遞增的sharding key

資料檔案挪動小,(優勢)

因為資料檔案遞增,所以會把insert的寫IO永久放在最后一片上,造成最后一片的寫熱點,同時,隨著最后一片的資料量增大,將不斷的發生遷移至之前的片上,

2、隨機的sharding key

資料分布均勻,insert的寫IO均勻分布在多個片上,(優勢)

大量的隨機IO,磁盤不堪重荷,

3、混合型key

大方向隨機遞增,小范圍隨機分布,

為了防止出現大量的chunk均衡遷移,可能造成的IO壓力,我們需要設定合理分片使用策略(片鍵的選擇、分片演算法(range、hash))

分片注意:

   分片鍵是不可變、分片鍵必須有索引、分片鍵大小限制512bytes、分片鍵用于路由查詢,

   MongoDB不接受已進行collection級分片的collection上插入無分片鍵的檔案(也不支持空值插入)、

資料庫開啟分片:

在共享分片模式下,創建完資料庫后,需要對資料庫開啟分片功能,并對資料庫下的表的欄位指定分片演算法

通過路由連接到mongoDb后,使用use admin 切換到admin模式,

開啟資料庫分片的命令:db.runCommand({"enablesharding":"資料庫名稱"}) ,例如對對庫hdctest開啟分片 :db.runCommand({"enablesharding":"hdctest"}) 

對庫hdctest下的表person按欄位ID配置hash分片演算法 :db.runCommand({"shardcollection":"hdctest.person","key":{_id:'hashed'}})

對庫hdctest下的表person按欄位ID配置按照id升序或者降序配置分片演算法(升序和降序 用1和-1表示):

db.runCommand({shardcollection:"hdctest.person",key:{_id:1}})

另外需要注意的是:對表中按照欄位進行分片時,需要預先創建索引才能配置分片演算法(索引和分片演算法保持一致,對id進行分片,那么就對id創建索引),

按照id升序索引:db.person.createIndex( {"_id": 1},{"name":'idx_id'})

按照createTime 降序索引:db.person.createIndex( {"createTime": -1 },{"name":'idx_createTime'})

 六、MongoDB 如何創建索引

 

1.為普通欄位添加索引,并且為索引命名

db.集合名.createIndex( {"欄位名": 1 },{"name":'idx_欄位名'})

說明: (1)索引命名規范:idx_<構成索引的欄位名>,如果欄位名字過長,可采用欄位縮寫,

         (2)欄位值后面的 1 代表升序;如是 -1 代表 降序,

 

2.為內嵌欄位添加索引

db.集合名.createIndex({"欄位名.內嵌欄位名":1},{"name":'idx_欄位名_內嵌欄位名'})

 

3.通過后臺創建索引

db.集合名.createIndex({"欄位名":1},{"name":'idx_欄位名',background:true})

 

4:組合索引

db.集合名.createIndex({"欄位名1":-1,"欄位名2":1},{"name":'idx_欄位名1_欄位名2',background:true})

 

5.設定TTL 索引

db.集合名.createIndex( { "欄位名": 1 },{ "name":'idx_欄位名',expireAfterSeconds: 定義的時間,background:true} )

  說明 :expireAfterSeconds為過期時間(單位秒)  

 

6.createIndex() 接收可選引數匯總

Parameter Typ Description
background Boolean 建索引程序會阻塞其它資料庫操作,background可指定以后臺方式創建索引,即增加 "background" 可選引數, "background" 默認值為false
unique Boolean 建立的索引是否唯一,指定為true創建唯一索引,默認值為false.
name string 索引的名稱,如果未指定,MongoDB的通過連接索引的欄位名和排序順序生成一個索引名稱,
sparse Boolean 對檔案中不存在的欄位資料不啟用索引;這個引數需要特別注意,如果設定為true的話,在索引欄位中不會查詢出不包含對應欄位的檔案.,默認值為 false.
expireAfterSeconds integer 指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間,
weights document 索引權重值,數值在 1 到 99,999 之間,表示該索引相對于其他索引欄位的得分權重,
default_language string 對于文本索引,該引數決定了停用詞及詞干和詞器的規則的串列, 默認為英語
本文作者:張永清,轉載請注明出處:MongoDB Java API操作很全的整理以及共享分片模式下的常見操作整理   最近發現很多不同的網站轉載作者的文章不注明出處,作者將追究法律責任,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/35513.html

標籤:NoSQL

上一篇:redis系列之------物件

下一篇:基于Redis實作分布式鎖

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more