簡介
mongodb是很出名的nosql數據庫了,屬于集合-文檔型的特有架構nosql數據庫,也是被譽為最像關系型數據庫的非關系型數據庫,但是不支持事務.
由于mongodb原生就支持分布式架構,所以部署簡單,靈活,可伸縮,自動平衡數據結構等優點,繼而性能也非常高.所以搭建mongodb來使用的公司,90%都會使用到mongodb集群.
YCSB是Yahoo開發的一個專門用來對新一代數據庫進行基準測試的工具。全名是Yahoo! Cloud Serving Benchmark。包括支持的數據庫有:cassandra, hbase,mongodb,redis等數據庫.YCSB的幾大特性:
支持常見的數據庫讀寫操作,如插入,修改,刪除及讀取
多線程支持。YCSB用Java實現,有很好的多線程支持。
靈活定義場景文件??梢酝ㄟ^參數靈活的指定測試場景,如100%插入, 50%讀50%寫等等
數據請求分布方式:支持隨機,zipfian(只有小部分的數據得到大部分的訪問請求)以及最新數據幾種請求分布方式
可擴展性:可以通過擴展Workload的方式來修改或者擴展YCSB的功能
安裝mongodb
個人建議直接裝二進制版本就算了,方便簡單,編譯版就顯得略麻煩了.
現在mongodb最新的正式版本是3.6的,個人覺得太新,這編文章測試用的還是3.2的版本,還請各位知照.
總下載地址:
https://www.mongodb.com/download-center?jmp=nav#community
記得是選擇community server的版本,然后選取你的操作系統和系統的版本(我這里是rhel的linux),他只顯示最新版的下載地址,你要下舊版就要點下面的All Version Binaries.

