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。
相關文章
相關標籤/搜索