pretty code

顯示具有 MongoDB 標籤的文章。 顯示所有文章
顯示具有 MongoDB 標籤的文章。 顯示所有文章

2021年3月30日 星期二

load average on linux

既然已提早完成部份 Q2 KR 項目,反正還有時間乾脆來跑一下測試。

一般我們都會使用 top 指令來監控系統整體狀況,在結果視窗右上角有一個 load average 資訊,從 man 可以得知這是指系統負載,但這個數字要如何解讀完全沒有頭緒,於是又拜託了 Google 大神。


上面文章是第一筆搜尋結果,講得蠻淺顯易懂的,一下子就把它看完了,當我正準備離開網站時,眼睛餘光瞄到下面有網友留言這篇文章內容有誤,於是又順著留言看了第二篇文章。


簡單來說,這個數字不只跟 CPU 有關,其負載還牽涉到 I/O 等,故不能單純拿這個數字除以 CPU 核心數來判斷系統是否過載。

該文作者建議先觀察這個數字在什麼數值時是表示工作良好,而當這個數字超過原本的數值時,我們就必須藉由其他的指標來確認發生什麼事。

我之所以如此關心這個議題,是因為我在測試時發現當查詢 mongoDB 的 collection 擁有大量筆數資料時,不但記憶體使用量會突然爆增,且 CPU 使用率也會超過 100% 好幾秒。

由於我要查詢的欄位並沒有建立索引,故直覺一定是針對常用查詢條件建立索引以減輕 CPU 負擔,但很明顯的我的系統負載也會從 0.2X 增加到 0.6X。

我的資料量目前是 3 千多萬筆,一個月後就會變成兩億一千多萬筆,而這還只是一個 collection 而已!

這也是為什麼我現在如此在意這個數字的原因,我必須實測才能得知最終結果。

2021/04/08 更新

連假前重新跑了一次模擬,昨天進終端機看,三個負載數字都來到 1.2X 左右,但是在 ESXi 過去一小時監控視窗數據顯示,CPU 使用率都還沒超過 30%,目前筆數已經來到四千多萬筆。

2021/04/12 更新

目前筆數來到八千多萬筆,查詢還是可以在秒級的單位內完成,15 分鐘負載來到 1.74 左右,唯一不一樣的是 ESXi 的最小 CPU 使用率已經超過 1 了。


2021/04/19 更新

目前筆數來到一億三千多萬筆,查詢還是可以在秒級的單位內完成,15 分鐘負載來到 1.5X 左右,唯一不一樣的是真正的 Server 已掛,但我的模擬程式還是很認真的工作。由於肩牓受傷,不方便低頭確認 Server 機器狀況,只好等到好一點再來看怎麼回事?

2021年3月8日 星期一

相容 mongoDB 的 memory DB - lungoDB

今天看到一個很神奇的專案,簡單來說就是一個相容 mongoDB 的 memory DB。

https://github.com/256dpi/lungo

第一個想到的用途就是可以更容易的避免使用 mongoDB 遇到的 GPL 問題。

假設我的專案是可用或可不用 mongoDB 的,則我的專案即使不使用 mongoDB,也保有功能上的完整性,也就是擁有獨立性與可區分性。故就算我使用了 mongoDB,我也不需要 open source。

自己的專案 open source 當然沒有什麼問題,但公司的專案就必須考慮清楚,有了這個專案,我就不用自己把 mongoDB 的 code 改成 SQLite 的 code。

2019年3月19日 星期二

mongodump stderr message

最近在使用程式定時備份 MongoDB,發現在備份之後的 code 都無法執行。

查了一下才發現,mongodump 的 message 是往 stderr 丟,故程式不能以 stderr 是否有字串來判斷成功與否。

應該要對 stderr 再做一次過濾,如果有 "Failed" or "error ",理論上就是 dump 過程中有錯誤。

不過因為我不知道所有的錯誤訊息內容,以上方式只是針對 MongoDB service 沒有啟動的 case。

另外,為了自動排程執行,有些人可能是用 Windows batch 再包一層。

如果要在 batch 中將訊息直接導向到  log,正確做法應該如下。

run.bat > back.log 2>&1

">" 前面沒有寫就表示 default (STDOUT=1)。
"2>&1" 將 STDERR(2) 導向到 STDOUT(1)。

2018年11月19日 星期一

Use mongodump and mongorestore with authentication

如果當初設定 MongoDB 時,有設定帳號密碼
則 dump and restore 時,都需要指定相關資訊

假設 ip 192.168.1.1, port 27017, user abc, password abc, database def

mongodump -h 192.168.1.1 -p 27017 -u abc -p abc /db:def /out:"xxxxxx"
mongorestore -h 192.168.1.1 -p 27017 -u abc -p abc /db:def "xxxxxx"
   
如果有設定 root 帳號,則不必指定 /db: 參數,會備份所有 database(含 admin)
相反的如果有針對 database 設定存取帳號,則一定要加上 /db: 參數

2018年11月13日 星期二

MongoDB 備份與還原

目前知道的備份有 2 種方式(針對 single server)

1. 直接複製 MongoDB db and log 的上層目錄,如果是在 Windows 下,需要先停止服務
2. 使用 mongodump -p portNumber /out:"folder path",dump 的資料夾會位於 "folder path"

至於還原的話
1. 直接複製回去即可
2. mongorestore /drop "folder path",在還原前會先砍掉舊資料

2018年3月2日 星期五

MongoDB PHP example

最近需要測試一下 MongoDB
雖然我很喜歡 Go 語言
但還是直覺認為用 PHP 會比較方便
 
不過網路上的文章大部份都是舊的 PHP Driver 寫法(class MongoClient)
故花點時間把它整理一下

1. 新的用法有分 Low, High Level,High Level 的 code 比較精簡,但兩個都要裝
2. High Level - https://github.com/mongodb/mongo-php-library
3. Low Level - https://github.com/mongodb/mongo-php-driver
4. 兩者都是官方 release 的(官方也有提供其他語言的 Library)
5. 我使用的版本 PHP 7.0.8, MongoDB 3.6

官方說明

High Level - Query

require 'vendor/autoload.php';

$connectStr = 'mongodb://user:password@localhost:27017/databaseName';

try {
    $client = new MongoDB\Client($connectStr);

    $collection = $client->databaseName->collectionName;
    
    $records = $collection->find([]);

    foreach ($records as $item) {
        echo "_id = $item->_id \n";
    }

} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
    echo $e->getMessage() . "\n";
}

High Level - Insert

require 'vendor/autoload.php';

$connectStr = 'mongodb://user:password@localhost:27017/databaseName';

try {
    $client = new MongoDB\Client($connectStr);

    $collection = $client->databaseName->collectionName;
    $collection->insertOne(['b' => 'CCC']);

} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
    echo $e->getMessage() . "\n";
}


2018年2月26日 星期一

MongoDB connection URI

如果 MongoDB 有設定 auth 認證
連線字串大概會類似下面這樣
mongodb://username:password@localhost:27017

由於此字串是用 '@' 來分隔帳密設定及伺服器 IP
假設密碼也有用到 '@' 就會造成切割字串的問題

此時只要遵照 URI encode 的規則
將特殊字元 encode 即可

不過不同程式語言 API 的實做可能不同
PHP 只要 encode 特殊字元即可
其他語言也許是用 options array 的方式來設定帳密
這部份就得參考各 API 的說明文件

2018年2月14日 星期三

Init MongoDB database with javascript

MongoDB Version:3.6

Steps:
1. run mongod
2. run mongo
3. load('xxxx.js')
4. run "init()"

the content of xxxx.js

var d_admin = {
    user: 'd_admin',
    pwd: 'xxxx',
    roles: [
        {
            role: 'readWrite',
            db: 'test'
        }
    ]
}

var d_user = {
    user: 'd_user',
    pwd: 'xxxx',
    roles: [
        {
            role: 'read',
            db: 'test'
        }
    ]
}

var admin = {
    user: 'root',
    pwd: 'xxxx',
    roles: [
        {
            role: 'root',
            db: 'admin'
        }
    ]
}

function init() {
    db = connect('localhost:27017');
    db = db.getSiblingDB('admin');
    db.createUser(admin);

    db = db.getSiblingDB('test');
    db.createCollection('collection1');
    db.createCollection('collection2');
    db.createUser(d_admin);
    db.createUser(d_user);
    db.getLastError();
}