成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

提升node.js中使用redis的性能

verano / 3385人閱讀

摘要:因此這種方式可以有效減少響應(yīng)次數(shù),從而減少觸發(fā)事件的次數(shù),盡可能快的拿到響應(yīng)體。

問題初現(xiàn)

某基于node.js開發(fā)的業(yè)務(wù)系統(tǒng)向外提供了一個(gè)dubbo服務(wù),提供向第三方緩存查詢、設(shè)置多項(xiàng)業(yè)務(wù)數(shù)據(jù)并聚合操作結(jié)果。在QPS達(dá)到800時(shí)(兩臺(tái)虛擬機(jī),每臺(tái)機(jī)器4Core8G4node進(jìn)程),在監(jiān)控平臺(tái)上出現(xiàn)了非常多的slow rt警告,平均接口響應(yīng)達(dá)到60+ms,請(qǐng)求報(bào)警率達(dá)到80%+。

為找到造成該服務(wù)吞吐量過低的罪魁禍?zhǔn)祝瑯I(yè)務(wù)人員在請(qǐng)求日志中打點(diǎn)了所有查詢緩存的操作,結(jié)果顯示每個(gè)請(qǐng)求查詢緩存耗時(shí)在50-100ms之間跳動(dòng)。查詢了redis-server的監(jiān)控?cái)?shù)據(jù)發(fā)現(xiàn),不存在server端的慢查詢,在整個(gè)監(jiān)控區(qū)間內(nèi)服務(wù)端處理時(shí)間在40us徘徊,因此排除了redis-server的處理能力不足原因;

通過登錄內(nèi)網(wǎng)機(jī)器進(jìn)行不斷測(cè)試到對(duì)應(yīng)redis server機(jī)器的端到端時(shí)延發(fā)現(xiàn)內(nèi)部局域網(wǎng)的帶寬、時(shí)延與抖動(dòng)足夠正常,都不是造成該問題的原因。

因此,錯(cuò)誤原因定位到了調(diào)用redis client的業(yè)務(wù)代碼以及redis client的I/O性能

本文中提到的node redis client采用的基于node-redis封裝的二方包,因此問題排查也基于node-redis這個(gè)模塊。
瓶頸在哪

為了在本地模擬線上環(huán)境的并發(fā),可以做一個(gè)不是很嚴(yán)謹(jǐn)?shù)臏y(cè)試:

async  ()=>{
    let  dd  =  Date.now()
    let  arr  = []
    for(let  i=0;i<200;i++){
        arr.push(new Promise((res,rej)=>{
            let  hrtime  = process.hrtime();
            client.send_command("get",["key"], function(e,r) {
            let  diff  = process.hrtime(hrtime);
            let  cost  = (diff[0] *  NS_PER_SEC  +  diff[1])/1000000;
            console.log(`final: ${cost} ms`)
            res();
            });
        }));
    }
    await  Promise.all(arr)
    console.log("ops/sec:",200*1000/(Date.now() -  dd),Date.now() -  dd);
}

會(huì)發(fā)現(xiàn)每個(gè)請(qǐng)求的rt都會(huì)比前一個(gè)請(qǐng)求來的大
](https://si.geilicdn.com/viewm...
最后一個(gè)請(qǐng)求的rt竟然達(dá)到了257 ms!雖然在node單進(jìn)程像示例代碼那樣并發(fā)執(zhí)行200次get請(qǐng)求是非常少見而且愚蠢的(關(guān)于示例代碼的優(yōu)化在在下節(jié)講述),但是針對(duì)這個(gè)示例必須找到請(qǐng)求delay增加的原因。
為此繼續(xù)分析,redis client采用的是單連接模式,底層采用的非阻塞網(wǎng)絡(luò)I/O,socket.recv()在node層面是通過監(jiān)聽socket的data事件完成的,因此先分析redis-client讀性能如何:
](https://si.geilicdn.com/viewm...
上圖每段日志的含義分別表示:

- data events trigger times: socket data事件觸發(fā)的次數(shù)
- data event start from prevent event: data事件距離上次觸發(fā)的時(shí)間間隔
- data events exec time(ms): 本次事件處理函數(shù)執(zhí)行時(shí)間

上圖只是截取了最初的請(qǐng)求日志,發(fā)現(xiàn)當(dāng)?shù)?次觸發(fā)data事件時(shí),竟然距離上次觸發(fā)事件隔了35ms,在隨后的請(qǐng)求中會(huì)復(fù)現(xiàn)這種現(xiàn)象,因此這也就導(dǎo)致了在并發(fā)200次查詢請(qǐng)求時(shí),每個(gè)請(qǐng)求的rt都會(huì)隨之增大,并且有些響應(yīng)之間間隔了30ms。

