最近有個業務場景儲存壓力很大,寫遠遠大於讀,讀也集中在最近寫入,想想這不很適合採用leveldb儲存麼。leveldb的話好像用ssdb比較多,花了兩天時間就ssdb簡單做下測試,以下總結。
ssdb 是對leveldb儲存引擎的redis相容協議封裝,並且實現了主從同步,原始碼不多易讀。對於支援的操作,除了get/set kv儲存,由於 leveldb 是有序的,還可實現很多操作;通過scan遍歷的命令,利用有序性 list、hset也通過key+fileld/seq - val 方式儲存,ttl 會單獨儲存乙個hset 儲存過期時間,由乙個單獨執行緒定時輪詢刪除。
leveldb 參考:
機器:兩台r720xd e5-2620 2.1g (6核12執行緒)*2/記憶體128gb/300gb機械硬碟
資料: key: key 10位順序數字 value: 50位元組
併發: 預設情況100連線併發
客戶端: 使用erlang erdis模組get/set
配置:leveldb:
cache_size: 500
block_size: 1
write_buffer_size: 64
compression: no
max_open_files: 1000
- 檔案大小:1.3gb
- 寫速度:7w/s cpu 250% mem:30m
- 隨機讀: 5.5w/s cpu 100% mem:1gb
- 併發讀寫1:10: 讀 5k/s 寫:5w/s,cpu 250%
- 檔案大小:9.6gb
- 寫速度:7w/s cpu: 250% mem:70m
- 隨機讀: 1.6w/s cpu:100% mem:70m
-併發讀寫:1: 10: 4k/s 讀 5w/s 寫 cpu: 250%
總結:讀太隨機的lru cache 無法有效快取任何資料,請求都要經過檔案系統讀取,效能下降;但寫保效能持不變
- 檔案大小:66gb
- 寫速度:7w/s cpu:250% mem:80m
- 隨機讀: 1.6w/s cpu:180% mem:80m
-併發讀寫:1: 10: 4k/s 讀:5w/s 寫:280%
總結:和1.5億級別效果保持一致
leveldb預設快取meta data、和8m的block;本次測試使用了500m block_cache,從測試效果看,因為隨機讀,cache只在2k資料級別上起到作用,且帶來很高效能提公升。
1.5億、10億時,完全依賴kernel 對檔案系統的page cache,機器有128gb記憶體,leveldb 沒有使用direct io,檔案都快取,實際執行中不會有磁碟io。
那麼使用指令碼清理:
while true; do echo 1 > /proc/sys/vm/drop_caches;echo clean cache ok; sleep 1; done
- 隨機讀 約160/s cpu: 5% mem: 120m iostat 95%util
- 1併發隨機讀,100併發寫:90/s 讀, 1500/s 寫,隨機讀取影響寫入速度
總結:隨機io在機械硬碟上是完全無解了,只能靠cache扛,相比page cache,block_cache 更有效,應該更加需求增加bock_cache。
相比增加記憶體,使用ssd硬碟成本更低。
讀取系統呼叫:
open("./var/data/006090.ldb", o_rdonly) = 27
stat("./var/data/006090.ldb", ) = 0
mmap(null, 34349641, prot_read, map_shared, 27, 0) = 0x7f0334f76000
madvise(0x7f040457e000, 737280, madv_dontneed) = 0
munmap(0x7f03dc2ab000, 34349599) = 0
close(27) = 0
ssdb 是多執行緒的,但上面測試效果看有明顯多核利用率很低問題,從原始碼看可以知道:
- 1個主線程,負責網路io
- 10個讀執行緒,負責像scan複雜操作讀
- 1個寫執行緒,負責寫操作磁碟io
- 1個leveldb 的compact執行緒
也就是:乙個主線程負責網路,乙個寫執行緒負責leveldb操作;而讀 get 只主線程在工作。
- 10個執行緒處理讀:2.5/s cpu 450%
60%消耗在sys,高併發讀檔案對核心瓶頸
- 減小至3個執行緒處理讀:3.2w/s 280%(相比10執行緒,更少的cpu消耗,更高的效能)
- 使用lrucahce 在1kw區間隨機讀 7w/s ,200%cpu
leveldb 更新前先寫日誌方式,但預設方式日誌mmap是不會做msync,也就是完全依賴作業系統刷磁碟,這樣存在機器掉電等意外故障時可能會丟失部分最新訊息。支援leveldb:writeoptions.sync可選引數,但ssdb預設false,改為需要修改**。
修改true後,奇怪效能無變化?**上看並不是每個寫都會msync,而是4kbuffer後刷一次。
那麼leveldb 在故障時可能丟時少量數量就是沒辦法的了,如需要強可靠需要注意。
測測msync速度怎麼樣呢?
簡單單執行緒c程式,每寫100位元組做一次msync,效果:
伺服器2w/s, 我的mac pro ssd 3w/s (此時ssd也沒太大優勢)
msync 每次都做的話,肯定是有較大的效能影響的,但是可以做group msync;group msync 會增加延時,就看可接受都少了,如0.1ms,那就就可以以1w/s 脈衝式、批量sync磁碟,保證所有請求都寫入磁碟再返回。
leveldb 的寫入、修改、刪除都是支援優化的batch操作,使用multi_set命令。
1. 寫效能
測試中,寫入速度一直維持7w/s, 可滿足到多需求, leveldb 寫入可以到40w/s, 這裡受限於ssdb 執行緒模型無法利用更多的核心。需要的話通過pipline、網絡卡中斷平衡、提高網路、leveldb寫執行緒數 來提高寫入效能。
2. 讀效能
一般業務都存在資料熱點,可調整cache_size, block_size 提高快取命中率,block_size 為快取塊大小1k~4m視具體業務value而定。
如果業務熱點度不高,那只能上ssd硬碟了。
注意使用了page cache,不小心清空會讓效能急劇下降,還是盡量配置足夠大的cache_size。還有就是啟動有個預熱過程。
3. compaction
本次使用的順序key寫入,因為業務上key 都是順序的,然後一段時間從後往前順序刪除。compaction影響會很小,如果業務大量隨機key寫入、修改、刪除會增加compaction量,需要注意另外做壓力測試。
效能使用指令
vmstat 1 總的cpu利用率 mpstat p all 1 每個cpu核的利用率 top pidstat 每個程序的cpu利用率 資訊 proc stat proc pid stat 檢視網路流量 sar n dev 1 100 網絡卡流量 sar n edev 1 100 網絡卡丟包 資料 ...
提高sql查詢效能 使用instr函式替換like
在查詢時經常使用like作為關鍵字進行模糊查詢,在生產環境中由於資料量較大,使用like查詢時比較慢,嘗試了一些方法,最終發現使用oracle的instr函式可以顯著提高查詢的效率.關於資料量 selectcount 1 fromt partner role 612565 selectcount 1...
pdfcrop不能使用
最近,用到了pdfcrop,用來去除pdf中空白的邊。但是使用pdfcrop margins 0 pdf 後,給出了錯誤 error pdfcrop cannot call ghostscript 但是我已經安裝了ctex,裡面已經包含ghostscript,所以就不知道什麼錯誤。在網上針對這個問題...