好代碼實踐:基于Redis的輕量級分布式均衡消費(fèi)隊列
一、我對好代碼的看法
1.什么是好代碼
如果你讀過《設(shè)計模式之美》,你可能會覺得玩轉(zhuǎn)各種設(shè)計模式,符合設(shè)計模式的6大基本原則的代碼就是好代碼;如果讀過《clean code》,你可能會覺得好代碼的一個標(biāo)準(zhǔn)是——整潔;如果你經(jīng)常研讀Spring源碼,你可能會覺得精妙的設(shè)計、高度的抽象、靈活的配置才是好代碼,就像是一本書,一千個讀者眼中有一千個哈姆雷特,每個人按照自己的認(rèn)知都會有自己的判斷。
2.我認(rèn)為的好代碼
如前文所述,不同的人對好代碼的認(rèn)知標(biāo)準(zhǔn)是不同的,我認(rèn)為的好代碼,也局限于我的認(rèn)知水平,也許今天我覺得是好代碼,隨著認(rèn)知的提升,改天也會有不同的想法;就目前的認(rèn)知而言,我認(rèn)為的好代碼的一些特點:
可用性
對,你沒看錯,好代碼,一定是可用的,可以work的,如果一段代碼只是看著好看,用了各種花里胡哨的編碼技巧、手法,但是不能work,那就失去了它存在的意義了。所以,好代碼,最最最重要的一個特點就是可用性。
可讀性
我認(rèn)為好代碼的第二個特點就是可讀性,我們的寫代碼的目標(biāo)用戶有兩類,第一類是給編譯器看的;第二類是給維護(hù)它的程序員看的。針對第一類用戶,只要你符合它的語法規(guī)范,它就認(rèn)識,它就可以執(zhí)行;而第二類用戶,就是后期不斷的維護(hù)它、升級它的程序員同學(xué),如果這段代碼,維護(hù)它的人都讀不懂,那他的長期存在的意義也就不大了。
其他優(yōu)秀的特點
可維護(hù)性、可擴(kuò)展性、可復(fù)用性、強(qiáng)魯棒性、可測試性等。
好代碼的其他優(yōu)秀特點太多了,不一一列舉了。
3.讓code在計算機(jī)上起舞
回到根源,我們寫代碼的目的是干嘛?為的是把我們的所思所想通過計算機(jī)認(rèn)識的指令告訴它,讓它來替我們做我們想做的事情。好代碼,不僅可以簡單地完成我們的所思所想,更能夠快速、高效、完備地執(zhí)行。讓我們的code一起在計算機(jī)上起舞吧。
二、我們?yōu)槭裁匆?/h2>
2020年五一期間,當(dāng)大家都在享受五一假期的快樂時光時,我們突然收到hbase報警,整個hbase的IO壓力已經(jīng)接近瓶頸,直接影響數(shù)據(jù)讀寫,臨時擴(kuò)容hbase才勉強(qiáng)支撐過去。按照這個發(fā)展趨勢,一旦遇到業(yè)務(wù)高峰時,hbase的讀寫直接會給整個業(yè)務(wù)鏈路帶來瓶頸問題。為了能夠解決海量巴槍數(shù)據(jù)實時寫入hbase+solr時產(chǎn)生的高IO壓力,我們設(shè)計出一款基于redis實現(xiàn)的輕量級分布式均衡消費(fèi)隊列,實現(xiàn)巴槍數(shù)據(jù)按照一定規(guī)則進(jìn)行sharding到不同的隊列中,實現(xiàn)批量數(shù)據(jù)攢批去重,然后按批寫入hbase+solr,從而降低hbase+solr的IO壓力。
三、我們怎么做的
組件整體設(shè)計思路:
整個組件主要分為三大核心模塊,master(主節(jié)點)、writer(數(shù)據(jù)寫入節(jié)點)、worker(工作節(jié)點)。
設(shè)計機(jī)制:弱中心機(jī)制,任何一個配置好的節(jié)點都可能成為master(主節(jié)點)、writer(數(shù)據(jù)寫入節(jié)點)、worker(工作節(jié)點),具備高可用能力,不存在單機(jī)單點瓶頸問題。
master(主節(jié)點)職責(zé):
- 負(fù)責(zé)實時探活worker(工作節(jié)點)是否有變化,掉線情況;
- 負(fù)責(zé)分配任務(wù)隊列到存活的worker(工作節(jié)點);
- 負(fù)責(zé)實時檢測整個redis隊列的負(fù)載情況。
writer(數(shù)據(jù)寫入節(jié)點)職責(zé):
- 負(fù)責(zé)分配實時寫入任務(wù)sharding到不同的隊列;
- 負(fù)責(zé)檢測當(dāng)前寫入隊列的負(fù)載情況。
worker(工作節(jié)點)職責(zé):
- 負(fù)責(zé)實時匯報當(dāng)前worker(工作節(jié)點)的狀態(tài),保持心跳;
- 負(fù)責(zé)定時消費(fèi)該worker(工作節(jié)點)負(fù)責(zé)的數(shù)據(jù)。
偉大的linux大神曾說過,"Talk is cheap,讓我看看代碼"。
四、我們做了什么
1.整個組件的包結(jié)構(gòu)圖
2.簡潔的代碼結(jié)構(gòu)
- 清晰的注釋,介紹類的作用和職責(zé)
- 啟動項配置,靈活的配置,控制模塊是否啟動。
- lambda-logger/lambda表達(dá)式,通過簡潔語法結(jié)構(gòu),輕量化代碼冗余,提高代碼簡潔度。
- 斷言判斷,替換傳統(tǒng)的if-else判斷,提高代碼的可讀性。
整個工程一共60個類,核心代碼共1623行, 平均每個類的代碼行數(shù)為27.05行,最大的一個類代碼行數(shù)不超過200行。
3.強(qiáng)大的擴(kuò)展性
通過鉤子回調(diào)方式的設(shè)計,方便接入的用戶能夠快速的注入自己的回調(diào)實現(xiàn)方法,進(jìn)行快速擴(kuò)展業(yè)務(wù)能力。
4.線上日志展示截圖
日志文件
master隊列分配日志
worker數(shù)據(jù)消費(fèi)日志
writer隊列負(fù)載檢測日志
redis消費(fèi)隊列監(jiān)控大盤
五、我們的收益
組件部署上線之時,hbase服務(wù)端監(jiān)控指標(biāo)變化,實現(xiàn)hbase整體使用水位接近50%的優(yōu)化。
hbase IOPS使用監(jiān)控
hbase CPU使用監(jiān)控
六、我們的展望
- 獨(dú)立抽象組件,基于Redis的輕量級分布式均衡消費(fèi)隊列,是一個全自主創(chuàng)新研發(fā)出來的,高可用,可擴(kuò)展的基礎(chǔ)組件,目前已經(jīng)封裝成為一個獨(dú)立的spring-boot-starter,具備高復(fù)用性和高擴(kuò)展性能力。
- 廣闊的使用場景,基于組件靈活的配置,在涉及的分布式任務(wù)隊列場景時,都可以使用到它,例如任務(wù)中心分發(fā)等可以做到天然的均衡負(fù)載。
- 擁抱開源,未來希望將組件開源出去。
七、我的一些理解
好代碼,給人第一個印象的感覺,就像一篇好文章一樣,讀起來朗朗上口。不同的文章有不同的風(fēng)格體裁,不同的代碼也有不同的編程風(fēng)格要求。Python有嚴(yán)格的縮進(jìn),像詩歌一樣工整對仗;C語言面向過程像散文一樣形散神聚,意境深邃;Java語言面向?qū)ο笥窒袷菍懶≌f一樣,能勾勒出一個一個人物形象。但是無論哪一種文章體裁,他的可讀性和可理解性都非常重要,只有文章是可讀的可理解的,才會吸引更多的讀者去讀它,讓他流傳下去,代碼也一樣,它的可維護(hù)性和可讀性也非常重要,保證代碼可用性,提高代碼的簡潔程度和可維護(hù)程度,才能讓我們的代碼在計算機(jī)上跑的更遠(yuǎn),更久。