從表象看造成問題在于redis-server發(fā)送的響應(yīng)不是一個(gè)數(shù)據(jù)塊,而是多個(gè)數(shù)據(jù)塊導(dǎo)致觸發(fā)socket的data事件過多,而且data事件抖動(dòng)過大導(dǎo)致響應(yīng)之間存在30ms的突變(data事件是無法同時(shí)觸發(fā)兩次的,每次data事件處理函數(shù)執(zhí)行完后才能繼續(xù)觸發(fā)下一個(gè)data事件);當(dāng)然也有可能和socket寫入(即發(fā)送req)有關(guān),如緩存請(qǐng)求等。為了繼續(xù)探查,監(jiān)控與socket寫入相關(guān)的接口 _write(),記錄每次寫入socket的數(shù)據(jù)時(shí)距離上一次寫入的間隔:
](https://si.geilicdn.com/viewm...
可見,在使用redis-client發(fā)送請(qǐng)求時(shí),write方法也不是瓶頸。

采用同樣方法,對(duì)socket的push()(該方法觸發(fā)socket的data事件)進(jìn)行監(jiān)控,發(fā)現(xiàn)socket的數(shù)據(jù)到達(dá)間隔抖動(dòng)非常大:
](https://si.geilicdn.com/viewm...
因此,造成redis-client并發(fā)請(qǐng)求下響應(yīng)rt抖動(dòng)較大的情況與單連接下響應(yīng)數(shù)據(jù)到達(dá)本地的時(shí)刻有關(guān),具體可能與底層libuv的緩存策略有關(guān)(筆者并未再往下探查)。
](https://si.geilicdn.com/viewm...

在一個(gè)node實(shí)例中通過一個(gè)單連接與redis server通信,在高并發(fā)下會(huì)出現(xiàn)排隊(duì)等待響應(yīng)的情況,并且有可能會(huì)出現(xiàn)響應(yīng)rt雪崩效應(yīng)(如上文demo所示),因此需要盡可能減少或緩存客戶端的請(qǐng)求數(shù)量,進(jìn)行批量發(fā)送。

調(diào)優(yōu)
1. pipeline(涉及到寫模式及時(shí)序)
2. script

對(duì)于pipeline方式,redis server是默認(rèn)支持的。通俗點(diǎn)說,pipeline可以合并一系列請(qǐng)求一次發(fā)送,并將這些請(qǐng)求對(duì)應(yīng)的結(jié)果一次性拿到。因此這種方式可以有效減少響應(yīng)次數(shù),從而減少socket觸發(fā)data事件的次數(shù),盡可能快的拿到響應(yīng)體。
](https://si.geilicdn.com/viewm...
需要強(qiáng)調(diào)的是,在node中,是通過底層socket的_writev實(shí)現(xiàn)一次發(fā)送多條redis命令的,_writev又叫做聚合寫,它支持將不同緩沖區(qū)的多條數(shù)據(jù)通過一次系統(tǒng)調(diào)用寫入目標(biāo)流,因此性能上比每次寫單個(gè)緩沖區(qū)的單個(gè)數(shù)據(jù)來的好得多。在node的Writeable對(duì)象中,有cork和uncork方法,通過這兩個(gè)方法可以在node write stream中緩存多條數(shù)據(jù),通過_writev一次性發(fā)送。

關(guān)于 _writev的數(shù)據(jù)結(jié)構(gòu)

redis在拿到數(shù)據(jù)后,根據(jù)resp協(xié)議解析出命令集合緩存在隊(duì)列中,直到收到exec命令,開始批量執(zhí)行命令集,并將所有命令執(zhí)行的結(jié)果轉(zhuǎn)換為數(shù)組返回給redis client。這樣就可以通過一次寫、一次讀實(shí)現(xiàn)高性能I/O。

async  ()=>{
    let  dd  =  Date.now()
    let  batch  =  await client.batch();
    for(let  i=0;i<200;i++){
        batch.get("vdWeex_com.koudai.weidian.buyer_1");
    }
    let rt = await batch.exec();
    process.exit();
}

而對(duì)于script方法,則是由redis client傳入script命令,在server端執(zhí)行script邏輯,批量執(zhí)行命令,并返回結(jié)果。同樣是一次寫、一次讀。

收獲
1. node socket默認(rèn)采用writev 集合寫
2. 無依賴批量請(qǐng)求采用pipeline
3. eval script解決有依賴批量請(qǐng)求    
4. redis高性能體現(xiàn)在服務(wù)端處理能力,但瓶頸往往出現(xiàn)在客戶端,因此增強(qiáng)客戶端I/O能力與并發(fā)并行多客戶端才是高并發(fā)解決方案

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98909.html

相關(guān)文章

  • 記一次Node項(xiàng)目優(yōu)化

    摘要:相關(guān)環(huán)境由于是一個(gè)幾年前的項(xiàng)目,所以使用的是這樣的。一些小提示本次優(yōu)化筆記,并不會(huì)有什么文件的展示。將異步改為了串行,喪失了作為異步事件流的優(yōu)勢(shì)。 這兩天針對(duì)一個(gè)Node項(xiàng)目進(jìn)行了一波代碼層面的優(yōu)化,從響應(yīng)時(shí)間上看,是一次很顯著的提升。 一個(gè)純粹給客戶端提供接口的服務(wù),沒有涉及到頁面渲染相關(guān)。 背景 首先這個(gè)項(xiàng)目是一個(gè)幾年前的項(xiàng)目了,期間一直在新增需求,導(dǎo)致代碼邏輯變得也比較復(fù)雜,接...

    dreamans 評(píng)論0 收藏0
  • [譯]Express在生產(chǎn)環(huán)境下最佳實(shí)踐 - 性能和可靠性

    摘要:前言這將是一個(gè)分為兩部分,內(nèi)容是關(guān)于在生產(chǎn)環(huán)境下,跑應(yīng)用的最佳實(shí)踐。第一部分會(huì)關(guān)注安全性,第二部分則會(huì)關(guān)注性能和可靠性。關(guān)于第一部分,請(qǐng)參閱在生產(chǎn)環(huán)境下的最佳實(shí)踐安全性。 前言 這將是一個(gè)分為兩部分,內(nèi)容是關(guān)于在生產(chǎn)環(huán)境下,跑Express應(yīng)用的最佳實(shí)踐。第一部分會(huì)關(guān)注安全性,第二部分則會(huì)關(guān)注性能和可靠性。當(dāng)你讀這篇文章時(shí),會(huì)假設(shè)你已經(jīng)對(duì)Node.js和web開發(fā)有所了解,并且對(duì)生產(chǎn)環(huán)...

    Luosunce 評(píng)論0 收藏0
  • Node.js運(yùn)行原理、高并發(fā)性能測(cè)試對(duì)比及生態(tài)圈匯總

    摘要:模式,單實(shí)例多進(jìn)程,常用于多語言混編,比如等,不支持端口復(fù)用,需要自己做應(yīng)用的端口分配和負(fù)載均衡的子進(jìn)程業(yè)務(wù)代碼。就是我們需要一個(gè)調(diào)度者,保證所有后端服務(wù)器都將性能充分發(fā)揮,從而保持服務(wù)器集群的整體性能最優(yōu),這就是負(fù)載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    kamushin233 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<