我為什么用ES做Redis監(jiān)控,不用Prometheus或Zabbix?
本文根據(jù)李猛老師在〖deeplus直播第220期〗線上分享演講內(nèi)容整理而成。
李猛
數(shù)據(jù)技術(shù)專家
Elastic-Stack產(chǎn)品深度用戶,ES認(rèn)證工程師,對(duì)Elastic-Stack開(kāi)發(fā)、架構(gòu)、運(yùn)維有深入體驗(yàn);
實(shí)踐過(guò)多種ES項(xiàng)目,最暴力的大數(shù)據(jù)分析應(yīng)用,最復(fù)雜的業(yè)務(wù)系統(tǒng)應(yīng)用。
圖示:Redis熱度排名
Redis當(dāng)下很流行,也很好用,無(wú)論是在業(yè)務(wù)應(yīng)用系統(tǒng),還是在大數(shù)據(jù)領(lǐng)域都有重要的地位;但Redis也很脆弱,用不好,問(wèn)題多多。2012年以前都是以memcached為主,之后轉(zhuǎn)到Redis陣營(yíng),經(jīng)歷過(guò)單實(shí)例模式、主從模式、哨兵模式、代理模式,集群模式,真正公司層面用得好的很少,對(duì)于Redis掌控都很片面,導(dǎo)致實(shí)際項(xiàng)目中問(wèn)題不少。
Redis要想用得好,需要整體掌握3個(gè)層面:
開(kāi)發(fā)層面
架構(gòu)層面
運(yùn)維層面
其中架構(gòu)與運(yùn)維至關(guān)重要,多數(shù)中小型企業(yè)僅在開(kāi)發(fā)層面滿足常用功能,數(shù)據(jù)規(guī)模稍微大些,業(yè)務(wù)復(fù)雜度高些,就容易出現(xiàn)各種架構(gòu)與運(yùn)維問(wèn)題。本文主旨是探討Redis監(jiān)控體系,目前業(yè)界當(dāng)然也有很多成熟的產(chǎn)品,但個(gè)人覺(jué)得都很常規(guī),只做到一些粗粒度的監(jiān)控, 沒(méi)有依據(jù)業(yè)務(wù)需求特點(diǎn)因地制宜去細(xì)化,從而反向的提供架構(gòu)開(kāi)發(fā)優(yōu)化方案。
本文內(nèi)容將圍繞如下幾個(gè)問(wèn)題展開(kāi)討論:
Redis監(jiān)控體系有哪些方面?
構(gòu)建Redis監(jiān)控體系我們做了哪些工作?
Redis監(jiān)控體系應(yīng)該細(xì)化到什么程度?
為什么使用ELK構(gòu)建監(jiān)控體系?
公司業(yè)務(wù)范圍屬于車聯(lián)網(wǎng)行業(yè),有上百萬(wàn)級(jí)的真實(shí)車主用戶,業(yè)務(wù)項(xiàng)目圍繞車主生活服務(wù)展開(kāi),為了提高系統(tǒng)性能,引入了Redis作為緩存中間件,具體描述如下:
部署架構(gòu)采用Redis-Cluster模式;
后臺(tái)應(yīng)用系統(tǒng)有幾十個(gè),應(yīng)用實(shí)例數(shù)超過(guò)二百個(gè);
所有應(yīng)用系統(tǒng)共用一套緩存集群;
集群節(jié)點(diǎn)數(shù)幾十個(gè),加上容災(zāi)備用環(huán)境,節(jié)點(diǎn)數(shù)量翻倍;
集群節(jié)點(diǎn)內(nèi)存配置較高。
圖示:Redis集群架構(gòu)與應(yīng)用架構(gòu)示意圖
系統(tǒng)剛開(kāi)始關(guān)于Redis的一切都很正常,隨著應(yīng)用系統(tǒng)接入越來(lái)越多,應(yīng)用系統(tǒng)子模塊接入也越來(lái)越多,開(kāi)始出現(xiàn)一些問(wèn)題,應(yīng)用系統(tǒng)有感知,集群服務(wù)端也有感知,如下描述:
集群節(jié)點(diǎn)崩潰;
集群節(jié)點(diǎn)假死;
某些后端應(yīng)用訪問(wèn)集群響應(yīng)特別慢。
其實(shí)問(wèn)題的根源都是架構(gòu)運(yùn)維層面的欠缺,對(duì)于Redis集群服務(wù)端的運(yùn)行監(jiān)控其實(shí)很好做,本身也提供了很多直接的命令方式,但只能看到服務(wù)端的一些常用指標(biāo)信息,無(wú)法深入分析,治標(biāo)不治本,對(duì)于Redis的內(nèi)部運(yùn)行一無(wú)所知,特別是對(duì)于業(yè)務(wù)應(yīng)用如何使用Redis集群一無(wú)所知:
Redis集群使用的熱度問(wèn)題?
哪些應(yīng)用占用的Redis內(nèi)存資源多?
哪些應(yīng)用占用Redis訪問(wèn)數(shù)最高?
哪些應(yīng)用使用Redis類型不合理?
應(yīng)用系統(tǒng)模塊使用Redis資源分布怎么樣?
應(yīng)用使用Redis集群的熱點(diǎn)問(wèn)題?
監(jiān)控的目的不僅僅是監(jiān)控Redis本身,而是為了更好的使用Redis。傳統(tǒng)的監(jiān)控一般比較單一化,沒(méi)有系統(tǒng)化,但對(duì)于Redis來(lái)說(shuō),個(gè)人認(rèn)為至少包括:一是服務(wù)端,二是應(yīng)用端,三是服務(wù)端與應(yīng)用端聯(lián)合分析。
服務(wù)端:
服務(wù)端首先是操作系統(tǒng)層面,常用的CPU、內(nèi)存、網(wǎng)絡(luò)IO,磁盤IO,服務(wù)端運(yùn)行的進(jìn)程信息等;
Redis運(yùn)行進(jìn)程信息,包括服務(wù)端運(yùn)行信息、客戶端連接數(shù)、內(nèi)存消耗、持久化信息 、鍵值數(shù)量、主從同步、命令統(tǒng)計(jì)、集群信息等;
Redis運(yùn)行日志,日志中會(huì)記錄一些重要的操作進(jìn)程,如運(yùn)行持久化時(shí),可以有效幫助分析崩潰假死的程序。
應(yīng)用端:
應(yīng)用端、獲取應(yīng)用端使用Redis的一些行為,具體哪些應(yīng)用哪些模塊最占用 Redis資源、哪些應(yīng)用哪些模塊最消耗Redis資源、哪些應(yīng)用哪些模塊用法有誤等。
聯(lián)合分析:
聯(lián)合分析結(jié)合服務(wù)端的運(yùn)行與應(yīng)用端使用的行為,如:一些造成服務(wù)端突然阻塞的原因,可能是應(yīng)用端設(shè)置了一個(gè)很大的緩存鍵值,或者使用的鍵值列表,數(shù)據(jù)量超大造成阻塞。
為什么會(huì)選擇Elastic-Stack技術(shù)棧呢?
多數(shù)的第三方只監(jiān)控一些指標(biāo),對(duì)于明細(xì)日志還是采用ELK(Elasticsearch、Logstash、Kibana),也就是說(shuō)用第三方監(jiān)控指標(biāo)之后,還得再搭建一個(gè)ELK集群看明細(xì)日志。
再就是說(shuō)Elastic-Stack技術(shù)棧整合的優(yōu)勢(shì),指標(biāo)也可以、日志文件也可以,從采集開(kāi)始到存儲(chǔ)、到最終報(bào)表面板都整合得非常好,門檻很低。
下面詳細(xì)聊聊我們具體怎么做的,做了哪些工作?
Elastic-Stack家族有Metricbeat產(chǎn)品,支持系統(tǒng)層面的信息收集,簡(jiǎn)單的配置下Elastic集群地址和系統(tǒng)指標(biāo)模塊即可上線,并且會(huì)在Kibana中創(chuàng)建已有的系統(tǒng)監(jiān)控面板,非常簡(jiǎn)單快速,一般運(yùn)維就可以搞定。
圖示:metrcibeat示意圖
系統(tǒng)指標(biāo)信息收集配置樣例如下:
收集Redis集群運(yùn)行信息,業(yè)界通常做法都是采用Redis提供的info命令,定期收集。
info獲取的信息包括如下:
server:Redis服務(wù)器的一般信息
clients:客戶端的連接部分
memory:內(nèi)存消耗相關(guān)信息
persistence:RDB和AOF相關(guān)信息
stats:一般統(tǒng)計(jì)
replication:主/從復(fù)制信息
cpu:統(tǒng)計(jì)CPU的消耗command
stats:Redis命令
統(tǒng)計(jì)cluster:Redis集群信息
keyspace:數(shù)據(jù)庫(kù)的相關(guān)統(tǒng)計(jì)
Elastic-Stack家族的Metricbeat產(chǎn)品也支持Redis模塊,也是采用info命令獲取的,但是有一些實(shí)現(xiàn)的局限性,如下描述:
Redis集群的主從關(guān)系信息,Metricbeats表達(dá)不出來(lái);
Redis集群的一些統(tǒng)計(jì)信息,永遠(yuǎn)是累計(jì)增加的,如命令數(shù),如果要獲取命令數(shù)的波峰值,則無(wú)法得到;
Redis集群狀態(tài)信息變化,Metricbeats是無(wú)法動(dòng)態(tài)的,如集群新增節(jié)點(diǎn)、下線節(jié)點(diǎn)等。
所以這里參考了CacheCloud產(chǎn)品(搜狐團(tuán)隊(duì)開(kāi)源),我們自定義設(shè)計(jì)開(kāi)發(fā)了 Agent,定時(shí)從Redis集群采集信息,并在內(nèi)部做一些統(tǒng)計(jì)數(shù)值的簡(jiǎn)單計(jì)算,轉(zhuǎn)換成Json,寫入到本地文件,通過(guò)Logstash采集發(fā)送到Elasticsearch。
圖示:Redis服務(wù)端運(yùn)行信息采集架構(gòu)示意圖
Redis服務(wù)端運(yùn)行日志采集很簡(jiǎn)單,直接通過(guò)Elastic-Stack家族的Filebeat產(chǎn)品,其中有Redis模塊,配置一下Elastic服務(wù)端,日志文件地址即可。
圖示:服務(wù)端日志采集過(guò)程
Redis運(yùn)行日志采集配置:
應(yīng)用端信息采集是整個(gè)Redis監(jiān)控體系最重要的部分,也是實(shí)現(xiàn)最麻煩、鏈路最長(zhǎng)的。首先是修改jedis(技術(shù)棧Java)源碼,增加埋點(diǎn)代碼,重新編譯并引用到應(yīng)用項(xiàng)目中,應(yīng)用端對(duì)于Redis集群的任何命令操作,都會(huì)被捕捉,并記錄下關(guān)鍵信息,之后寫入到本地文件。
圖示:Redis應(yīng)用端行為采集架構(gòu)圖
應(yīng)用端采集的數(shù)據(jù)格式如下:
圖示:應(yīng)用端采集的數(shù)據(jù)案例
jedis修改:
jedis改造記錄的信息如下:
r_host:訪問(wèn)Redis集群的服務(wù)器地址與端口,其中某一臺(tái)ip:port;
r_cmd:執(zhí)行命令類型、如get、set、hget、hset等各種;
r_start:執(zhí)行命令開(kāi)始時(shí)間;
r_cost:時(shí)間消耗;
r_size:獲取鍵值大小或者設(shè)置鍵值大?。?/span>
r_key:獲取鍵值名稱;
r_keys:鍵值的二級(jí)拆分,數(shù)組的長(zhǎng)度不限制。這里有必要強(qiáng)調(diào)一下,所有應(yīng)用系統(tǒng)共用的是一套集群,所以應(yīng)用系統(tǒng)的鍵值都是有規(guī)范的,按照特殊符號(hào)分割,如:"應(yīng)用名稱_系統(tǒng)模塊_動(dòng)態(tài)變量_xxx“,主要便于我們區(qū)分。
在jedis改造有幾處地方,如下:
類Connection.java文件,統(tǒng)計(jì)開(kāi)始,記錄命令執(zhí)行開(kāi)始時(shí)間;統(tǒng)計(jì)結(jié)束,記錄命令結(jié)束時(shí)間、時(shí)間消耗等,并寫入到日志流中;
類JedisClusterCommand文件,獲取鍵的地方key,方便之后分析應(yīng)用鍵的行為。
在類Connection.java文件中有2處:
圖示:類Connection.java文件埋點(diǎn)代碼的地方
圖示:類Connection.java文件埋點(diǎn)代碼的地方
類JedisClusterCommand文件埋點(diǎn)代碼.java文件中有1處:
圖示:類JedisClusterCommand文件埋點(diǎn)代碼
logback修改:
應(yīng)用端都會(huì)使用logback寫入日志文件,同時(shí)為了更加精準(zhǔn),應(yīng)用端寫入日志時(shí)還需要獲取應(yīng)用端的一些信息,如下:
app_ip:應(yīng)用端部署在服務(wù)器上的IP地址;
app_host:應(yīng)用端部署在服務(wù)器上的服務(wù)器名稱。
自定義一個(gè)Layout,自動(dòng)獲取應(yīng)用端的IP地址與服務(wù)器名稱:
圖示:自定義Logback的Layout
app配置:
app配置屬于最后收尾工作,主要是輸出埋點(diǎn)的日志數(shù)據(jù),配置日志logback.xml文件即可:
圖示:配置應(yīng)用端日志文件logback.xml
日志采集:
應(yīng)用端日志采集采用Logstash,配置日志目錄,指向Elastic集群,這樣整體的監(jiān)控日志采集部分就結(jié)束了。
Redis服務(wù)端的日志分析比較簡(jiǎn)單,常規(guī)的一些指標(biāo)而已,創(chuàng)建好關(guān)鍵的圖表,容易看出問(wèn)題。重點(diǎn)討論應(yīng)用端的日志分析。
圖示:應(yīng)用端使用Redis一些行為圖表
ELK監(jiān)控體系上線之后,我們連續(xù)觀察分析兩周,獲得了一些監(jiān)控成果,如:
應(yīng)用端部分鍵值太大,居然超過(guò)1MB,這種鍵值訪問(wèn)一次消耗時(shí)間很大,會(huì)嚴(yán)重造成阻塞;
部分應(yīng)用居然使用Redis當(dāng)成數(shù)據(jù)庫(kù)使用;
有將List類型當(dāng)成消息隊(duì)列使用,一次存取幾十萬(wàn)的數(shù)據(jù);
某些應(yīng)用對(duì)于集群的操作頻次特別高,幾乎占用了一半以上;
還有很多,就不一一描述了。
監(jiān)控體系相當(dāng)于架構(gòu)師的眼睛,有了這個(gè),Redis方面的優(yōu)化改造方案就很好制定了:
應(yīng)用端、誤用的使用全部要改掉;
服務(wù)端,按照應(yīng)用的數(shù)據(jù),進(jìn)行一些拆分,拆分出一些專用的集群,特定為一些應(yīng)用使用或者場(chǎng)景;
開(kāi)發(fā)者,后續(xù)有新業(yè)務(wù)模塊需要接入Redis需要告知架構(gòu)師們?cè)u(píng)審。
監(jiān)控體系項(xiàng)目前后經(jīng)歷過(guò)幾個(gè)月,服務(wù)端部分短期內(nèi)就完成的,應(yīng)用端是隨著應(yīng)用發(fā)布逐步完成的。上線完成之后又經(jīng)歷幾周的跟蹤分析,才確定下來(lái)整體的優(yōu)化方案。
監(jiān)控體系本身并不是為了監(jiān)控,而是發(fā)現(xiàn)問(wèn)題、預(yù)見(jiàn)問(wèn)題,最終提前解決問(wèn)題,監(jiān)控做得好,下班下得早。
Redis集群是個(gè)好東西,完全掌握還是需要很長(zhǎng)的時(shí)間,特別是架構(gòu)、運(yùn)維層面,如果沒(méi)有,請(qǐng)做好監(jiān)控。
Q&A
Q1:請(qǐng)問(wèn)單臺(tái)機(jī)器一般部署幾個(gè)Redis實(shí)例呢?
A:依據(jù)服務(wù)器資源設(shè)置:
1、CPU核數(shù),Redis是單線程工作模型,實(shí)際運(yùn)行并非進(jìn)程只有一個(gè)線程,這個(gè)要搞清楚;
2、內(nèi)存,一個(gè)Redis進(jìn)程配置部分內(nèi)存,需要至少對(duì)等的內(nèi)存閑置,fork子進(jìn)程使用, 所以配置多實(shí)例要簡(jiǎn)單計(jì)算下;
3、網(wǎng)絡(luò),網(wǎng)絡(luò)IO超過(guò)網(wǎng)卡限制,會(huì)出問(wèn)題。
Q2:直播中講到的大key,hash要改成什么?分片嗎?
A:1、比如,一個(gè)車子的基本信息,包括很多區(qū)塊部分,用hash確實(shí)非常好理解,但是過(guò)期之后整個(gè)hash都刪除了,其實(shí)很多信息是固定的,不用定時(shí)過(guò)期的;2、拆分成小的string更合適。
Q3:在客戶端打印key和value,如果是bigkey的話,qps有個(gè)1000,打印日志就占用很高的機(jī)器負(fù)載了吧?
A:1、打印的key,不包括value值內(nèi)容,只有key以及value的大??;2、logback這些框架其實(shí)支持的性能相當(dāng)不錯(cuò)的,可以配置成異步的方式,如果還不夠,可以直接輸出到Kafka隊(duì)列等。
Q4:請(qǐng)問(wèn)ES怎么部署MongoDB慢查詢報(bào)表平臺(tái)呢?
A:1、沒(méi)有深度使用過(guò)MongoDB;2、基于Elastic-Stack做慢查詢報(bào)表平臺(tái)思路與Redis一樣的,不管什么指標(biāo)+日志全部都采集到ES完事。
Q5:info all執(zhí)行頻繁,會(huì)經(jīng)常阻塞服務(wù)器,怎么平衡它的性能呢?
A:1、因?yàn)椴杉氖欠?wù)端運(yùn)行的快照信息,定時(shí)采集,可以設(shè)定時(shí)間間隔大一些,比如5s;2、執(zhí)行info all,是在 java客戶端,可以修改jedis,在其中捕獲info命令,采集數(shù)據(jù),觀察分析一段時(shí)間。
Q6:請(qǐng)問(wèn)應(yīng)用端jedis要怎么埋點(diǎn)呢?
A:1、原有jedis版本基于2.9,在2個(gè)類中修改埋點(diǎn),參考了CacheCloud產(chǎn)品。最新版本的程序最近沒(méi)有關(guān)注,思路一樣;2、詳細(xì)見(jiàn)本文中貼出的代碼。
Q7:監(jiān)控的話,個(gè)人覺(jué)得放在K8S里面,不是最優(yōu)方案,您對(duì)這個(gè)怎么看?
A:1、本人未使用過(guò)K8S部署產(chǎn)品;2、Redis監(jiān)控體系,整體服務(wù)端,應(yīng)用端,在Docker中也僅服務(wù)端可以,將metrcibeats這些集成在一起,但也有一些服務(wù)端監(jiān)指標(biāo)計(jì)算,需要自己編寫Agent來(lái)完成,也是可以到Docker中去。應(yīng)用端的就沒(méi)有辦法了,這個(gè)屬于前端的行為統(tǒng)計(jì)。
Q8:請(qǐng)問(wèn)您的ES有多少節(jié)點(diǎn)?要用ssd盤嗎?
A:1、標(biāo)準(zhǔn)集群,起步3個(gè)實(shí)例節(jié)點(diǎn);2、固態(tài)硬盤應(yīng)用看場(chǎng)景,業(yè)務(wù)系統(tǒng)用用可以,日志系統(tǒng)一般不需要,即使需要也可以做冷熱隔離,少量的數(shù)據(jù)使用ssd,歷史的數(shù)據(jù)全部hdd足矣。
Q9:如果公司缺乏足夠的人力物力,是用ES、Prometheus還是Zabbix做監(jiān)控比較適合呢?能分別說(shuō)一下它們各自最適用的情況嗎?
A:1、ES,Elastic-Stack,首選考慮,ES擅長(zhǎng)的領(lǐng)域很多,應(yīng)用系統(tǒng)查詢加速、大數(shù)據(jù)領(lǐng)域、監(jiān)控領(lǐng)域;2、其它兩個(gè)產(chǎn)品主要是做指標(biāo)型的監(jiān)控,但實(shí)際項(xiàng)目中,僅僅指標(biāo)監(jiān)控是不夠的,需要一個(gè)整體型的監(jiān)控體系,便于聯(lián)合分析。ES其實(shí)很多方面比時(shí)序數(shù)據(jù)庫(kù)做得更好,騰訊有資深專家做過(guò)詳細(xì)的ES與TSDB對(duì)比的測(cè)試,性能與功能都完全超過(guò)專門的時(shí)序數(shù)據(jù)庫(kù)。
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:
長(zhǎng)按訂閱更多精彩▼
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!