Mongo Cursor


簡介

在使用 Java 對數據庫進行連接時,都會獲取到一個 cursor ,cursor 實際指到的是我們查詢數據庫的query,而並不是 query 查詢到的數據集。

此次在使用 mongo 的 cursor 的過程中,對線上數據庫產生了很大壓力,在這里對此次的優化過程進行記錄。

場景

數據源:Mongo 數據庫 4台服務器 4000+表 總共3億+數據量

背景介紹:即將建立大數據平台,需要將數據源的數據導入到 hbase 中,分為歷史數據導入和實時 opLog 數據導入兩部分

方案:

  1. 多線程歷史數據導入
  2. 多線程實時數據導入

問題描述:

  1. 導入的數據占據資源
    1. 硬盤資源 計算需要占用的硬盤資源,事先確認硬盤資源是否充足
    2. CPU 確認運行腳本的服務器處於半空閑狀態
    3. 內存 運行jar包時的腳本配置內存即可
  2. 對線上數據庫的連接沒有釋放,導致線上數據庫壓力
    1. 歷史數據導入時,每個線程都會新建連接,之后關閉 #可能沒有關閉
    2. 實時數據導入時,輪詢產生連接,但是關閉時間較長,導致的連接數增長 #關閉時長較長

解決方法:

  1. 歷史數據導入時的每個線程所建立的連接,修改邏輯,使其一定被關閉
  2. 實時數據導入時的每個線程的讀取 opLog 的 cursor ,使其保持活性
  3. 創建連接池,確保連接數在一定時間內

知識點

cursor

cursor的獲取:find() 方法返回的是一個 FindIterable 對象,對此對象的控制即可對 cursor 的屬性進行控制,根據FindIterable獲取一個Cursor 。

1)batchSize(int size):每次網絡請求返回的document條數,比如你需要查詢500條數據,mongodb不會一次性全部load並返回給client,而是每次返回batchSize條,遍歷完之后后再通過網路IO獲取直到cursor耗盡。默認情況下,首次批量獲取101個document或者1M的數據,此后每次4M,當然我們可以通過此方法來覆蓋默認值,如果文檔尺寸較小,則建議batchSize可以大一些。

2)skip(int number)、limit(int number):同SQL中的limit字句,即表示在符合匹配規則的結果集中skip一定數量的document,並最終返回limit條數據。可以實現分頁查詢。

3)maxTime(int time,TimeUnit unit):表示此次操作保持的最長時間,即server端保持cursor狀態的最長時間,如果超時server端將移除此cursor,即再次通過此cursor遍歷數據將會error。

4)sort(Bson bson):根據指定field排序,參與排序的字段最好是索引,如果不是,將會在內存中排序,如果參與排序的數據尺寸大於32M,將會拋出error。1表示正序,-1表示倒敘,比如"age":1表示按照age正序排序。

5)noCursorTimeout(boolean timeout):如果cursor空閑一定時間后(10分鍾),server端是否將其移除,默認為false,即server會將空閑10分鍾的cursor移除以節約內存。如果為true,則表示server端不需要移除空閑的cursor,而是等待用戶手動關閉。無論如何,開發者都需要注意,手動關閉cursor。

6)partial(boolean partial):對於sharding集群,如果一個或者多個shard不可達,是否允許返回部分數據(只從正常的shard中獲取數據)。

7)cursorType():指定cursor類型,當cursor遍歷完畢后是否關閉cursor,默認是關閉,無論何時都建議手動關閉cursor(不管是否耗盡curosr);當然有些開發場景可能需要保持cursor的活性,遍歷到cursor的最后一條后,不關閉cursor,繼續等待,此后一段時間內如果有新數據插入到cursor之后,則可以繼續遍歷,這就是Tailable Cursor,通常對於Capped Collection中使用。目前支持支持3種類型的Cursor:NonTailable、Tailable、TailableAwait。

8)projection(Bson bson):限定返回結果中需要包含的filed或者數組元素。在6)中我們已經看到相關的幾個例子。默認情況下,將會返回document的所有字段,1表示包含,0表示不包含。

連接池

Mongo Client本身即是一個連接池,有默認參數,也可以自己設置參數,建議全局使用同一個mongo的client實例。

NOTE: 連接池里的連接數 = ConnectionsPerHost * threadsAllowedToBlockForConnectionMultiplier

參數說明:來自於http://api.mongodb.com/java/3.2/

com.mongodb

Class MongoClientOptions.Builder

參數名 默認參數值 參數說明
ConnectionsPerHost 100 設置每台主機的最大連接數
Description null
RequiredReplicaSetName null 設置群集所需的副本集名稱
ConnectTimeout 10000 設置連接超時
HeartbeatConnectTimeout 20000 設置用於群集心跳的連接的連接超時
HeartbeatFrequency 10000 設置心跳頻率。這是驅動程序嘗試確定群集中每個服務器當前狀態的頻率。默認值為10,000毫秒
HeartbeatSocketTimeout 20000 設置用於群集心跳的連接的套接字超時
LocalThreshold 15 設置本地閾值
MaxConnectionIdleTime 0 設置池連接的最大空閑時間
MaxConnectionLifeTime 0 設置池連接的最長生存期
MaxWaitTime 120000 設置線程阻塞等待連接的最長時間
MinConnectionsPerHost 0 設置每台主機的最小連接數
MinHeartbeatFrequency 500 設置最小心跳頻率。如果驅動程序必須頻繁地重新檢查服務器的可用性,它至少會在上次檢查后等待這么長時間,以避免浪費精力。默認值為500毫秒
ServerSelectionTimeout 30000 以毫秒為單位設置服務器選擇超時,這定義了驅動程序在引發異常之前等待服務器選擇成功的時間。 值0表示如果沒有服務器可用,它將立即超時。負值意味着無限期等待。
SocketTimeout 0 設置socket超時
threadsAllowedToBlockForConnectionMultiplier 5 設置允許阻塞等待連接的線程數的乘數。
socketKeepAlive 設置是否啟用套接字保持活動
sslEnabled 設置是否使用SSL。將此設置為true也會將SocketFactory設置為sLSocketFactory。GetDefault ( )並將此設置為false會將SocketFactory設置為SocketFactory。GetDefault ( )
sslInvalidHostNameAllowed 定義是否允許無效主機名。默認為false。在將此設置為真之前要小心,因為這會使應用程序容易受到中間人攻擊
readPreference 設置讀取首選項
writeConcern 設置寫入關注點。
readConcern 設置讀取關注點。
codecRegistry 設置編解碼器注冊表
請注意,DB和DBCollection的實例不使用注冊表,因此無需在注冊表中包含DBObject的編解碼器。
addCommandListener 添加給定的命令偵聽器。
socketFactory 設置socket工廠。
cursorFinalizerEnabled 設置是否啟用游標終結器
alwaysUseMBeans 設置驅動程序注冊的JMX Beans是否應該始終是MBean,而不管VM是Java 6還是更高版本。如果為false,如果虛擬機為Java 6或更高版本,驅動程序將使用MXBeans,如果虛擬機為Java 5,則使用mbean。
dbDecoderFactory 設置解碼器工廠
dbEncoderFactory 設置編碼器工廠
legacyDefaults 將默認值設置為MongoOptions中的值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM