天天看點

MongoDB基礎問題及使用方式

                     這是在學習MongoDB時網上找的一篇不錯的文檔,做為儲存。

1.linux 系統:

1】關閉檔案系統/分區的atime 選項

Vi /etc/fstab

在對應的分區項後面添加noatime ,nodiratime

LABEL=/1 / ext3 defaults 1 1

LABEL=/data1 /data ext4 defaults,noatime,nodiratime 1 2

2】設定檔案句柄4k+,目前該配置已經內建到啟動腳本中。

Vi /etc/security/limit.conf

* soft nproc 65536

* hard nproc 65536

* soft nofile 65536

* hard nofile 65536

3】不要使用large vm page (不要使用大記憶體頁選項)

Linux 大記憶體頁參考:http://linuxgazette.net/155/krishnakumar.html

4】用dmesg 檢視主機的資訊。

2.linux 檔案系統的選擇:

Mongodb 采用預配置設定的大檔案來存儲資料,我們推薦

1】ext4

2】xfs

3.核心版本:

網絡上對2.6.33-31 以及2.6.32 的表現持懷疑度, 而強力推薦2.6.36

4.線程堆棧的尺寸

預設的線程堆棧尺寸為10m ,調整為1m ,已經內建在啟動腳本中。

項目過程中的總結與建議

1.大小寫問題

mongodb 是預設區分大小寫的,但是這會不會衍生出跟mysql 一樣的問題?(mysql 區

分大小寫,導緻windows 與linux 下的表名,字段名不一緻)。

如果無特别用途,建議表名,字段名全部用小寫字母。

2.盡可能的縮短字段名的長度

mongodb 的schema free 導緻了每筆資料都要存儲他的key 以及屬性,這導緻了這些數

據的大量備援。開發同僚也許考慮到,從易讀性出發設計的key 基本比較長,基本都是按

照起字面意思去設計的。這導緻key 很長。對應的資料存儲占用了很大的空間。

必要的時候,可以考慮建立一個key 與實際意義的map 表,盡量降低key 的長度。

示例定義:

// 基本資訊

static final String _ID = "_id";

static final String STATUS_CODE = "sc";

// 緩沖

static final String DATE = "date";

static final String MAX_AGE = "age";

// 内容

static final String CONTENT = "content";

static final String CONTENT_TYPE = "ctype";

static final String CONTENT_LENGTH = "clen";

static final String ZIP = "zip";

3. mongodb 單表最大索引數為64

無索引排序的最大資料量為4M, 超過則報錯退出。

建議where 條件盡量落在索引字段上,排序字段需要建立索引,索引的使用原則與oracle

mysql 一緻,盡量降低索引數量,索引長度。

mongodb 的查詢每次隻能用到一個索引,對資料的查詢不會“并發”執行

例如: db.tab.find({'id'=1,'name'=2}) 如果‘id’,‘name' 列上分别有索引

對查詢效率提升意義不大,如果索引為('id','name') 則大幅提升效率。

4.mongodb 添加字段

如果添加字段且帶有default 值,需要全部資料都要修改,這也是設計階段需要考慮的

事情,這個問題的另外一種解法是應用代碼裡做一次判斷。

5.測試過程的密碼問題

對于用作資料庫使用的Mongodb,在代碼測試階段都應加上密碼驗證,目前上線階段基

本都會在密碼驗證方面出現問題(做緩存使用的可以不做密碼驗證)。

6.資料源連接配接方式

使用連接配接池模式,盡量減少認證帶來的性能額外消耗

建議采用标準的uri 連接配接方式: mongodb://user:passwd@host:port,host:port/db

7.Mongodb日志量

正常情況下不需要開啟-v 日志選項。

Mongodb 的-v 日志适合在開發環境的調試線上部署不建議采用這個參數,目前線上

部署的情況,-v 日志一天也會有幾個G 的日志量,去掉這個參數,跟資料查詢相關的操作

就不會記日志了,資料庫的内部的重要操作還是會寫日志的。

8.連接配接數大小的設定

Mongodb 驅動程式采用的連接配接池的方式連接配接到資料庫,目前從觀察到的情況是應用一

開啟便根據變量的設定,建立全部連接配接,然後提供給程式使用,并且一旦其中某個連接配接

到資料庫的通路失敗,則會清空整個連接配接池到這台資料庫的連接配接,并重建立立連接配接。

而mongodb 對中斷連接配接的垃圾清理工作則是懶惰的被動清理方式,如果驅動程式端配

置的連接配接數過大,一旦發生重連,則會導緻mongo 端堆積大量的垃圾連接配接資料,導緻

主機資源耗盡。

建議: mongodb 驅動的連接配接池大小的設定一般應該控制100 以下,一般情況30-50 足

夠支撐應用通路。

9.鎖的問題

Mongodb 對資料庫的通路全部加鎖,如果是查詢請求則設定共享鎖,資料修改請求,

則設定全局排他鎖,并且是執行個體級别的排他鎖。并且寫鎖會阻塞讀請求,如果長時間持有

寫鎖,會阻塞整個執行個體的讀請求。

部署建議:

1】一般情況下,建議不同的應用不要合用一套示例。

2】如果資源不滿足,需要合用,應該具有相同屬性的應用合用一套執行個體。

例如合同mongo 的應用都是讀多寫少,防止一台寫多應用阻塞讀請求。

10.關于map/reduce問題

mongodb 對map/reduce 的支援是單線程的,我們不建議在前台使用該功能, group by

是通過map/reduce 實作的,開發過程中,要慎用。

11.安全問題

1】Mongodb 運作在mongodb 使用者之上,并禁止mongodb 使用者登入

2】使用Mongodb 自帶的認證方法(adduser、auth)限制使用者通路行為

3】将Mongodb 置于内網環境中

4】Mongodb 必須暴露在外網環境中的時候,使用IPTABLES 等網絡層技術進行防護

5】網絡層面内容為明文傳輸,可以考慮存儲加密文檔,應用端,加解密。

12.性能監控

Mongodb 自帶有性能資料收集系統

Mongostat 實時采集資料庫的多項名額,提供http console 端口号為應用端口号+1000。

關注的主要性能名額:

1】Faults:顯示Mongodb 每秒頁面故障的數量,這個是mongoDB 映射到虛拟位址空間,

而不是實體記憶體,這個值如果飙高的話,可能意味着機器沒有足夠的記憶體來

存儲資料和索引。

2】Flushes:每秒做了多少次fsync,顯示多少次資料被重新整理進了磁盤

3】locked:寫鎖

4】idx miss:索引未命中比例

5】qr | qw:讀寫鎖的請求隊列長度。

6】conn: 目前已經建立的連接配接數。

其他指令:

Db.stat()

db.serverStatuse()

Db.collection.stats()

13.碎片問題

Mongodb 資料庫如果資料修改很頻繁,會出現比較嚴重的空間碎片問題,表現在磁盤

檔案擴張與實際資料量不相符,記憶體不夠用,索引命中率低,查詢效率降低。

碎片整理,目前我們采用的版本沒有太有效的方法。

可以用db.repaireDatabase() 來整理資料庫,這個過程非常的慢

如果是Master-slave 模式則相當于執行一次主從切換,然後從建立立從庫。

如果是replSet 架構可以停掉資料庫,然後删除資料目錄,從新從複制複制組中全同步資料,

這個時候要考慮oplog 的尺寸。

一個大體的步驟:

1.】先調用rs.freeze(1200),将每個不想讓它成為primary 的機器讓它在1200 秒内無法成為

primary(這步也可以不做)

2. 】将primary stepDown,不出意外新的primary 會起來.

3. 】将原primary kill 掉.

4. 】删掉所有data 資料(調用repair 很慢,真不如幹掉重新來)

5. 】再重新開機動原primary 的程序

6. 】以此循環完成整個複制組的全部重建。

14.系統備份:

Mongodb 目前不支援線上備份,隻能離線備份。

我們采用的架構為replSet 和Master-slave .

基于我們目前的架構以及資料一緻性要求,我們沒有安排相關的備份系統。

15.應用代碼中Mongodb連接配接問題

在有些應用在使用Mongodb 過程中會存在以下兩個小問題:

1. 在應用啟動過程中,應用存在要求連接配接池中所有的連接配接都建立成功才讓應用正

常啟動,這種做法不可取,因為存在網絡問題、Mongodb 拒絕連接配接或Mongodb 假死情況,如果沒加外部try catch 做防護,則Resin 不斷重新開機也不能正常啟動端口。

2.有些應用在使用Mongodb 中連接配接池配置了safe=true,w=1;這種配置意味着用戶端在

插入資料或更新資料的時候,要求mongodb 必須将所更新的資料寫入磁盤并傳回更新成功的資訊給程式。如果碰上應用程式通路壓力大,mongodb 就會反應遲鈍,并會發生假死可能,針對此情況,需要評估資料的一緻性需求,做出合适調整。我們一般建議關閉此選項。

16.補充開發方面的一些問題

1】skip+limit翻頁,越往後面越慢,有資料說用數組元素的分頁可以解決,目前還沒

試過,比較靠譜的做法是,先找出上次的id,翻頁的時候不用skip:

last_row_id = ObjectId(‘....’);

db.activity_stream->find({_id:{$lt: last_row_id },

user_id:20 } ).sort( {_id:-1} ).limit(10);

2】.隻有真正需要的字段才select出來

3】.更新的某條資料的時候,先查出來再更新會減小鎖的時間

4】.隻有傳回很少結果的查詢才用索引,否則會加載太多資料,比沒有用索引還慢

5】.屬性比較多的時候,建立分層的關系能夠提高查詢效率,否則每個記錄都要過一遍

才能找到要的屬性

17.關于硬體資源的選擇:

虛拟機可以很好的隔離資源,并可動态的擴充。

我們建議mongodb 的部署采用虛拟機的方式,每個虛拟機部署一個執行個體,使各節點分

散在不同的實體機上,根據應用的前期預測,平衡虛拟機的之間的i/o。

繼續閱讀