然后就有一堆地址,你自己選擇需要的版本吧,例如我要下的是這個地址.
#在linux下用wget下載 wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.18.tgz?_ga=2.240790083.1507844543.1517391237-2141045386.1517391237
下載完成,就開始安裝了,因為是二進制版的,很簡單就是了.
#先安裝下依賴包,因為他是用c寫的,主要就是C的東西了 yum -y install gcc gcc-c++ glibc glibc-devel glib2 glib2-devel #解壓壓縮包 tar xf mongodb-linux-x86_64-rhel70-3.2.18.tgz #把壓縮包放到安裝目錄 mv mongodb-linux-x86_64-rhel70-3.2.18 /usr/local/ #創建安裝目錄的軟連接 ln -sf /usr/local/mongodb-linux-x86_64-rhel70-3.2.18/ /usr/local/mongodb #創建命令文件的軟連接,那就不用加到環境變量了 ln -sf /usr/local/mongodb/bin/* /usr/bin/ #創建用戶 useradd mongodb #創建數據目錄文件夾 mkdir -p /data/mongodb/data #更改文件夾屬主權限 chown -R mongodb:mongodb /data/mongodb/ #修改資源限制參數,添加mongodb相關項 vim /etc/security/limits.conf mongod soft nofile 64000 mongod hard nofile 64000 mongod soft nproc 32000 mongod hard nproc 32000
這就安裝完成了,后面就是初始化數據庫了,初始化之前,必須先有配置文件,二進制版本安裝的程序是不帶配置文件模板的,所以就要自己編輯了,配置文件存放的位置可以隨意,因為啟動是需要指定位置的,例如下面這個:
#編輯配置文件,并指定位置 vim /usr/local/mongodb/mongod_data_40001.conf #數據目錄 dbpath=/data/mongodb/data #日志文件 logpath=/data/mongodb/data/mongodb_data.log #日志形式為追加到文件后 logappend=true #端口 port = 40001 #指定訪問地址,不指定就是全網,但是在3.6之后必須制定這個參數才能啟動.0.0.0.0代表全網匹配 bind_ip = 0.0.0.0 #最大連接數 maxConns = 5000 pidfilepath = /data/mongodb/data/mongo_40001.pid #日志,redo log journal = true #刷寫提交機制 journalCommitInterval = 200 #守護進程模式 fork = true #刷寫數據到日志的頻率 syncdelay = 60 #存儲引擎,3.2之后默認就是wiredTiger #storageEngine = wiredTiger #操作日志,單位M oplogSize = 2000 #命名空間的文件大小,默認16M,最大2G。 nssize = 16 unixSocketPrefix = /tmp #指定一個數據庫一個文件夾,必須在初始化前配置,在已有數據庫上新增這個參數會報錯 directoryperdb=true #開啟慢查詢分析功能,0:關閉,不收集任何數據。1:收集慢查詢數據,默認是100毫秒.2:收集所有數據 profile=1 #慢查詢的時間,單位ms,超過這個時間將被記錄 slowms=200 #是否開啟認證模式,不開就不用用戶名密碼就能登錄數據庫,測試環境可以不開 #auth = true #關閉認證模式,和上面的沖突 noauth = true #指定集群認證文件,沒開認證就不用指定,注釋關閉即可,需要用openssl來生成 #keyFile = /data/mongodb/data/keyfile #標識這臺mongodb數據庫為分片集群使用 #shardsvr = true #副本集名稱,這里測的是單臺,不設置 #replSet=shard1 #是否config端,做集群的配置端使用,后面詳細介紹,這里不需要 #configsvr = true #禁止HTTP狀態接口,3.6后不用 nohttpinterface=true #禁止REST接口-在生產環境下建議不要啟用MongoDB的REST接口,,3.6后不用 rest=false #打開web監控,和上面相反,這里不開了 #httpinterface=true #rest=true
配置文件有了,就可以初始化啟動了,因為我沒有開啟認證模式,啟動就可以使用了.
#開啟mongodb的數據端 mongod -f /usr/local/mongodb/mongod_data_40001.conf about to fork child process, waiting until server is ready for connections. forked process: 15808 child process started successfully, parent exiting #來測試一下 mongo --port=40001 MongoDB shell version: 3.2.18 connecting to: 127.0.0.1:40001/test Server has startup warnings: 2018-01-31×××1:12:12.537+0800 I CONTROL [initandlisten] > show dbs local 0.000GB
============分割線開始=============
其實官方是推薦下面這種啟動方式,不過我為了方便,就簡單化啟動了.
#啟動之前,要先把文件夾權限確保一下 chown mongodb:mongodb -R /data/mongodb/data/* #然后關閉numa并使用mongodb用戶啟動 su - mongodb -s /bin/bash -c "numactl --interleave=all /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongod_data_40001.conf"
這種啟動方式好處是顯然的,對于數據庫來說,最怕就是被***提權,然后控制整臺機器,所以限制數據庫的啟動用戶是很有意義的.
而numa這個功能,對于大內存應用是很不友好的,會變成性能瓶頸,所以無論是sql還是nosql都最好是關閉了這個功能,那性能就更好一些了.
===========分割線結束==============
然后,這個mongodb數據庫就可以正常使用的了,當然,我們不是只使用單臺mongodb.
開頭也說了,90%的公司使用mongodb都是會使用到集群,在3.4版本之前,一般就用上面的配置就可以搭建集群,但是在3.4之后,如果不在啟動的時候指定這是分片端,則分片集群就不能被正常使用.
#標識這臺mongodb數據庫為分片集群使用 shardsvr = true
只有開啟了這個參數,分片集群才會正常使用.
如果,需要加載到服務啟動項,就添加以下腳本:
vim /etc/init.d/mongod
#!/bin/sh
#
#mongod - Startup script for mongod
#
# chkconfig: - 85 15
# description: Mongodb database.
# processname: mongod
# Source function library
. /etc/rc.d/init.d/functions
mongod="/usr/local/mongodb/bin/mongod"
configfile=" -f /etc/mongod.conf"
lockfile=/var/lock/subsys/mongod
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 64000
ulimit -m unlimited
ulimit -u 64000
ulimit -l unlimited
start()
{
echo -n $"Starting mongod: "
daemon --user mongod "$mongod $configfile"
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
}
stop()
{
echo -n $"Stopping mongod: "
$mongod --shutdown $configfile
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
}
restart () {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload|force-reload)
restart
;;
condrestart)
[ -f $lockfile ] && restart || :
;;
status)
status $mongod
retval=$?
;;
*)
echo "Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
retval=1
esac
exit $retval這樣就可以chkconfig或者systemd了
搭建mongodb分片集群
先來介紹一下架構,需要三個角色,
配置服務器,config端,需要1臺或3臺,不能是雙數,保存集群和分片的元數據,即各分片包含了哪些數據的信息,配置文件指定configsvr選項.
路由服務器,router端,隨便多少臺都行,本身不保存數據,在啟動時從配置服務器加載集群信息,開啟mongos進程需要知道配置服務器的地址,指定configdb選項.也可以理解為代理端
分片服務器,sharding端,保存真實數據信息,可以是一個副本集也可以是單獨的一臺服務器,支持主從故障切換.也可以叫數據端.
總共有8臺機器,配置是8核16G的虛擬機.
10.21.1.205 config端(1)+router端(1)
10.21.1.206 sharding端(1)
10.21.1.207 sharding端(1)
10.21.1.208 sharding端(1)
10.21.1.209 sharding端(1)
10.21.1.210 sharding端(1)
10.21.1.211 sharding端(1)
10.21.1.212 sharding端(1)
由于是測試環境,不想糾結太復雜,config端和router端都是一臺,當啟動router端的時候會拋出一個警告,"只有一臺config端的集群建議只用來測試",是的,我就是用來做測試.
sharding端我不打算詳細說了,就按照上面安裝mongodb的方式去操作并啟動就ok,不需要額外的配置,只需要等配置端把他們地址加載就可以,然后就會自動連接并分配數據塊起來,暫時也不需要研究其他東西.就是需要一臺臺去裝就比較麻煩一點,各位自行操作.
1.配置并啟動config端:
配置服務器也是一個mongod進程,其實也可以按照上面的配置文件來,配置服務器必須開啟1個或則3個,開啟2個則會報錯,
BadValue need either 1 or 3 configdbs
所以要注意數量,這里我就設一個就算了.
#也和上面一樣,沒有模板,只能自己編輯 vim /usr/local/mongodb/mongod_config_20000.conf #數據目錄,目錄名字區分于數據節點 dbpath=/data/mongodb/config/ #日志文件 logpath=/data/mongodb/mongodb_config.log #日志追加 logappend=true #端口 port = 20000 #綁定ip,可以限制IP登錄,例如bind_ip=10.21.1.208,3.2默認是允許所有ip登入,之后是允許127.0.0.1,只有配置0.0.0.0才是允許所有 bind_ip = 0.0.0.0 #最大連接數 maxConns = 5000 pidfilepath = /data/mongodb/mongo_20000.pid #日志,redo log journal = true #刷寫提交機制 journalCommitInterval = 200 #守護進程模式 fork = true #刷寫數據到日志的頻率 syncdelay = 60 #存儲引擎 #storageEngine = wiredTiger #操作日志,單位M oplogSize = 2000 #命名空間的文件大小,默認16M,最大2G。 nssize = 16 #套接字存放位置 unixSocketPrefix = /tmp #指定一個數據庫一個文件夾,必須在初始化前配置,在已有數據庫上新增這個參數會報錯 directoryperdb=true #關閉認證模式,config端可以不需要,也視乎你的需求 noauth = true #是否config端,這里當然是了 configsvr = true #副本集名稱,3.4之前可以不做集群,之后都需要設置config集群才可以使用 replSet=configs
其實和上面只是多了最后一行,標記是config端而已,然后啟動.
#啟動config端 mongod -f /usr/local/mongodb/mongod_config_20000.conf about to fork child process, waiting until server is ready for connections. forked process: 18535 child process started successfully, parent exiting
這里就不需要測試了,因為不需要在這里控制config端,然后看router端.
注意:3.4之后的版本使用分片集群,config端必須使用副本集,不然router端無法啟動.
2.配置并啟動router端:
路由服務器本身不保存數據,把日志記錄一下即可,他都是直接調用config端來使用.而所有客戶端程序想要連接mongodb集群,其實就是連接這個router端的端口來使用,并不是連接config端和sharding端,所以也說是類似于代理的形式.
#也和上面一樣,沒有模板,只能自己編輯 vim /usr/local/mongodb/mongos_route_30000.conf #日志文件 logpath=/data/mongodb/mongodb_route.log #日志追加 logappend=true #端口 port = 30000 #綁定ip,可以限制IP登錄,例如bind_ip=10.21.1.208,3.2默認是允許所有ip登入,之后是允許127.0.0.1,只有配置0.0.0.0才是允許所有 bind_ip = 0.0.0.0 #最大連接數 maxConns = 5000 pidfilepath = /data/mongodb/mongo_30000.pid #指定config端地址,不能使用127.0.0.1,會報錯,3.4后config必須是集群, #還必須在地址前面帶上副本集名稱,3.0和3.2可以點,例如:configdb=172.25.33.98:20000,單會提示警告 configdb=configs/172.25.33.98:20000,172.25.33.99:20000,172.25.33.101:20000 #守護進程模式 fork = true
最重要的參數是configdb,指定config端的地址,可以1個或3個,但是不能在其后面帶的配置服務器的地址寫成localhost或則127.0.0.1,需要設置成其他分片也能訪問的地址,即10.21.1.205:20000/20001/20002。否則在添加分片地址的時候會報錯.
然后是啟動:
#啟動方式略有不同,要使用mongos mongos -f /usr/local/mongodb/mongos_route_30000.conf 2018-02-01×××0:27:26.604+0800 W SHARDING [main] Running a sharded cluster with fewer than 3 config servers should only be done for testing purposes and is not recommended for production. about to fork child process, waiting until server is ready for connections. forked process: 6355 child process started successfully, parent exiting
啟動完成后會看到個警告,不過這里可以忽略,就是我開頭說的,提示你只有一臺config的話只建議用來測試.原因就是這臺config存儲的是各分片的數據塊信息,假如這臺config掛了,那么各分片之間的數據塊就不知道怎么關聯了,是一個非常大的安全隱患,所以生產環境一定要保證有3臺,最好還是錯開在不同的服務器上面,提高安全性.
3.添加和配置分片信息
按上面的步驟啟動完畢,那就可以開始配置分片了,當然,前提就是那些sharding端都已經全部部署啟動完畢.然后,就登錄進去操作了:
#使用客戶端像一般登錄mongodb那樣操作,這里沒有認證
mongo --port=30000 --host=10.21.1.205
MongoDB shell version: 3.2.18
connecting to: 10.21.1.205:30000/test
Server has startup warnings:
2018-02-01×××0:27:26.619+0800 I CONTROL [main]
mongos>
#看看現在的狀態,現在當然是什么也沒有
mongos>sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5a69925ee61d3e7c0519035a")
}
shards:
active mongoses:
"3.2.18" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:然后,我們來添加分片,sh.addShard("IP:Port")
#添加分片,如此類推
mongos> sh.addShard("10.21.1.206:40001")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("10.21.1.207:40001")
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> sh.addShard("10.21.1.208:40001")
{ "shardAdded" : "shard0002", "ok" : 1 }
.
.
.
#全部加完了,看看狀態,
mongos>sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5a69925ee61d3e7c0519035a")
}
shards:
{ "_id" : "shard0000", "host" : "10.21.1.206:40001" }
{ "_id" : "shard0001", "host" : "10.21.1.207:40001" }
{ "_id" : "shard0002", "host" : "10.21.1.208:40001" }
{ "_id" : "shard0003", "host" : "10.21.1.209:40001" }
{ "_id" : "shard0004", "host" : "10.21.1.210:40001" }
{ "_id" : "shard0005", "host" : "10.21.1.211:40001" }
{ "_id" : "shard0006", "host" : "10.21.1.212:40001" }
active mongoses:
"3.2.18" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:這個時候,7個分片都添加完畢,不過,現在還沒有數據庫,所以還要創建數據庫和數據庫的片鍵.創建數據庫應該還能理解,片鍵是什么,下面來簡單解析一下:
片鍵必須是一個索引,數據根據這個片鍵進行拆分分散。通過sh.shardCollection加會自動創建索引。一個自增的片鍵對寫入和數據均勻分布就不是很好,因為自增的片鍵總會在一個分片上寫入,后續達到某個閥值可能會寫到別的分片。但是按照片鍵查詢會非常高效。隨機片鍵對數據的均勻分布效果很好。注意盡量避免在多個分片上進行查詢。在所有分片上查詢,mongos會對結果進行歸并排序。也可以說是分片的規則字段了.
=============分割線開始==================
需要特別注意的一點是,有些mongodb是用root啟動的,所以數據庫的文件權限也是root,這樣就可能會造成一種奇葩現象,連接不正常,數據異常等,所以我們要確保數據庫文件權限是mongodb的.
#關閉mongodb killall mongod #刪掉鎖文件 rm -rf /data/mongodb/data/*.lock #更改文件夾權限 chown mongodb:mongodb -R /data/mongodb/* #啟動 mongod -f /usr/local/mongodb/mongod_data_40001.conf
當然是包括config端的了.
=============分割線結束===================
然后,我們就創建數據庫并開啟分片功能,一條命令就可以,最后再添加個片鍵就可以用了,命令是sh.enableSharding("庫名")、sh.shardCollection("庫名.集合名",{"key":1})
#創建一個ycsb的數據庫,并啟動他的分片功能
mongos>sh.enableSharding("ycsb")
{ "ok" : 1 }
#添加這個數據庫的片鍵為_id,規則是hash
mongos>sh.shardCollection("ycsb.usertable", {_id:"hashed"})
{ "collectionsharded" : "ycsb.usertable", "ok" : 1 }
###########################################
#假如你已經創建了一個,現在需要重建,那就要先刪除舊的數據庫了
#mongos> use ycsb
#switched to db ycsb
#mongos> db.dropDatabase()
#{ "dropped" : "ycsb", "ok" : 1 }
#mongos> show dbs
#config 0.013GB
###########################################==============分割線開始==================
在mongodb單純創建數據庫和表,并不需要另外的create命令操作,只需要直接插入一條數據就好了,也就代表創建成功
#當前沒有新的數據庫
> show dbs
admin 0.000GB
local 0.000GB
#單純切換到數據庫,也算是新建數據庫的了
> use foo
switched to db foo
> db
foo
#但是這個時候,你還是看不到的
> show dbs
admin 0.000GB
local 0.000GB
#插入一條數據,createtmp是要新建的表名,
> db.createtmp.insert({"name":"create database"})
WriteResult({ "nInserted" : 1 })
#你就能看到了
> show dbs
foo 0.000GB
admin 0.000GB
local 0.000GB
#而且你的表也創建好了
> show collections
createtmp不過,我們如果做分片的話,一開始有表是不合適的,因為要做片鍵,所以才在這里另外來說這個問題.
==============分割線結束==================
這樣添加的原因是后面的ycsb測試工具的需要,他會生成一個名為ycsb的數據庫,里面有一個usertable集合(表),然后其中有_id這個列,至于hash規則我想就不解析了.然后,在看看狀態:
#看看現在的狀態,很長
mongos>sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5a69925ee61d3e7c0519035a")
}
shards:
{ "_id" : "shard0000", "host" : "10.21.1.206:40001" }
{ "_id" : "shard0001", "host" : "10.21.1.207:40001" }
{ "_id" : "shard0002", "host" : "10.21.1.208:40001" }
{ "_id" : "shard0003", "host" : "10.21.1.209:40001" }
{ "_id" : "shard0004", "host" : "10.21.1.210:40001" }
{ "_id" : "shard0005", "host" : "10.21.1.211:40001" }
{ "_id" : "shard0006", "host" : "10.21.1.212:40001" }
active mongoses:
"3.2.18" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 5
Last reported error: Connection refused
Time of Reported error: Thu Feb 01 2018 14:26:07 GMT+0800 (CST)
Migration Results for the last 24 hours:
databases:
{ "_id" : "ycsb", "primary" : "shard0000", "partitioned" : true }
ycsb.usertable
shard key: { "_id" : "hashed" }
unique: false
balancing: true
chunks:
shard0000 2
shard0001 2
shard0002 2
shard0003 2
shard0004 2
shard0005 2
shard0006 2
{ "_id" : { "$minKey" : 1 } } -->> { "_id" : NumberLong("-7905747460161236400") } on : shard0000 Timestamp(7, 2)
{ "_id" : NumberLong("-7905747460161236400") } -->> { "_id" : NumberLong("-6588122883467697000") } on : shard0000 Timestamp(7, 3)
{ "_id" : NumberLong("-6588122883467697000") } -->> { "_id" : NumberLong("-5270498306774157600") } on : shard0001 Timestamp(7, 4)
{ "_id" : NumberLong("-5270498306774157600") } -->> { "_id" : NumberLong("-3952873730080618200") } on : shard0001 Timestamp(7, 5)
{ "_id" : NumberLong("-3952873730080618200") } -->> { "_id" : NumberLong("-2635249153387078800") } on : shard0002 Timestamp(7, 6)
{ "_id" : NumberLong("-2635249153387078800") } -->> { "_id" : NumberLong("-1317624576693539400") } on : shard0002 Timestamp(7, 7)
{ "_id" : NumberLong("-1317624576693539400") } -->> { "_id" : NumberLong(0) } on : shard0003 Timestamp(7, 8)
{ "_id" : NumberLong(0) } -->> { "_id" : NumberLong("1317624576693539400") } on : shard0003 Timestamp(7, 9)
{ "_id" : NumberLong("1317624576693539400") } -->> { "_id" : NumberLong("2635249153387078800") } on : shard0004 Timestamp(7, 10)
{ "_id" : NumberLong("2635249153387078800") } -->> { "_id" : NumberLong("3952873730080618200") } on : shard0004 Timestamp(7, 11)
{ "_id" : NumberLong("3952873730080618200") } -->> { "_id" : NumberLong("5270498306774157600") } on : shard0005 Timestamp(7, 12)
{ "_id" : NumberLong("5270498306774157600") } -->> { "_id" : NumberLong("6588122883467697000") } on : shard0005 Timestamp(7, 13)
{ "_id" : NumberLong("6588122883467697000") } -->> { "_id" : NumberLong("7905747460161236400") } on : shard0006 Timestamp(7, 14)
{ "_id" : NumberLong("7905747460161236400") } -->> { "_id" : { "$maxKey" : 1 } } on : shard0006 Timestamp(7, 15)
#看看有什么數據庫
mongos> show dbs
config 0.007GB
ycsb 0.000GB
#登進目標數據庫
mongos> use ycsb
switched to db ycsb
#查看數據庫的狀態
mongos> db.stats()
{
"raw" : {
"10.21.1.206:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.207:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.208:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.209:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.210:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.211:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
},
"10.21.1.212:40001" : {
"db" : "ycsb",
"collections" : 1,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 4096,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 8192,
"ok" : 1
}
},
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 28672,
"numExtents" : 0,
"indexes" : 14,
"indexSize" : 57344,
"fileSize" : 0,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"ok" : 1
}好了,至此,mongodb的分片集群已經搭建好,暫時還沒有數據,objects顯示是0就是沒數據了,各分片也沒有數據.
不過,有時候會因為信息太長而導致顯示不全,并提示
too many chunks to print, use verbose if you want to force print
那么我們就要用下列命令來顯示了,三個都可以,然后就顯示全部了,但是更長.
mongos> sh.status({"verbose":1})
mongos> db.printShardingStatus("vvvv")
mongos> printShardingStatus(db.getSisterDB("config"),1)4.刪除分片信息
最后來看刪除分片,有添加,就當然有刪除了,雖然不是這里的重點, db.runCommand({"removeshard":"mmm"})
#登進管理數據庫admin,3.2隱藏了,不過確實存在.
mongos> use admin
switched to db admin
mongos> db
admin
#刪除剛才添加的一個分片,注意state狀態,是準備刪除,將不會有新數據進入該分片
mongos> db.runCommand({"removeshard":"shard0006"})
{
"msg" : "draining started successfully",
"state" : "started",
"shard" : "shard0006",
"note" : "you need to drop or movePrimary these databases",
"dbsToMove" : [ ],
"ok" : 1
}
#這個時候,狀態已經改變成draining,但是還沒有刪除,只是新數據不再寫入進去
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5a69925ee61d3e7c0519035a")
}
shards:
{ "_id" : "shard0000", "host" : "10.21.1.206:40001" }
{ "_id" : "shard0001", "host" : "10.21.1.207:40001" }
{ "_id" : "shard0002", "host" : "10.21.1.208:40001" }
{ "_id" : "shard0003", "host" : "10.21.1.209:40001" }
{ "_id" : "shard0004", "host" : "10.21.1.210:40001" }
{ "_id" : "shard0005", "host" : "10.21.1.211:40001" }
{ "_id" : "shard0006", "host" : "10.21.1.212:40001", "draining" : true }
active mongoses:
"3.2.18" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
.
.
.
#再操作一次,這次將會完全刪除,
#如果里面沒數據,會顯示state狀態為completed,
mongos> db.runCommand({"removeshard":"shard0006"})
{
"msg" : "removeshard completed successfully",
"state" : "completed",
"shard" : "shard0006",
"ok" : 1
}
#如果有數據,則會等到遷移完才會執行通過,取決于數據量多不多,顯示state狀態為ongoing
mongos> db.runCommand({"removeshard":"shard0006"})
{
"msg" : "draining ongoing",
"state" : "ongoing",
"remaining" : {
"chunks" : NumberLong(2128),
"dbs" : NumberLong(0)
},
"note" : "you need to drop or movePrimary these databases",
"dbsToMove" : [ ],
"ok" : 1
}
#刪除完畢后,再次查看,id為shard0006的分片已經被刪除,
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5a69925ee61d3e7c0519035a")
}
shards:
{ "_id" : "shard0000", "host" : "10.21.1.206:40001" }
{ "_id" : "shard0001", "host" : "10.21.1.207:40001" }
{ "_id" : "shard0002", "host" : "10.21.1.208:40001" }
{ "_id" : "shard0003", "host" : "10.21.1.209:40001" }
{ "_id" : "shard0004", "host" : "10.21.1.210:40001" }
{ "_id" : "shard0005", "host" : "10.21.1.211:40001" }
active mongoses:
"3.2.18" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
.
.
.
#這里顯示也沒有了該分片地址了
mongos> db.runCommand({ listshards : 1 })
{
"shards" : [
{
"_id" : "shard0000",
"host" : "10.21.1.206:40001"
},
{
"_id" : "shard0001",
"host" : "10.21.1.207:40001"
},
{
"_id" : "shard0002",
"host" : "10.21.1.208:40001"
},
{
"_id" : "shard0003",
"host" : "10.21.1.209:40001"
},
{
"_id" : "shard0004",
"host" : "10.21.1.210:40001"
},
{
"_id" : "shard0005",
"host" : "10.21.1.211:40001"
}
],
"ok" : 1
}需要注意的是,不能同時刪除兩個或以上的分片,只有刪除完一個后,另一個才可以開始刪除.
另外,分片還有遷移功能,可以是整個遷移或遷移某一個塊chunks(sh.moveChunk("db.collection",{塊地址},"新片名稱")),這里不打算展開來說,日常使用中,這種操作也基本上很少涉及,基本上都讓均衡器balancer自己去跑就算了.
需要特別注意的是刪除主分片,則需要先遷移走數據庫到別的分片,
db.adminCommand({"movePrimary":"ycsb","to":"shard0001"})這樣才能刪主分片.
安裝刪除都完成了,后面來看ycsb要怎么使用了.
搭建ycsb環境
ycsb程序本身是python+java的結合體,是不是很奇怪?主要測試的對象是nosql系列數據庫:cassandra, hbase,mongodb,redis這些.程序本身也是二進制版,python其實yum一下也行了,主要就是java了.
由于java的下載地址經常變,包的容量也不少,所以就只給個官方總地址了,去下java se的包就可以了,雖然已經出了9,但是我還是覺得用8就算了.
http://www.oracle.com/technetwork/java/javase/downloads
#安裝python環境 yum install -y python python-devel #安裝java tar xf jdk-8u144-linux-x64.tar.gz mv jdk1.8.0_144/ /usr/local/ ln -sf /usr/local/jdk1.8.0_144/ /usr/local/jdk #創建java環境變量 vim /etc/profile.d/java.sh export JAVA_HOME=/usr/local/jdk export JRE_HOME=/usr/local/jdk/jre export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib export PATH=$PATH:$JAVA_HOME/bin #重載環境變量 source /etc/profile #測試一下 java -version java version "1.8.0_144" Java(TM) SE Runtime Environment (build 1.8.0_144-b01) Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
前置的環境安裝完畢,就來看怎么安裝ycsb了,和java有點像,而且還不用做環境變量,其實我覺得也不能叫安裝,直接解壓就能用了,現在最新版本是ycsb-0.12.0
#下載ycsb wget https://github.com/brianfrankcooper/YCSB/releases/download/0.12.0/ycsb-0.12.0.tar.gz #解壓 tar xf ycsb-0.12.0.tar.gz #查看目錄結構 ll ycsb-0.12.0 total 12 drwxr-xr-x. 4 root root 46 Jan 30 11:23 accumulo-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 aerospike-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 arangodb-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 asynchbase-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 azuretablestorage-binding drwxr-xr-x. 2 root root 76 Feb 1 18:01 bin drwxr-xr-x. 3 root root 34 Jan 30 11:23 cassandra-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 couchbase2-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 couchbase-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 dynamodb-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 elasticsearch-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 geode-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 googlebigtable-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 googledatastore-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 hbase094-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 hbase098-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 hbase10-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 hypertable-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 infinispan-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 jdbc-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 kudu-binding drwxr-xr-x. 2 root root 170 Jan 30 11:23 lib -rw-r--r--. 1 501 games 8082 Jan 21 2015 LICENSE.txt drwxr-xr-x. 3 root root 34 Jan 30 11:23 memcached-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 mongodb-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 nosqldb-binding -rw-r--r--. 1 501 games 615 Sep 27 2016 NOTICE.txt drwxr-xr-x. 3 root root 34 Jan 30 11:23 orientdb-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 rados-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 redis-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 rest-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 riak-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 s3-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 solr6-binding drwxr-xr-x. 3 root root 34 Jan 30 11:23 solr-binding drwxr-xr-x. 4 root root 46 Jan 30 11:23 tarantool-binding drwxr-xr-x. 2 501 games 183 Feb 2 11:19 workloads #和一般程序差不多,bin目錄就是命令目錄了 ll /opt/ycsb-0.12.0/bin/ total 36 -rw-r--r--. 1 501 games 2672 Nov 1 2016 bindings.properties -rwxr-xr-x. 1 501 games 12572 Nov 1 2016 ycsb -rwxr-xr-x. 1 501 games 6431 Sep 30 2016 ycsb.bat -rwxr-xr-x. 1 501 games 7458 Sep 30 2016 ycsb.sh
其他目錄暫時就不研究,不過從字面意思可以理解一些,其實就是各種數據庫的驅動.后面來看怎么使用了.
使用ycsb
1.使用簡介
使用前,我們要先了解他的命令結構,我們才能知道怎么做才能達到效果.有點類似于測試mysql數據庫的sysbench
bin/ycsb load/run/shell mongodb/hbase10/basic.. mongodb.url="mongodb://user:pwd@server1.example.com:9999" -P workloads/workloada -s
第一項,bin/ycsb,就不用解析了,就是命令本身.
第二項,load/run/shell,指定這個命令的作用,加載數據/運行測試/交互界面,類似sysbench
第三項,mongodb/hbase10/basic..指定這次測試使用的驅動,也就是這次究竟測的是什么數據庫,有很多選項,可以ycsb --help看到所有
第四項,mongodb.url,指定測試的數據庫的認證信息,地址端口和用戶密碼,這里拿的是mongodb的來做演示
第五項,-P workloads/workloada,指定測試的參數文件,默認有6種測試模板,加一個大模板,都可以vim打開來看,大致為:
workloada:讀寫均衡型,50%/50%,Reads/Writes
workloadb:讀多寫少型,95%/5%,Reads/Writes
workloadc:只讀型,100%,Reads
workloadd:讀最近寫入記錄型,95%/5%,Reads/insert
workloade:掃描小區間型,95%/5%,scan/insert
workloadf:讀寫入記錄均衡型,50%/50%,Reads/insert
workload_template:參數列表模板
第六項,-s,每10秒打印報告一次到屏幕,可以ycsb --help看到
2.測試參數解析
看了上面的解析,就可以看出來,問題的重點是第五項,-P workloads/workloada,這里編輯好,那壓測效果才會出來,那么里面有些什么呢,西面來看看:
#打開這個文件來看
vim workloads/workloada
#YCSB load(加載元數據)命令的參數,表示加載的記錄條數,也就是可用于測試的總記錄數。
recordcount=1000000
#YCSB run(運行壓力測試)命令的參數,測試的總次數。和maxexecutiontime參數有沖突,誰先完成就中斷測試退出,結合下面的增改讀掃參數,按比例來操作.
#operationcount=1000000
#測試的總時長,單位為秒,和operationcount參數有沖突,誰先完成就中斷測試退出,這里3600秒就代表一小時,也是結合下面的增改讀掃參數,按比例來操作.
maxexecutiontime=3600
#java相關參數,指定了workload的實現類為 com.yahoo.ycsb.workloads.CoreWorkload
workload=com.yahoo.ycsb.workloads.CoreWorkload
#表示查詢時是否讀取記錄的所有字段
readallfields=true
#表示讀操作的比例,該場景為0.54,即54%
readproportion=0.54
#表示更新操作的比例,該場景為0.2,即20%
updateproportion=0.2
#表示掃描操作的比例,即1%,通常是用來模擬沒有索引的查詢
scanproportion=0.01
#表示插入操作的比例,即25%
insertproportion=0.25
#表示請求的分布模式,YCSB提供uniform(隨機均衡讀寫),zipfian(偏重讀寫少量熱數據),latest(偏重讀寫最新數據)三種分布模式
requestdistribution=uniform
#插入文檔的順序方式:哈希(hashed)/隨機 (insertorder)
insertorder=hashed
#測試數據的每一個字段的長度,單位字節
fieldlength=2000
#測試數據的每條記錄的字段數,也就是說一條記錄的總長度是2000*10=20000字節
fieldcount=10
#####################以下是不自帶的參數#############################
#把數據庫連接地址寫到這里,那么輸命令的時候就不用輸地址了,我這里沒有設用戶名密碼,當然是不需要了
mongodb.url=mongodb://10.21.1.205:30000/ycsb?w=0
#如果你是有很多個mongos的話,就要這樣寫
#mongodb.url=mongodb://172.25.31.101:30000,172.25.31.102:30000,172.25.31.103:30000/ycsb?w=0
#如果是有用戶名密碼的話,就要這樣寫,還記得上面一開始的模板嘛,mongodb://user:pwd@server1.example.com:9999
#mongodb.url=mongodb://ycsbtest:ycsbtest@10.21.1.205:30000/ycsb?w=0
#寫安全設置,Unacknowledged(不返回用戶是否寫入成功{w:0}),Acknowledged(寫入到主節點內存就返回寫入成功{w:1}),Journaled(寫入到主節點journal log才返回寫入成功{w:1,j:true}),Replica Acknowledged(寫入到所有副本集內存和主節點journal log才返回寫入成功{w:2}),Available Write Concern(寫入到所有節點journal log才返回寫入成功{w:2,j:true}),選項越往后,安全性越高,但是性能越差.
mongodb.writeConcern=acknowledged
#線程數,也就是說100個并發,既然是壓測,怎么可能是單線程
threadcount=100還有一些參數沒列出,然后我們得出自己需要的參數文件,這個是100%純插入1億條記錄的參數文件,如下所示:
#100%純插入的參數文件 vim workloads/mongotest_in_only #定個小目標,比如1個億,插入1億條文檔數據 recordcount=100000000 operationcount=100000000 workload=com.yahoo.ycsb.workloads.CoreWorkload readallfields=true readproportion=0 updateproportion=0 scanproportion=0 #只有插入的操作,1就是100% insertproportion=1 requestdistribution=uniform insertorder=hashed fieldlength=250 fieldcount=8 mongodb.url=mongodb://10.21.1.205:30000/ycsb?w=0 mongodb.writeConcern=acknowledged threadcount=100
每個文檔大小大約2KB(fieldlength x fieldcount),數據總大小大概是200G+12G的索引,數量還是比較多,如果是單點,估計是比較難撐,查詢也超級慢.但是做了分片的話,程序會自動分配,把他們平均分配到每一個分片中,那么壓力就減輕很多了,分布式架構的優勢出來了.
3.執行純插入測試
上面我自己寫的配置文件,就是為了做插入測試,總共7個分片,插入1億條數據,花了兩個多小時,看來時間還是要預足夠.
#執行下面命令進行插入測試 bin/ycsb load mongodb -P workloads/mongotest_in_only -s > /home/logs/mongo_ycsb20180131-1.log & /usr/local/jdk/bin/java -cp /opt/ycsb-0.12.0/mongodb-binding/conf:/opt/ycsb-0.12.0/conf:/opt/ycsb-0.12.0/lib/core-0.12.0.jar:/opt/ycsb-0.12.0/lib/htrace-core4-4.1.0-incubating.jar:/opt/ycsb-0.12.0/lib/jackson-mapper-asl-1.9.4.jar:/opt/ycsb-0.12.0/lib/jackson-core-asl-1.9.4.jar:/opt/ycsb-0.12.0/lib/HdrHistogram-2.1.4.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/logback-classic-1.1.2.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/logback-core-1.1.2.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongo-java-driver-3.0.3.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongodb-async-driver-2.0.1.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/slf4j-api-1.6.4.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongodb-binding-0.12.0.jar com.yahoo.ycsb.Client -db com.yahoo.ycsb.db.MongoDbClient -P workloads/mongotest_in_only -s -load YCSB Client 0.12.0 Command line: -db com.yahoo.ycsb.db.MongoDbClient -P workloads/mongotest_in_only -s -load Loading workload... Starting test. 2018-02-02 11:19:40:314 0 sec: 0 operations; est completion in 0 seconds 2018-02-02 11:19:50:233 10 sec: 57123 operations; 5703.74 current ops/sec; est completion in 4 hours 52 minutes [INSERT: Count=57144, Max=1724415, Min=150, Avg=12858.59, 90=621, 99=416511, 99.9=1072127, 99.99=1367039] 2018-02-02 11:20:00:218 20 sec: 188182 operations; 13125.59 current ops/sec; est completion in 2 hours 56 minutes [INSERT: Count=131051, Max=2009087, Min=35, Avg=6348.01, 90=206, 99=140159, 99.9=1202175, 99.99=1803263] 2018-02-02 11:20:11:036 30 sec: 370000 operations; 18181.8 current ops/sec; est completion in 2 hours 14 minutes [INSERT: Count=181818, Max=2965503, Min=30, Avg=5638.81, 90=122, 99=371, 99.9=1506303, 99.99=2301951] 2018-02-02 11:20:20:223 40 sec: 576572 operations; 20646.88 current ops/sec; est completion in 1 hours 54 minutes [INSERT: Count=206574, Max=4304895, Min=27, Avg=3766.68, 90=109, 99=276, 99.9=1126399, 99.99=1978367] 2018-02-02 11:20:31:659 51 sec: 747015 operations; 14904.07 current ops/sec; est completion in 1 hours 53 minutes [INSERT: Count=170445, Max=5423103, Min=27, Avg=6511.35, 90=107, 99=276, 99.9=2037759, 99.99=3981311] . . . 2018-02-02 13:10:50:218 6670 sec: 99794282 operations; 17292.1 current ops/sec; est completion in 14 seconds [CLEANUP: Count=12, Max=3, Min=2, Avg=2.58, 90=3, 99=3, 99.9=3, 99.99=3] [INSERT: Count=172921, Max=1833983, Min=18, Avg=1729.1, 90=50, 99=202, 99.9=783871, 99.99=1312767] 2018-02-02 13:11:00:218 6680 sec: ×××5363 operations; 13108.1 current ops/sec; est completion in 5 seconds [CLEANUP: Count=16, Max=4, Min=2, Avg=3, 90=4, 99=4, 99.9=4, 99.99=4] [INSERT: Count=131081, Max=1249279, Min=19, Avg=1336.59, 90=54, 99=152, 99.9=607231, 99.99=1011711] 2018-02-02 13:11:10:218 6690 sec: 99972913 operations; 4755 current ops/sec; est completion in 2 seconds [CLEANUP: Count=5, Max=5, Min=4, Avg=4.2, 90=5, 99=5, 99.9=5, 99.99=5] [INSERT: Count=47550, Max=898559, Min=21, Avg=1097.42, 90=78, 99=136, 99.9=512511, 99.99=825855] 2018-02-02 13:11:20:218 6700 sec: 99995467 operations; 2255.4 current ops/sec; est completion in 1 seconds [CLEANUP: Count=2, Max=4, Min=4, Avg=4, 90=4, 99=4, 99.9=4, 99.99=4] [INSERT: Count=22554, Max=752127, Min=24, Avg=850.14, 90=68, 99=106, 99.9=500223, 99.99=642559] 2018-02-02 13:11:23:489 6703 sec: 100000000 operations; 1385.39 current ops/sec; [CLEANUP: Count=1, Max=5411, Min=5408, Avg=5410, 90=5411, 99=5411, 99.9=5411, 99.99=5411] [INSERT: Count=4533, Max=527871, Min=20, Avg=821.06, 90=61, 99=90, 99.9=466175, 99.99=527871]
中間很多行暫時先忽略,因為是會一致輸出到運行完畢為止,來看運行解讀,每一個項都用分號;來隔開,直接拿例子來說說.這是第二行的數據:
第一個分號前的數值:2018-02-02 11:20:00:218 20 sec: 188182 operations;
表示"當前的時間,已運行的時間,運行的數據量"三個值,而-s參數默認是每10秒輸出一次,直到這1億數據寫完就停止.
第二個分號前的數值:13125.59 current ops/sec;
表示吞吐量信息,也就是常說的ops值(每秒操作次數),可以用他來做趨勢圖,看看這個集群的趨勢.
后面的所有:est completion in 2 hours 56 minutes [INSERT: Count=131051, Max=2009087, Min=35, Avg=6348.01, 90=206, 99=140159, 99.9=1202175, 99.99=1803263]
表示預估執行時間,進行了什么操作(這里只有insert),總共操作了多少數據,操作的時間和延時等數據,意義不大,只做參考.
4.執行純讀測試
配置文件和上面可以保持大體一致即可,只修改下面這里
#只讀,1即100 readproportion=1 updateproportion=0 scanproportion=0 insertproportion=0
然后就可以執行了
#執行下面命令進行只讀測試 bin/ycsb run mongodb -P workloads/mongotest_re_only -s > /home/logs/mongo_ycsb20180201-1.log & /usr/local/jdk/bin/java -cp /opt/ycsb-0.12.0/mongodb-binding/conf:/opt/ycsb-0.12.0/conf:/opt/ycsb-0.12.0/lib/core-0.12.0.jar:/opt/ycsb-0.12.0/lib/htrace-core4-4.1.0-incubating.jar:/opt/ycsb-0.12.0/lib/jackson-mapper-asl-1.9.4.jar:/opt/ycsb-0.12.0/lib/jackson-core-asl-1.9.4.jar:/opt/ycsb-0.12.0/lib/HdrHistogram-2.1.4.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/logback-classic-1.1.2.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/logback-core-1.1.2.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongo-java-driver-3.0.3.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongodb-async-driver-2.0.1.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/slf4j-api-1.6.4.jar:/opt/ycsb-0.12.0/mongodb-binding/lib/mongodb-binding-0.12.0.jar com.yahoo.ycsb.Client -db com.yahoo.ycsb.db.MongoDbClient -P workloads/mongotest_re_only -s -t YCSB Client 0.12.0 Command line: -db com.yahoo.ycsb.db.MongoDbClient -P workloads/mongotest_re_only -s -t Loading workload... Starting test. 2018-02-02 14:14:03:394 0 sec: 0 operations; est completion in 0 seconds 2018-02-02 14:14:13:316 10 sec: 52718 operations; 5271.8 current ops/sec; est completion in 5 hours 15 minutes [READ: Count=52726, Max=515839, Min=886, Avg=17807.9, 90=32959, 99=84223, 99.9=215551, 99.99=422655] 2018-02-02 14:14:23:315 20 sec: 136267 operations; 8354.9 current ops/sec; est completion in 4 hours 4 minutes [READ: Count=83543, Max=71231, Min=740, Avg=11962.2, 90=22063, 99=39167, 99.9=52863, 99.99=65919] 2018-02-02 14:14:33:315 30 sec: 227979 operations; 9171.2 current ops/sec; est completion in 3 hours 38 minutes [READ: Count=91710, Max=60479, Min=969, Avg=10899.01, 90=18143, 99=29439, 99.9=45055, 99.99=55839] 2018-02-02 14:14:43:315 40 sec: 319725 operations; 9174.6 current ops/sec; est completion in 3 hours 27 minutes [READ: Count=91747, Max=57215, Min=1036, Avg=10890.33, 90=17919, 99=27007, 99.9=36031, 99.99=49023] 2018-02-02 14:14:53:318 50 sec: 411156 operations; 9141.27 current ops/sec; est completion in 3 hours 21 minutes [READ: Count=91439, Max=51039, Min=1052, Avg=10932.95, 90=17983, 99=27887, 99.9=37375, 99.99=44639] . . . 2018-02-02 17:18:53:315 11090 sec: 99690172 operations; 8923 current ops/sec; est completion in 35 seconds [READ: Count=89229, Max=59263, Min=920, Avg=11199.31, 90=18879, 99=30383, 99.9=43423, 99.99=53631] 2018-02-02 17:19:03:315 11100 sec: 99779154 operations; 8898.2 current ops/sec; est completion in 25 seconds [READ: Count=88982, Max=69119, Min=914, Avg=11232.26, 90=18959, 99=30303, 99.9=42975, 99.99=54751] 2018-02-02 17:19:13:315 11110 sec: 99868510 operations; 8935.6 current ops/sec; est completion in 15 seconds [READ: Count=89356, Max=72895, Min=720, Avg=11122.55, 90=18591, 99=29871, 99.9=41215, 99.99=48831] [CLEANUP: Count=2, Max=19, Min=5, Avg=12, 90=19, 99=19, 99.9=19, 99.99=19] 2018-02-02 17:19:23:316 11120 sec: 99956583 operations; 8806.42 current ops/sec; est completion in 5 seconds [READ: Count=88074, Max=67007, Min=886, Avg=9859.62, 90=16527, 99=27039, 99.9=38911, 99.99=51519] [CLEANUP: Count=35, Max=15, Min=4, Avg=5.49, 90=7, 99=15, 99.9=15, 99.99=15] 2018-02-02 17:19:30:066 11126 sec: 100000000 operations; 6432.15 current ops/sec; [READ: Count=43416, Max=42047, Min=705, Avg=4970.02, 90=8567, 99=16719, 99.9=27343, 99.99=37055] [CLEANUP: Count=63, Max=9311, Min=2, Avg=153.7, 90=6, 99=53, 99.9=9311, 99.99=9311]
和上面差不多,
第一個分號前的數值:2018-02-02 14:14:23:315 20 sec: 136267 operations;
表示"當前的時間,已運行的時間,運行的數據量"三個值,而-s參數默認是每10秒輸出一次,直到這1億數據寫完就停止.
第二個分號前的數值:8354.9 current ops/sec;
表示吞吐量信息,也就是常說的ops值(每秒操作次數),可以用他來做趨勢圖,看看這個集群的趨勢.
后面的所有:est completion in 4 hours 4 minutes [READ: Count=83543, Max=71231, Min=740, Avg=11962.2, 90=22063, 99=39167, 99.9=52863, 99.99=65919]
表示預估執行時間,進行了什么操作(這里只有read),總共操作了多少數據,操作的時間和延時等數據,意義不大,只做參考.
其他測試就不一一細說了,各位自己按實際情況配置這個比例即可.
5.結果解讀
上面介紹的其實只是-s輸出的結果,當然那些結果還是很有參考價值的,但是真正的結果其實是下面這些,
#打開結果文件 vim mongo_ycsb20180202-1.log mongo client connection created with mongodb://10.21.1.205:30000/ycsb?w=0 [OVERALL], RunTime(ms), 1.112675E7 [OVERALL], Throughput(ops/sec), 8987.350304446492 [TOTAL_GCS_PS_Scavenge], Count, 18117.0 [TOTAL_GC_TIME_PS_Scavenge], Time(ms), 99198.0 [TOTAL_GC_TIME_%_PS_Scavenge], Time(%), 0.891527175500483 [TOTAL_GCS_PS_MarkSweep], Count, 8.0 [TOTAL_GC_TIME_PS_MarkSweep], Time(ms), 254.0 [TOTAL_GC_TIME_%_PS_MarkSweep], Time(%), 0.002282786977329409 [TOTAL_GCs], Count, 18125.0 [TOTAL_GC_TIME], Time(ms), 99452.0 [TOTAL_GC_TIME_%], Time(%), 0.8938099624778125 [READ], Operations, 1.0E8 [READ], AverageLatency(us), 11114.24612337 [READ], MinLatency(us), 672.0 [READ], MaxLatency(us), 515839.0 [READ], 95thPercentileLatency(us), 21871.0 [READ], 99thPercentileLatency(us), 29615.0 [READ], Return=OK, 100000000 [CLEANUP], Operations, 100.0 [CLEANUP], AverageLatency(us), 98.99 [CLEANUP], MinLatency(us), 2.0 [CLEANUP], MaxLatency(us), 9311.0 [CLEANUP], 95thPercentileLatency(us), 10.0 [CLEANUP], 99thPercentileLatency(us), 53.0
關注幾個信息:
RunTime(ms): 數據加載所用時間,單位毫秒(ms)
Throughput(ops/sec): 吞吐量,即ops(每秒操作次數)
Operations: 操作的總次數
AverageLatency(us): 平均響應延時,單位是微秒(us)
MinLatency(us): 最小響應時間,單位是微秒(us)
MaxLatency(us): 最大響應時間,單位是微秒(us)
95thPercentileLatency(us): 95%的操作延時,單位是微秒(us)
99thPercentileLatency(us): 99%的操作延時,單位是微秒(us)
Return=OK: 成功返回數,這個值不符合測試要求,則證明測試失敗.
[READ]開頭的代表只讀的操作記錄,其他還有例如上面的[insert],[UPDATE]等,
其他可以理解的就是字面意思,不能理解也不需要太過關注.
和其他測試軟件一樣,這個只能說是基準值,并不是標準值,和真實環境不能全部模擬,所以測試的思維要結合別的測試軟件的方法來做.
測試總結
經過對5分片/7分片的1億/3億數據的測試來看,其實mongodb的OPS并沒有明顯提升,但是可以看到cpu負載長期屬于低狀態,而磁盤壓力也沒有跑滿,內存剩余還算多,所以分片的真正意義是提高了并發能力.
5分片1億只讀數據圖表:
單臺分片的iops值,

單臺分片磁盤利用率,

單臺分片cpu使用率,

測試集群ops值,

測試集群平均延時,單位是微秒(us)

7分片1億只讀數據圖表:
單臺分片的iops值,

單臺分片磁盤利用率,

單臺分片cpu使用率,

測試集群ops值,

測試集群平均延時,單位是微秒(us)

7分片3億只讀數據圖表:
單臺分片的iops值,

單臺分片磁盤利用率,

單臺分片cpu使用率,

測試集群ops值,

測試集群平均延時,單位是微秒(us)

補充信息
1.創建副本集
config端的副本集:
一個架構穩定的分片集群,應該需要多個節點副本集,防止一掛全掛現象,這是對數據安全的基本要求.而上面我們也談到一點,在3.4版本之后,mongos的啟動已經強制使用config端的副本集模式,如果沒有副本集,你也是啟動不起來的,所以這里特別補充一下.
首先,說說在3.4情況下,我們的config端必須要建立副本集,所以要在config端設置,就是上面強調的一個參數replSet
#打開config的配置文件 vim /usr/local/mongodb/mongod_config_20000.conf . . . #開啟副本集功能,并指定副本集名稱為configs replSet=configs
當然,上面也說了,至少要1個或3個config端,那么我們需要開啟三個config端,具體配置不詳細解析,也不要吐槽為什么放一起,只是測試而已.
#看一下有多少個配置文件
ll /usr/local/mongodb/
drwxr-xr-x. 2 root root 248 Mar 14 10:21 bin
-rw-r--r--. 1 root root 34520 Feb 23 03:53 GNU-AGPL-3.0
-rw-r--r--. 1 root root 622 Mar 14 14:26 mongod_config_20000.conf
-rw-r--r--. 1 root root 622 Mar 14 14:28 mongod_config_20001.conf
-rw-r--r--. 1 root root 622 Mar 14 14:35 mongod_config_20002.conf
-rw-r--r--. 1 root root 419 Mar 14 14:41 mongos_route_30000.conf
#看一下運行的mongo進程
ps aux |grep mongo
root 17211 1.1 0.7 1718800 60916 ? Sl 14:36 1:57 mongod -f /usr/local/mongodb/mongod_config_20000.conf
root 17244 1.0 0.7 1551432 58216 ? Sl 14:36 1:41 mongod -f /usr/local/mongodb/mongod_config_20001.conf
root 17277 1.0 0.7 1551432 57920 ? Sl 14:36 1:40 mongod -f /usr/local/mongodb/mongod_config_20002.conf
#看一下當前端口情況
ss -ntplu |grep mongo
tcp LISTEN 0 128 *:20000 *:* users:(("mongod",pid=17211,fd=11))
tcp LISTEN 0 128 *:20001 *:* users:(("mongod",pid=17244,fd=11))
tcp LISTEN 0 128 *:20002 *:* users:(("mongod",pid=17277,fd=11))三臺都可以用了,但是也只是創建了而已,關聯關系還是要做初始化,就像mysql的change master的意思一樣.
#連接其中一臺config端
mongo --port 20000
#輸入命令,添加關聯關系
>config = {_id:"configs",members:[{_id:0, host:"10.21.1.205:20000" },{_id:1, host:"10.21.1.205:20001" },{_id:2, host:"10.21.1.205:20002" }]}
#初始化副本集
rs.initiate(config)要注意出現 "ok" : 1, 那才是成功初始化,不成功就需要看看哪里出了問題,包括權限.
chown -R mongodb:mongodb /data/mongodb/
然后再次啟動,就ok了,那就可以用了,愉快的使用mongos啟動router端吧.
節點分片的副本集:
如果是節點分片的副本集則有點不一樣,參數是一樣要加的.
#編輯配置文件 vim /usr/local/mongodb/mongod_data_40001.conf . . . #開啟副本集功能,并指定副本集名稱為shard1 replSet=shard1
這里倒沒有強制你用多少個副本集,兩個三個十個都可以,只要你覺得有必要,這里也就不詳細描述了.但是關聯關系,那當然是必須的.
#連接其中一臺節點
mongo --port 40001
#進入管理數據庫admin
>use admin
#輸入命令,添加關聯關系,和上面不同的點也是這里,
>config = { _id : "shard1", members : [ {_id : 0, host : "10.21.1.208:40001" }, {_id : 1, host : "10.21.1.208:40002" }, {_id : 2, host : "10.21.1.208:40003" , arbiterOnly: true } ]}
#初始化副本集,這里是一樣的
rs.initiate(config)不同的點就是arbiterOnly參數,表示這個成員為仲裁節點,不接收數據.使用他的原因是當副本集發生故障時,需要一個仲裁機制來決定誰頂上來接收新的數據,屬于故障切換機制,還是比較嚴密的.
節點副本集添加分片:
另外,由于創建了副本集,分片添加有點不一樣了,刪除倒是一樣的,按分片名字就好了.
#副本集模式添加分片的方式
sh.addShard("shard1/10.21.1.208:40001,10.21.1.208:40002,10.21.1.208:40003")免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。