Mongodb千萬級資料在python下的綜合壓力測試及應用探討
曾經在收集資料的專案中,用過mongodb的資料儲存,但是當資料很大的時候,還是比較的吃力。很可能當時的應用水平不高,也可以是當時的伺服器不是很強。 所以這次能力比以前高點了,然後伺服器比以前也高端了很多,好嘞 ~再測試下。
(更多的是單機測試,沒有用複製分片的測試 ~)!
相比較MySQL,MongoDB資料庫更適合那些讀作業較重的任務模型。MongoDB能充分利用機器的記憶體資源。如果機器的記憶體資源豐富的話,MongoDB的查詢效率會快很多。
這次測試的伺服器是dell 的 r510!
記憶體還行,是48G的,本來想讓同事給加滿,但是最終還是沒有說出口 ~
磁碟是10個2T的,但是因為格式化的時間太久了,哥們直接把其他的硬碟給拔出來了,就用了三個盤。。。data目錄沒有做raid,是為了讓他們體現更好的硬碟速度。
既然說好了是在python下的應用測試,那就需要安裝mongodb python下的模組 !
對了,不知道mongodb-server的安裝要不要說下?
cat/etc/yum.repos.d/10.repo [10gen] name=10genRepository baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64 gpgcheck=0
Pymongo的基本用法
frompymongoimport*#導包 con=Connection(...)#連結 db=con.database#連結資料庫 db.authenticate('username','password')#登入 db.drop_collection('users')#刪除表 db.logout()#退出 db.collection_names()#檢視所有表 db.users.count()#查詢數量 db.users.find_one({'name':'xiaoming'})#單個物件 db.users.find({'age':18})#所有物件 db.users.find({'id':64},{'age':1,'_id':0})#返回一些欄位預設_id總是返回的0不返回1返回 db.users.find({}).sort({'age':1})#排序 db.users.find({}).skip(2).limit(5)#切片
測試的程式碼:
#!/usr/bin/envpython frompymongoimportConnection importtime,datetime importos,sys connection=Connection('127.0.0.1',27017) db=connection['xiaorui'] deffunc_time(func): def_wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) printfunc.__name__,'run:',time.time()-start return_wrapper @func_time defainsert(num): posts=db.userinfo forxinrange(num): post={"_id":str(x), "author":str(x)+"Mike", "text":"Myfirstblogpost!", "tags":["xiaorui","xiaorui.cc","rfyiamcool.51cto"], "date":datetime.datetime.utcnow()} posts.insert(post) if__name__=="__main__": num=sys.argv[1] ainsert(int(num))
咱們就先來個百萬的資料做做測試~
綜合點的資料:
在top下看到的程式佔用資源的情況 ~ 我們看到的是有兩個程序的很突出,對頭 ! 正是mongodb的服務和我們正在跑的python指令碼 !
看下服務的io的情況 ~
指令碼執行完畢,總結下執行的時間 ~
檢視mongodb的狀態~
他的insert也不到5k ~ 插入量也就800k左右 ~
它的輸出有以下幾列:
inserts/s 每秒插入次數
query/s 每秒查詢次數
update/s 每秒更新次數
delete/s 每秒刪除次數
getmore/s 每秒執行getmore次數
command/s 每秒的命令數,比以上插入、查詢、更新、刪除的綜合還多,還統計了別的命令
flushs/s 每秒執行fsync將資料寫入硬碟的次數。
mapped/s 所有的被mmap的資料量,單位是MB,
vsize 虛擬記憶體使用量,單位MB
res 實體記憶體使用量,單位MB
faults/s 每秒訪問失敗數(只有Linux有),資料被交換出實體記憶體,放到swap。不要超過100,否則就是機器記憶體太小,造成頻繁swap寫入。此時要升級記憶體或者擴充套件
locked % 被鎖的時間百分比,儘量控制在50%以下吧
idx miss % 索引不命中所佔百分比。如果太高的話就要考慮索引是不是少了
q t|r|w 當Mongodb接收到太多的命令而資料庫被鎖住無法執行完成,它會將命令加入佇列。這一欄顯示了總共、讀、寫3個佇列的長度,都為0的話表示mongo毫無壓力。高併發時,一般佇列值會升高。
conn 當前連線數
time 時間戳
瞅下面的監控資料 !
然後我們在測試下在一千萬的資料下的消耗時間情況 ~
共用了2294秒,每秒插入 4359個數據 ~
虛擬記憶體在8gb左右,真實記憶體在2gb左右
再換成多執行緒的模式跑跑 ~ 個人不太喜歡用多執行緒,這東西屬於管你忙不忙,老大說了要公平,我就算搶到了,但是沒事幹,我也不讓給你。。。屬於那種蠻幹的機制 ~
nima,要比單個跑的慢呀 ~ 執行緒這東西咋會這麼不靠譜呀 ~
應該是沒有做執行緒池pool,拉取佇列。導致執行緒過多導致的。不然不可能比單程序都要慢~
還有就是像這些涉及到IO的東西,交給協程的事件框架更加合理點 !!!
defgoodinsert(a): posts.insert(a) defainsert(num): forxinrange(num): post={"_id":str(x), "author":str(x)+"Mike", "text":"Myfirstblogpost!", "tags":["mongodb","python","pymongo"], "date":datetime.datetime.utcnow()} #goodinsert(post) a=threading.Thread(target=goodinsert,args=(post,)) a.start()
python畢竟有gil的限制,雖然multiprocess號稱可以解決多程序的。但是用過的朋友知道,這個東西更不靠譜 ~ 屬於坑人的東西 ~
要是有朋友懷疑是python的單程序的效能問題,那咱們就用supervisord跑了幾個後臺的python壓力指令碼 ~ supervisord的配置我就不說了,我以前的文章裡面有詳述的 ~
cpu方面是跑的有點均勻了,但是mongodb那邊的壓力總是上不去
當加大到16個後臺程序做壓力測試的時候 ~ 大家會發現insert很不穩定。 看來他的極限也就是2MB左右的資料 ~
當減少到8個壓力程序的時候 ~ 我們發現他的insert慢慢的提供到正常了,也就是說 他真的是2MB的極限 ~
腳本里面是有做有序的id插入的,我們試試把id的插入給去掉,看看有沒有提升~
結果和不插入id差不多的結果 ~
調優之後~ 再度測試
ulimit的優化
cat/etc/security/limits.conf *softnofile102400 *hardnofile102400
核心的tcp優化
cat/etc/sysctl.conf net.ipv4.tcp_syncookies=1 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_tw_recycle=1 net.ipv4.tcp_timestsmps=0 net.ipv4.tcp_synack_retries=2 net.ipv4.tcp_syn_retries=2 net.ipv4.tcp_wmem=8192436600873200 net.ipv4.tcp_rmem=32768436600873200 net.ipv4.tcp_mem=945000009150000092700000 net.ipv4.tcp_max_orphans=3276800 net.ipv4.tcp_fin_timeout=30 #直接生效 /sbin/sysctl-p
啟動的時候,加上多核的優化引數
多核問題可以在啟動時加入啟動引數:numactl--interleave=all
insert的頻率已經到了2w左右 ~ 記憶體佔用了8G左右 ~
我想到的一個方案:
當然不用非要celery,就算咱們用socket寫分發,和zeromq的pub sub也可以實現這些的。這是celery的排程更加專業點。
剛才我們測試的都是insert,現在我們再來測試下在千萬級別資料量下的查詢如何:
查詢正則的,以2開頭的字元
posts=db.userinfo foriinposts.find({"author":re.compile('^2.Mike')}): printi
精確的查詢:
查詢在5s左右 ~
總結:
典型的高讀低寫資料庫 !
轉載於:https://blog.51cto.com/rfyiamcool/1329351