解剖屎山,尋覓黃金之第二彈
大家好,我3y啊。由于去重邏輯重構(gòu)了幾次,好多股東直呼看不懂,于是我今天再安排一波對(duì)代碼的解析吧。austin支持兩種去重的類型:N分鐘相同內(nèi)容達(dá)到N次去重和一天內(nèi)N次相同渠道頻次去重。
在最開始,我的第一版實(shí)現(xiàn)是這樣的:
publicvoidduplication(TaskInfotaskInfo){//配置示例:{"contentDeduplication":{"num":1,"time":300},"frequencyDeduplication":{"num":5}}JSONObjectproperty=JSON.parseObject(config.getProperty(DEDUPLICATION_RULE_KEY,AustinConstant.APOLLO_DEFAULT_VALUE_JSON_OBJECT));JSONObjectcontentDeduplication=property.getJSONObject(CONTENT_DEDUPLICATION);JSONObjectfrequencyDeduplication=property.getJSONObject(FREQUENCY_DEDUPLICATION);//文案去重DeduplicationParamcontentParams=DeduplicationParam.builder().deduplicationTime(contentDeduplication.getLong(TIME)).countNum(contentDeduplication.getInteger(NUM)).taskInfo(taskInfo).anchorState(AnchorState.CONTENT_DEDUPLICATION).build();contentDeduplicationService.deduplication(contentParams);//運(yùn)營(yíng)總規(guī)則去重(一天內(nèi)用戶收到最多同一個(gè)渠道的消息次數(shù))Longseconds=(DateUtil.endOfDay(newDate()).getTime()-DateUtil.current())/1000;DeduplicationParambusinessParams=DeduplicationParam.builder().deduplicationTime(seconds).countNum(frequencyDeduplication.getInteger(NUM)).taskInfo(taskInfo).anchorState(AnchorState.RULE_DEDUPLICATION).build();frequencyDeduplicationService.deduplication(businessParams);}
【資料圖】
那時(shí)候很簡(jiǎn)單,基本主體邏輯都寫在這個(gè)入口上了,應(yīng)該都能看得懂。后來,群里滴滴哥表示這種代碼不行,不能一眼看出來它干了什么。于是怒提了一波pull request重構(gòu)了一版,入口是這樣的:
publicvoidduplication(TaskInfotaskInfo){//配置樣例:{"contentDeduplication":{"num":1,"time":300},"frequencyDeduplication":{"num":5}}Stringdeduplication=config.getProperty(DeduplicationConstants.DEDUPLICATION_RULE_KEY,AustinConstant.APOLLO_DEFAULT_VALUE_JSON_OBJECT);//去重DEDUPLICATION_LIST.forEach(key->{DeduplicationParamdeduplicationParam=builderFactory.select(key).build(deduplication,key);if(deduplicationParam!=null){deduplicationParam.setTaskInfo(taskInfo);DeduplicationServicededuplicationService=findService(key+SERVICE);deduplicationService.deduplication(deduplicationParam);}});}
我猜想他的思路就是把構(gòu)建去重參數(shù)和選擇具體的去重服務(wù)給封裝起來了,在最外層的代碼看起來就很簡(jiǎn)潔了。后來又跟他聊了下,他的設(shè)計(jì)思路是這樣的:考慮到以后會(huì)有其他規(guī)則的去重就把去重邏輯單獨(dú)封裝起來了,之后用策略模版的設(shè)計(jì)模式進(jìn)行了重構(gòu),重構(gòu)后的代碼 模版不變,支持各種不同策略的去重,擴(kuò)展性更高更強(qiáng)更簡(jiǎn)潔
確實(shí)牛逼。
我基于上面的思路微改了下入口,代碼最終演變成這樣:
publicvoidduplication(TaskInfotaskInfo){//配置樣例:{"deduplication_10":{"num":1,"time":300},"deduplication_20":{"num":5}}StringdeduplicationConfig=config.getProperty(DEDUPLICATION_RULE_KEY,CommonConstant.EMPTY_JSON_OBJECT);//去重ListdeduplicationList=DeduplicationType.getDeduplicationList();for(IntegerdeduplicationType:deduplicationList){DeduplicationParamdeduplicationParam=deduplicationHolder.selectBuilder(deduplicationType).build(deduplicationConfig,taskInfo);if(Objects.nonNull(deduplicationParam)){deduplicationHolder.selectService(deduplicationType).deduplication(deduplicationParam);}}}
到這,應(yīng)該大多數(shù)人還能跟上吧?在講具體的代碼之前,我們先來簡(jiǎn)單看看去重功能的代碼結(jié)構(gòu)(這會(huì)對(duì)后面看代碼有幫助)
去重的邏輯可以統(tǒng)一抽象為:在X時(shí)間段內(nèi)達(dá)到了Y閾值,還記得我曾經(jīng)說過:「去重」的本質(zhì):「業(yè)務(wù)Key」+「存儲(chǔ)」。那么去重實(shí)現(xiàn)的步驟可以簡(jiǎn)單分為(我這邊存儲(chǔ)就用的Redis):
通過Key從Redis獲取記錄判斷該Key在Redis的記錄是否符合條件符合條件的則去重,不符合條件的則重新塞進(jìn)Redis更新記錄為了方便調(diào)整去重的參數(shù),我把X時(shí)間段和Y閾值都放到了配置里{"deduplication_10":{"num":1,"time":300},"deduplication_20":{"num":5}}。目前有兩種去重的具體實(shí)現(xiàn):
1、5分鐘內(nèi)相同用戶如果收到相同的內(nèi)容,則應(yīng)該被過濾掉
2、一天內(nèi)相同的用戶如果已經(jīng)收到某渠道內(nèi)容5次,則應(yīng)該被過濾掉
從配置中心拿到配置信息了以后,Builder就是根據(jù)這兩種類型去構(gòu)建出DeduplicationParam,就是以下代碼:
DeduplicationParamdeduplicationParam=deduplicationHolder.selectBuilder(deduplicationType).build(deduplicationConfig,taskInfo);
Builder和DeduplicationService都用了類似的寫法(在子類初始化的時(shí)候指定類型,在父類統(tǒng)一接收,放到Map里管理)
而統(tǒng)一管理著這些服務(wù)有個(gè)中心的地方,我把這取名為DeduplicationHolder
/***@authorhuskey*@date2022/1/18*/@ServicepublicclassDeduplicationHolder{privatefinalMapbuilderHolder=newHashMap<>(4);privatefinalMap serviceHolder=newHashMap<>(4);publicBuilderselectBuilder(Integerkey){returnbuilderHolder.get(key);}publicDeduplicationServiceselectService(Integerkey){returnserviceHolder.get(key);}publicvoidputBuilder(Integerkey,Builderbuilder){builderHolder.put(key,builder);}publicvoidputService(Integerkey,DeduplicationServiceservice){serviceHolder.put(key,service);}}
前面提到的業(yè)務(wù)Key,是在AbstractDeduplicationService的子類下構(gòu)建的:
而具體的去重邏輯實(shí)現(xiàn)則都在LimitService下,{一天內(nèi)相同的用戶如果已經(jīng)收到某渠道內(nèi)容5次}是在SimpleLimitService中處理使用mget和pipelineSetEX就完成了實(shí)現(xiàn)。而{5分鐘內(nèi)相同用戶如果收到相同的內(nèi)容}是在SlideWindowLimitService中處理,使用了lua腳本完成了實(shí)現(xiàn)。
LimitService的代碼都來源于@caolongxiu的pull request,建議大家可以對(duì)比commit再學(xué)習(xí)一番:https://gitee.com/zhongfucheng/austin/pulls/19
1、頻次去重采用普通的計(jì)數(shù)去重方法,限制的是每天發(fā)送的條數(shù)。
2、內(nèi)容去重采用的是新開發(fā)的基于redis中zset的滑動(dòng)窗口去重,可以做到嚴(yán)格控制單位時(shí)間內(nèi)的頻次。
3、redis使用lua腳本來保證原子性和減少網(wǎng)絡(luò)io的損耗
4、redis的key增加前綴做到數(shù)據(jù)隔離(后期可能有動(dòng)態(tài)更換去重方法的需求)
5、把具體限流去重方法從DeduplicationService抽取出來,DeduplicationService只需設(shè)置構(gòu)造器注入時(shí)注入的AbstractLimitService(具體限流去重服務(wù))類型即可動(dòng)態(tài)更換去重的方法 6、使用雪花算法生成zset的唯一value,score使用的是當(dāng)前的時(shí)間戳
針對(duì)滑動(dòng)窗口去重,有會(huì)引申出新的問題:limit.lua的邏輯?為什么要移除時(shí)間窗口的之前的數(shù)據(jù)?為什么ARGV[4]參數(shù)要唯一?為什么要expire?
A: 使用滑動(dòng)窗口可以保證N分鐘達(dá)到N次進(jìn)行去重?;瑒?dòng)窗口可以回顧下TCP的,也可以回顧下刷LeetCode時(shí)的一些題,那這為什么要移除,就不陌生了。
為什么ARGV[4]要唯一,具體可以看看zadd這條命令,我們只需要保證每次add進(jìn)窗口內(nèi)的成員是唯一的,那么就不會(huì)觸發(fā)有更新的操作(我認(rèn)為這樣設(shè)計(jì)會(huì)更加簡(jiǎn)單些),而唯一Key用雪花算法比較方便。
為什么expire?,如果這個(gè)key只被調(diào)用一次。那就很有可能在redis內(nèi)存常駐了,expire能避免這種情況。
推薦項(xiàng)目最后再叨叨吧,很多人可能會(huì)發(fā)一段截圖,跑來問我為什么要這樣寫,為什么要以這種方式實(shí)現(xiàn),能不能以這種方式實(shí)現(xiàn)。這時(shí)候,我更想看到的是:你已經(jīng)實(shí)現(xiàn)了第二種方式了,然后探討你寫的這種方案好不好,現(xiàn)有的代碼差在哪里。
畢竟問問題很簡(jiǎn)單,我又不是客服,總不能沒誠(chéng)意的問題我都得一一回答吧。
如果想學(xué)Java項(xiàng)目的,我還是強(qiáng)烈推薦我的開源項(xiàng)目消息推送平臺(tái)Austin,可以用作畢業(yè)設(shè)計(jì),可以用作校招,可以看看生產(chǎn)環(huán)境是怎么推送消息的。
倉(cāng)庫(kù)地址(可點(diǎn)擊閱讀原文跳轉(zhuǎn)):https://gitee.com/zhongfucheng/austin
我開通了股東服務(wù)內(nèi)容,感興趣可以點(diǎn)擊下方看看,主要針對(duì)的是項(xiàng)目喲
VIP服務(wù)
標(biāo)簽:
搶先讀
- 湖北發(fā)布災(zāi)害風(fēng)險(xiǎn)提示:雷暴大風(fēng)天氣來了,非必要不出行-每日資訊
- 熱點(diǎn)在線丨遼寧省藥品監(jiān)督管理局注銷1家公司《藥品營(yíng)許可證》
- 環(huán)球信息:股東知情權(quán)應(yīng)該如何行使
- 世界微頭條丨中國(guó)首家麗思卡爾頓隱世酒店開業(yè)
- 甘州區(qū)上秦鎮(zhèn)中心學(xué)校舉辦第四屆小學(xué)生詩詞大會(huì)
- 為何一到夏季,結(jié)石卻多發(fā)?可能存在這3點(diǎn)因素,勸你要避避開
- 永寧縣新就業(yè)群體服務(wù)季正式啟動(dòng)
- 房屋拆遷糾紛訴訟時(shí)效是多久
- 鍥介檯娌逛環(huán)鏂欑粓緇撳懆綰夸簩榪炶穼錛屼駭娌瑰浗鏈熷緟涓浗涔伴渶鎵樺競(jìng)
- 湖紅之源:新化紅茶“挑擔(dān)茶葉上北京”_環(huán)球精選
- 貴陽郵政:打通大動(dòng)脈 疏通微循環(huán)
- 金融街完成發(fā)行10億元公司債券,票面利率為3.14% 焦點(diǎn)速讀
- 當(dāng)前速讀:宸展光電:聘任徐可欣擔(dān)任公司董事會(huì)秘書
- 環(huán)球頭條:2023上海端午節(jié)游玩推薦景點(diǎn)有哪些?
- 信用卡現(xiàn)金轉(zhuǎn)出有利息嗎 怎么提前還|每日信息
- 安陽紅旗渠機(jī)場(chǎng)飛行程序?qū)嵉仳?yàn)證試飛成功
- 【環(huán)球聚看點(diǎn)】武磊梅開二度,國(guó)足4-0勝緬甸!
- 解剖屎山,尋覓黃金之第二彈
- 天天看熱訊:國(guó)產(chǎn)GPU的第一縷光:自研架構(gòu)“天狼星”在京亮相
- 2023年電子標(biāo)簽產(chǎn)業(yè)深度調(diào)研及發(fā)展趨勢(shì)預(yù)測(cè) 今日?qǐng)?bào)
- 個(gè)人原因離職申請(qǐng)書范文 全球播資訊
- 新烽光電啟動(dòng)IPO輔導(dǎo),解決方案應(yīng)用于智慧排水、智慧供水等_天天熱點(diǎn)評(píng)
- 上汽大眾、上通五菱回暖緩慢,誰來緩解上汽集團(tuán)的產(chǎn)銷焦慮? 環(huán)球訊息
- 【天天時(shí)快訊】股份公司和有限公司的區(qū)別?
- 天天精選!大運(yùn)會(huì)火炬手姜志強(qiáng):將大運(yùn)精神延續(xù)至賽場(chǎng)外,助推數(shù)字經(jīng)濟(jì)發(fā)展
- 專題講座連連看 揚(yáng)州航務(wù)中心第二期揚(yáng)帆講堂開講啦
- 2023粵港澳車展:極狐阿爾法S/T森林版上市 售價(jià)18.58萬元起
- 谷歌為你準(zhǔn)備了一個(gè)秘密的片魂復(fù)活節(jié)彩蛋 天天新要聞
- 京東白條,螞蟻花唄本質(zhì)就是信用卡,更方便,自從有了這兩樣,我信用卡都很少用了-視焦點(diǎn)訊
- 勝利監(jiān)理(836665):擬10派0.6元,共派現(xiàn)1749.87萬元_世界新視野
- 世界觀天下!云從科技投資算力芯片企業(yè)奕斯偉計(jì)算,打通大模型生態(tài)閉環(huán)
- 16日北京將迎本輪高溫峰值 最高氣溫預(yù)計(jì)39℃
- 資訊推薦:汽車下鄉(xiāng)政策回顧:新能源汽車市場(chǎng)潛力巨大,代步型純電+平價(jià)混動(dòng)將成為主力產(chǎn)品
- 烏當(dāng)區(qū)2023幼升小入學(xué)報(bào)名指南(對(duì)象+時(shí)間+入口+學(xué)區(qū)劃片)_天天快資訊
- 杭州地鐵公安公示“偷拍案”處罰信息,律師:有“羞辱性懲罰”和侵犯隱私之嫌_世界今頭條
- 世界快訊:甘州區(qū)市場(chǎng)監(jiān)管局西街市場(chǎng)監(jiān)管所開展早夜市計(jì)量器具專項(xiàng)檢查
- 公司邀請(qǐng)函
- 世界動(dòng)態(tài):停息掛賬還收利息不?停息掛賬之前的利息還需要嗎?|天天速看
- 織嘜機(jī)(織嘜) 環(huán)球快資訊
- 鄧清清 抖音(鄧清清) 全球訊息
- 增設(shè)電梯陷“拉鋸戰(zhàn)”:電梯選址距自家僅1米,一樓業(yè)主不同意被起訴-天天觀天下
- 梅西中國(guó)行,有哪些品牌搭上了“順風(fēng)車”?
- 世界播報(bào):北京亦莊搭平臺(tái)助企業(yè)共赴雙碳之約
- 榮盛發(fā)展為5家全資子公司融資提供合計(jì)不超10.7億元擔(dān)保 環(huán)球今日訊
- 環(huán)球要聞:重癥肌無力關(guān)愛日|全身漸漸無力,最終喚起心靈之力
- 世界快看點(diǎn)丨“流動(dòng)的咨詢臺(tái)”——崇明海事局開展“安全宣傳咨詢?nèi)铡被顒?dòng)
- 今日熱聞!河南:強(qiáng)化監(jiān)督執(zhí)紀(jì) 筑牢南水北調(diào)工程安全“堤壩”
- 廣東最新平均工資出爐!這些行業(yè)仍“吃香”→_天天新消息
- 每日視訊:2023南陽端午節(jié)游玩景點(diǎn)推薦
- 每日速看!6月FOMC會(huì)議點(diǎn)評(píng):“留有余地”的暫停加息
- 600余場(chǎng)活動(dòng)!30余萬個(gè)崗位!重慶市“百日千萬招聘專項(xiàng)行動(dòng)”來了
- 天天速遞!強(qiáng)觀察|這些返回艙里的“神器”為航天員保駕護(hù)航
- 跨界布局儲(chǔ)能領(lǐng)域!家電龍頭獲外資連買7日 當(dāng)前播報(bào)
- 天馬行空揮灑創(chuàng)意!《狂想樂園》今日上市! 世界速訊
- 高爾夫全錦賽:上海男隊(duì)和陜西女隊(duì)繼續(xù)占據(jù)榜首
- 書從文:青海發(fā)生山體滑坡(已致5死2失聯(lián))
- 中煤國(guó)際工程集團(tuán)武漢設(shè)計(jì)研究院(關(guān)于中煤國(guó)際工程集團(tuán)武漢設(shè)計(jì)研究院的基本詳情介紹)|全球快消息
- word里怎么打鋼筋等級(jí)符號(hào)(鋼筋等級(jí)符號(hào)) 新消息
- 石嘴山市氣象臺(tái)發(fā)布大風(fēng)藍(lán)色預(yù)警【IV級(jí)/一般】【2023-06-16】
- 司法重拳嚴(yán)懲性侵未成年人犯罪
- 陜西寶雞:暖心服務(wù)助力小麥歸倉(cāng)-天天頭條
- (聚焦中國(guó)高質(zhì)量發(fā)展)以僑為橋 泉州優(yōu)品“揚(yáng)帆出海” 天天新資訊
- 北京朝陽區(qū)“閱讀大運(yùn)河”系列主題活動(dòng)啟幕 世界實(shí)時(shí)
- 發(fā)改委:研究部署加強(qiáng)居民增收工作 各地要加大穩(wěn)就業(yè)工作力度-即時(shí)看
- 金融如何賦能“天府糧倉(cāng)”建設(shè)?崇州這場(chǎng)發(fā)布會(huì)給出答案_觀焦點(diǎn)
- 本周全國(guó)碳市場(chǎng)碳排放配額總成交額突破2700萬元_全球即時(shí)
- “云”上逛房,福利多多,2023齊魯(濟(jì)南)夏季房展匯盛大啟動(dòng)-熱門看點(diǎn)
- 天天看點(diǎn):讓安全走進(jìn)社區(qū)!中原區(qū)首家“社區(qū)警?!遍_課啦
- 哈佛醫(yī)學(xué)院丑聞曝光!太平間管理員倒賣遺體,6 人已被逮捕 天天速訊
- 又有券商被監(jiān)管談話!-最新資訊
- 沿江高鐵武宜段步入“四電”施工階段 環(huán)球快報(bào)
- 華商雙翼平衡混合基金增設(shè)C份額
- 神州播報(bào)丨北京警方通報(bào)“球迷沖入球場(chǎng)擁抱梅西”事件:已行拘!12個(gè)月內(nèi)不得進(jìn)體育場(chǎng)館看同類比賽
- 帶你全面提升工作效率:B端設(shè)計(jì)規(guī)范攻略(三)
- 【世界新視野】南陽宛城區(qū):“四美庭院”扮靚城市顏值
- 谷歌&凱度:2023年中國(guó)全球化品牌50強(qiáng) 比亞迪進(jìn)入前十
- 世界今日訊!【透視】美知名媒體人稱“世界上其他國(guó)家對(duì)中國(guó)的看法和美國(guó)不同”引發(fā)網(wǎng)友共鳴
- 市紀(jì)委監(jiān)委下發(fā)通知嚴(yán)禁黨員干部、公職人員違規(guī)操辦“學(xué)子宴”“謝師宴” 天天熱聞
- 當(dāng)前熱文:猝不及防!西安又一本土房企破產(chǎn),買房人要警惕!
- 民航局:預(yù)計(jì)今年暑運(yùn)每日有近195萬旅客通過航空出行-訊息
- 福州一商店隨便賣紅牛被查:沒有保健品售賣許可證_新資訊
- 批了!再添一所九年一貫制學(xué)校_全球動(dòng)態(tài)
- 《射雕》演員太坎坷,孤獨(dú)離世、酒店猝死、開煤氣自殺,令人惋惜-速看料
- 6月16日內(nèi)蒙時(shí)泰液化天然氣價(jià)格動(dòng)態(tài) 環(huán)球速讀
- 速看:sony(lt26ii)
- 性價(jià)比神卡!盈通RX 6600顯卡降至1399元:8GB顯存
- 天天觀察:諾安基金韓冬燕在管產(chǎn)品近1年業(yè)績(jī)居同類前1%
- 環(huán)球聚焦:華爾街大銀行裁員人數(shù)將超過1.1萬人
- 俄羅斯經(jīng)濟(jì)學(xué)家:美國(guó)借債“成癮”將危及全球經(jīng)濟(jì)復(fù)蘇
- 貴陽市2023年學(xué)前教育宣傳月宣講活動(dòng)在清鎮(zhèn)舉行_世界熱聞
- 全球速訊:天天速遞!信用卡停息掛賬后逾期多久會(huì)被起訴?網(wǎng)貸逾期了暫時(shí)還不上怎么辦?
- 通訊!夏夜和夜宵是絕配!餐飲消費(fèi)催熱“夏日夜經(jīng)濟(jì)”
- 全球熱點(diǎn)!端午節(jié)臨近 重慶手工現(xiàn)包粽子受熱捧
- 下載音樂到U盤怎么下載mp3格式 下載音樂到u盤怎么下載 熱點(diǎn)在線
- 葡萄酒怎做的?(葡萄酒怎么做的步驟) 微資訊
- 速看:2023樂華88度溫泉樂園端午夜場(chǎng)特惠
- 土拍丨蘇系房企成功搖號(hào)進(jìn)京 保利擊退石景山區(qū)“老地主”
- 韋伯以學(xué)術(shù)為志業(yè)的演講基調(diào)是(韋伯)
- 《萌探》仙俠特輯,娜扎最美,劉令姿最敢,謝娜沾了趙麗穎的光_焦點(diǎn)速遞
- 迎峰度夏又至 中國(guó)統(tǒng)調(diào)電廠存煤達(dá)歷史新高