使用SSD做KV存儲(chǔ)時(shí)發(fā)現(xiàn)磁盤IO非常低。配置成RAID10的性能只有3~6MB/s;配置成RAID0的性能有~130MB/s,系統(tǒng)中沒有發(fā)現(xiàn)CPU,MEM,中斷等瓶頸。一臺(tái)服務(wù)器從RAID1改成RAID0后,性能只有~60MB/s。這說明我們用的SSD盤性能不穩(wěn)定。
根據(jù)以上現(xiàn)象,初步懷疑以下幾點(diǎn):SSD盤,線上系統(tǒng)用的三星840Pro是消費(fèi)級(jí)硬盤。RAID卡設(shè)置,Write back和Write through策略。后來測(cè)試驗(yàn)證,有影響,但不是關(guān)鍵。RAID卡類型,線上系統(tǒng)用的是LSI 2008,比較陳舊。
本實(shí)驗(yàn)使用dd順序?qū)懖僮骱?jiǎn)單測(cè)試,嚴(yán)格測(cè)試需要用FIO等工具。
我們對(duì)于存儲(chǔ)選型時(shí)嘗試過LevelDB、RocksDB、BeansDB、LMDB、Riak等,最終根據(jù)我們的需求選擇了LMDB。
機(jī)器:2臺(tái)
配置:32核CPU、32GB內(nèi)存、SSD((512GB)三星840Pro--> (600GB)Intel 3500 /Intel S3610)
數(shù)據(jù):1.7億數(shù)據(jù)(800多G數(shù)據(jù))、大小5~30KB左右
KV存儲(chǔ)引擎:LevelDB、RocksDB、LMDB,每臺(tái)啟動(dòng)2個(gè)實(shí)例
壓測(cè)工具:tcpcopy直接線上導(dǎo)流
壓測(cè)用例:隨機(jī)寫+隨機(jī)讀
LevelDB壓測(cè)時(shí),隨機(jī)讀+隨機(jī)寫會(huì)產(chǎn)生抖動(dòng)(我們的數(shù)據(jù)出自自己的監(jiān)控平臺(tái),分鐘級(jí)采樣)。
RocksDB是改造自LevelDB,對(duì)SSD做了優(yōu)化,我們壓測(cè)時(shí)單獨(dú)寫或讀,性能非常好,但是讀寫混合時(shí)就會(huì)因?yàn)闅w并產(chǎn)生抖動(dòng)。??
LMDB引擎沒有大的抖動(dòng),基本滿足我們的需求。
我們目前一些線上服務(wù)器使用的是LMDB,其他一些正在嘗試公司自主研發(fā)的CycleDB引擎。
Jimdb數(shù)據(jù)同步時(shí)要dump數(shù)據(jù),SSD盤容量用了50%以上,dump到同一塊磁盤容量不足。解決方案:
1、一臺(tái)物理機(jī)掛2塊SSD(512GB),單掛raid0;啟動(dòng)8個(gè)jimdb實(shí)例;這樣每實(shí)例差不多125GB左右;目前是掛4塊,raid0;新機(jī)房計(jì)劃8塊raid10;
2、目前是千兆網(wǎng)卡同步,同步峰值在100MB/s左右;
3、dump和sync數(shù)據(jù)時(shí)是順序讀寫,因此掛一塊SAS盤專門來同步數(shù)據(jù);
4、使用文件鎖保證一臺(tái)物理機(jī)多個(gè)實(shí)例同時(shí)只有一個(gè)dump;
5、后續(xù)計(jì)劃改造為直接內(nèi)存轉(zhuǎn)發(fā)而不做dump。
之前存儲(chǔ)架構(gòu)是一主二從(主機(jī)房一主一從,備機(jī)房一從)切換到備機(jī)房時(shí),只有一個(gè)主服務(wù),讀寫壓力大時(shí)有抖動(dòng),因此我們改造為之前架構(gòu)圖中的一主三從。
之前的架構(gòu)是分片邏輯分散到多個(gè)子系統(tǒng)的配置文件中,切換時(shí)需要操作很多系統(tǒng);解決方案:
1、引入Twemproxy中間件,我們使用本地部署的Twemproxy來維護(hù)分片邏輯;
2、使用自動(dòng)部署系統(tǒng)推送配置和重啟應(yīng)用,重啟之前暫停mq消費(fèi)保證數(shù)據(jù)一致性;
3、用unix domain socket減少連接數(shù)和端口占用不釋放啟動(dòng)不了服務(wù)的問題。
起初不確定Lua做邏輯和渲染模板性能如何,就盡量減少for、if/else之類的邏輯;通過java worker組裝html片段存儲(chǔ)到j(luò)imdb,html片段會(huì)存儲(chǔ)諸多問題,假設(shè)未來變了也是需要全量刷出的,因此存儲(chǔ)的內(nèi)容最好就是元數(shù)據(jù)。因此通過線上不斷壓測(cè),最終jimdb只存儲(chǔ)元數(shù)據(jù),lua做邏輯和渲染;邏輯代碼在3000行以上;模板代碼1500行以上,其中大量for、if/else,目前渲染性能可以接受。
線上真實(shí)流量,整體性能從TP99 53ms降到32ms。
綁定8 CPU測(cè)試的,渲染模板的性能可以接受。
商品詳情頁(yè)庫(kù)存接口2014年被惡意刷,每分鐘超過600w訪問量,tomcat機(jī)器只能定時(shí)重啟;因?yàn)槭窃斍轫?yè)展示的數(shù)據(jù),緩存幾秒鐘是可以接受的,因此開啟nginx proxy cache來解決該問題,開啟后降到正常水平;我們目前正在使用Nginx+Lua架構(gòu)改造服務(wù),數(shù)據(jù)過濾、URL重寫等在Nginx層完成,通過URL重寫+一致性哈希負(fù)載均衡,不怕隨機(jī)URL,一些服務(wù)提升了10%+的緩存命中率。
通過訪問日志發(fā)現(xiàn)某IP頻繁抓??;而且按照商品編號(hào)遍歷,但是會(huì)有一些不存在的編號(hào);解決方案:
1、讀取KV存儲(chǔ)的部分不限流;
2、回源到服務(wù)接口的進(jìn)行請(qǐng)求限流,保證服務(wù)質(zhì)量。
開啟Nginx Proxy Cache后,性能下降,而且過一段內(nèi)存使用率到達(dá)98%;解決方案:
1、對(duì)于內(nèi)存占用率高的問題是內(nèi)核問題,內(nèi)核使用LRU機(jī)制,本身不是問題,不過可以通過修改內(nèi)核參數(shù)
sysctl -w vm.extra_free_kbytes=6436787
sysctl -w vm.vfs_cache_pressure=10000
2、使用Proxy Cache在機(jī)械盤上性能差可以通過tmpfs緩存或nginx共享字典緩存元數(shù)據(jù),或者使用SSD,我們目前使用內(nèi)存文件系統(tǒng)。
配送至服務(wù)每天有數(shù)十億調(diào)用量,響應(yīng)時(shí)間偏慢。解決方案:
1、串行獲取變并發(fā)獲取,這樣一些服務(wù)可以并發(fā)調(diào)用,在我們某個(gè)系統(tǒng)中能提升一倍多的性能,從原來TP99差不多1s降到500ms以下;
2、預(yù)取依賴數(shù)據(jù)回傳,這種機(jī)制還一個(gè)好處,比如我們依賴三個(gè)下游服務(wù),而這三個(gè)服務(wù)都需要商品數(shù)據(jù),那么我們可以在當(dāng)前服務(wù)中取數(shù)據(jù),然后回傳給他們,這樣可以減少下游系統(tǒng)的商品服務(wù)調(diào)用量,如果沒有傳,那么下游服務(wù)再自己查一下。
假設(shè)一個(gè)讀服務(wù)是需要如下數(shù)據(jù):
1、數(shù)據(jù)A ?10ms
2、數(shù)據(jù)B ?15ms
3、數(shù)據(jù)C ? 20ms
4、數(shù)據(jù)D ? 5ms
5、數(shù)據(jù)E ? 10ms
那么如果串行獲取那么需要:60ms;
而如果數(shù)據(jù)C依賴數(shù)據(jù)A和數(shù)據(jù)B、數(shù)據(jù)D誰也不依賴、數(shù)據(jù)E依賴數(shù)據(jù)C;那么我們可以這樣子來獲取數(shù)據(jù):
那么如果并發(fā)化獲取那么需要:30ms;能提升一倍的性能。
假設(shè)數(shù)據(jù)E還依賴數(shù)據(jù)F(5ms),而數(shù)據(jù)F是在數(shù)據(jù)E服務(wù)中獲取的,此時(shí)就可以考慮在此服務(wù)中在取數(shù)據(jù)A/B/D時(shí)預(yù)取數(shù)據(jù)F,那么整體性能就變?yōu)榱耍?5ms。
通過這種優(yōu)化我們服務(wù)提升了差不多10ms性能。
如下服務(wù)是在抖動(dòng)時(shí)的性能,老服務(wù)TP99 211ms,新服務(wù)118ms,此處我們主要就是并發(fā)調(diào)用+超時(shí)時(shí)間限制,超時(shí)直接降級(jí)。
Twemproxy配置的timeout時(shí)間太長(zhǎng),之前設(shè)置為5s,而且沒有分別針對(duì)連接、讀、寫設(shè)置超時(shí)。后來我們減少超時(shí)時(shí)間,內(nèi)網(wǎng)設(shè)置在150ms以內(nèi),當(dāng)超時(shí)時(shí)訪問動(dòng)態(tài)服務(wù)。
2014年雙11期間,服務(wù)器網(wǎng)卡流量到了400Mbps,CPU 30%左右。原因是我們所有壓縮都在接入層完成,因此接入層不再傳入相關(guān)請(qǐng)求頭到應(yīng)用,隨著流量的增大,接入層壓力過大,因此我們把壓縮下方到各個(gè)業(yè)務(wù)應(yīng)用,添加了相應(yīng)的請(qǐng)求頭,Nginx GZIP壓縮級(jí)別在2~4吞吐量最高;應(yīng)用服務(wù)器流量降了差不多5倍;目前正常情況CPU在4%以下。
更多建議: