大家好,我3y啊。由于去重邏輯重構(gòu)了幾次,好多股東直呼看不懂,于是我今天再安排一波對代碼的解析吧。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)營總規(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í)候很簡單,基本主體邏輯都寫在這個(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ù)給封裝起來了,在最外層的代碼看起來就很簡潔了。后來又跟他聊了下,他的設(shè)計(jì)思路是這樣的:考慮到以后會(huì)有其他規(guī)則的去重就把去重邏輯單獨(dú)封裝起來了,之后用策略模版的設(shè)計(jì)模式進(jìn)行了重構(gòu),重構(gòu)后的代碼 模版不變,支持各種不同策略的去重,擴(kuò)展性更高更強(qiáng)更簡潔
確實(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é)構(gòu)(這會(huì)對后面看代碼有幫助)
去重的邏輯可以統(tǒng)一抽象為:在X時(shí)間段內(nèi)達(dá)到了Y閾值,還記得我曾經(jīng)說過:「去重」的本質(zhì):「業(yè)務(wù)Key」+「存儲」。那么去重實(shí)現(xiàn)的步驟可以簡單分為(我這邊存儲就用的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,建議大家可以對比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í)間戳
針對滑動(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ì)更加簡單些),而唯一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)有的代碼差在哪里。
畢竟問問題很簡單,我又不是客服,總不能沒誠意的問題我都得一一回答吧。
如果想學(xué)Java項(xiàng)目的,我還是強(qiáng)烈推薦我的開源項(xiàng)目消息推送平臺Austin,可以用作畢業(yè)設(shè)計(jì),可以用作校招,可以看看生產(chǎn)環(huán)境是怎么推送消息的。
倉庫地址(可點(diǎn)擊閱讀原文跳轉(zhuǎn)):https://gitee.com/zhongfucheng/austin
我開通了股東服務(wù)內(nèi)容,感興趣可以點(diǎn)擊下方看看,主要針對的是項(xiàng)目喲
VIP服務(wù)

-
1怎么打開電腦路由器設(shè)置?初次設(shè)置無線路由器方法是什么?
-
2路由器如何設(shè)置提升網(wǎng)速?學(xué)校寢室路由器無線怎么設(shè)置的?
-
3電腦沒連路由器卻能進(jìn)入路由器界面?電腦無法進(jìn)入路由器?
-
4把電腦變成無線路由器怎么弄?臺式電腦如何變成無線路由器?
-
5重新啟用U盤的技巧有什么?U盤提速的技巧有哪些?
-
6如何安全的使用U盤?U盤日常使用的技巧有哪些?
-
7曲面顯示器怎么選擇?曲面顯示器和平面顯示器的區(qū)別有什么?
-
8安卓設(shè)備型號和名稱可以改嗎?安卓手機(jī)如何修改手機(jī)IMEI串號?
-
9地址和域名是什么關(guān)系?互聯(lián)網(wǎng)域名是商標(biāo)的一個(gè)組成部分對錯(cuò)?
-
10Linux獲取文件名稱和文件路徑并寫入txt?linux下exports文件是什么?
-
鹽城濱海:以創(chuàng)建成色擦亮文明底色 全球今日報(bào)
-
熱門:閑情雅趣 | 云山深處茶香來
-
什么是問題證券? 政府對問題證券的處置方式是怎么樣的呢?
-
平?jīng)龈G洞養(yǎng)紅牛登上全國高考地理試卷
-
無記名證券的相關(guān)規(guī)定是怎么樣的呢? 無記名證券與指示證券的不同在哪里?
-
i77600u核顯相當(dāng)于什么顯卡(hd6470) 快消息
-
北緯科技:公司北緯國際中心入駐率比去年同期有所下降 前沿?zé)狳c(diǎn)
-
無記名證券的特點(diǎn)是怎么樣的? 無記名證券的質(zhì)具體如何說?
-
什么是無抵押證券? 無抵押證券的特點(diǎn)是怎么樣的呢?
-
赫伊倫德談是否和曼聯(lián)有過接觸:對此我沒什么可說的... 天天觀熱點(diǎn)
-
女媧傳說之靈珠劇情_你有看過嗎_天天熱推薦
-
環(huán)球播報(bào):168 192 0 111_168 192 0 1
-
每日信息:事業(yè)單位改革公益一類和公益二類的區(qū)別_事業(yè)單位改革公益一類
-
什么是無風(fēng)險(xiǎn)證券? 無風(fēng)險(xiǎn)證券對有效邊界的影響有哪些內(nèi)容?
-
產(chǎn)婦護(hù)理墊需要多少_產(chǎn)婦護(hù)理墊準(zhǔn)備須知 世界快資訊
-
3天簽訂各類意向訂單額7.5億!第七屆中華老字號(山東)博覽會(huì)碩果累累
-
以天地為舞臺,萬人合唱侗族大歌 | Thousands of people sing the Kam Grand Choir with the sky and earth as the stage
-
無價(jià)證券表示的是什么含義的內(nèi)容? 無價(jià)證券的分類分別是什么內(nèi)容?
-
清鎮(zhèn):“檢法”兩家合力推動(dòng)社會(huì)治安重點(diǎn)工作開展
-
【多彩新論.圖里有理】廣泛參與 強(qiáng)身健體_焦點(diǎn)精選
-
商業(yè)地產(chǎn)抵押貸款支持證券的闡述是如何的呢? 商業(yè)地產(chǎn)抵押貸款支持證券的組成的內(nèi)容是什么?
-
世界今日訊!教師體罰學(xué)生后群內(nèi)道歉獲其他家長安慰?官方通報(bào):責(zé)令學(xué)校解聘
-
手機(jī)證券的優(yōu)勢是如何的呢? 手機(jī)證券的開通是怎么做的呢?
-
北京明起4天最高溫均在35℃及以上,部分地區(qū)可達(dá)39℃
-
以天地為舞臺,萬人合唱侗族大歌 | Thousands of people sing the Kam Grand Choir with the sky and earth as the stage
-
女生罵男生偷拍變態(tài)后稱認(rèn)錯(cuò)人了?疑似女生家屬發(fā)聲:男生曾多次騷擾女生,已經(jīng)報(bào)警處理
-
每日聚焦:最高達(dá)39℃!北京明起四天持續(xù)高溫
-
老師體罰學(xué)生后道歉獲其他家長安慰 義烏教育局:責(zé)令解聘
-
電池級氫氧化鋰(粗顆粒)漲2000元/噸 報(bào)298000元/噸
-
什么是手機(jī)證券? 手機(jī)證券的具體內(nèi)容有哪些?
-
突發(fā)爆裂!水立方緊急通知……
-
昌平區(qū)市場監(jiān)管局持續(xù)開展餐飲食品安全大檢查和“凈化后廚”行動(dòng)-快資訊
-
實(shí)物券式證券指的是什么意思? 實(shí)物券式證券與簿記券式證券的區(qū)別在哪里?
-
環(huán)球觀點(diǎn):專家學(xué)者齊聚天水 共同助力伏羲文化走向世界
-
八大類商品“六漲二跌”!湖南5月份CPI同比上漲0.5%,食品價(jià)格上漲是主因
-
什么是適銷證券? 適銷證券和不適銷證券區(qū)別在哪些地方?
-
上市證券的申請條件包括哪些內(nèi)容? 上市證券的作用體現(xiàn)在哪里?
-
環(huán)球要聞:江蘇省會(huì)計(jì)中級職稱報(bào)名時(shí)間2023
-
什么是融資融券標(biāo)的證券? 融資融券標(biāo)的證券的條件有哪些內(nèi)容?
-
天天簡訊:罕見的 1970 年道奇 Polara 敞篷車在谷倉里停放了 20 年后終于上路了
-
什么是權(quán)益證券? 權(quán)益證券發(fā)行費(fèi)用扣除辦法是如何操作的?
-
在家用手機(jī)怎么賺錢
-
微信打車怎么打_如何用微信打車_環(huán)球播報(bào)
-
仙佑集團(tuán)積極應(yīng)對市場變化,實(shí)現(xiàn)膏藥行業(yè)穩(wěn)健發(fā)展
-
鄭州仙佑市場營銷案例分享 打造多元化產(chǎn)品矩陣
-
天天熱消息:無題
-
切塊抵押貸款證券的類型分別是哪些內(nèi)容? 切塊抵押貸款證券的特點(diǎn)具體如何描述?
-
什么是免稅證券? 免稅證券的內(nèi)容包括哪些?
-
【全球時(shí)快訊】贊美老師的名言警句_哪些名人名言是贊美老師的
-
想追“梅球王”不容易
-
現(xiàn)場直擊|貴州茅臺2022年度股東大會(huì)
-
綠色證券實(shí)踐中可能的問題和建議是怎么樣的? 綠色證券的研究與實(shí)踐進(jìn)展是如何的呢?
-
暖途
-
【天眼問政】打擊非法營運(yùn) 持續(xù)整治不手軟
-
每日報(bào)道:津津樂教丨振興縣中“大手筆”:啟動(dòng)建設(shè)100所縣域普通高中“徐特立項(xiàng)目”
-
北京地鐵孟藝兵創(chuàng)新工作室“供電程序員”為列車運(yùn)行安全續(xù)航
-
流通證券的特點(diǎn)包括哪些內(nèi)容? 流通證券的種類包括什么?
-
美景、民俗、文化、小吃……這里有你要的“詩和遠(yuǎn)方”
-
農(nóng)業(yè)銀行保險(xiǎn)產(chǎn)品可靠嗎?安全嗎?以農(nóng)銀人壽金穗傳家終身壽險(xiǎn)為例分析
-
速讀:重磅!監(jiān)管出手!部分機(jī)構(gòu)接到通知,下線! 環(huán)球視點(diǎn)
-
綠色證券政策存在的問題分別是什么? 實(shí)施綠色證券政策的建議是什么內(nèi)容?
-
全球視訊!鑫相伴尊享版怎么樣值得買嗎?收益多少?
-
范志毅、陳百祥都要帶隊(duì)來PK!貴州“村超”太頂了 天天時(shí)快訊
-
鑫相伴尊享版和樂盈一生做對比,從三個(gè)方面來看哪個(gè)值得買_環(huán)球即時(shí)
-
世界觀速訊丨北京城區(qū)首個(gè)夏商周遺址之謎:夏商時(shí)北京就能種水稻嗎?
-
明起四天北京持續(xù)高溫,局地最高氣溫可達(dá)39℃-當(dāng)前動(dòng)態(tài)
-
綠色證券政策的實(shí)施背景是怎么樣的呢? 我國綠色證券政策的主要內(nèi)容包括什么?
-
什么是可銷售證券? 可銷售證券的臨時(shí)投是怎么樣的呢?
-
環(huán)球觀熱點(diǎn):【天眼問政】打擊非法營運(yùn) 持續(xù)整治不手軟
-
70歲老人保險(xiǎn),哪種好,哪個(gè)值得買?
-
高考后放縱無度、感覺自己沒考好、填報(bào)志愿有沖突……怎么破?心理專家來支招
-
轉(zhuǎn)換債券的價(jià)值和價(jià)格分別是如何的呢? 可轉(zhuǎn)換證券的價(jià)值如何描述的?
-
八旬老人服用中藥降血壓致烏頭堿中毒,昏迷5小時(shí)獲救康復(fù)|前沿?zé)狳c(diǎn)
-
可轉(zhuǎn)換證券概述指的是什么? 可轉(zhuǎn)換證券的要素包含哪些內(nèi)容?
-
焦點(diǎn)速讀:椰奶紅豆糕團(tuán)購(椰奶紅豆糕)-關(guān)注
-
環(huán)球快訊:比利牛斯山犬_比利牛斯山犬
-
世界快看:破解青年就業(yè)難題尚有短板要補(bǔ) 專家建議修法增加特殊群體就業(yè)促進(jìn)制度
-
急急急!八旬老人失聯(lián)的34小時(shí)—— 天天觀察
-
生物科學(xué)專業(yè)是什么院系_生物科學(xué)專業(yè)主要學(xué)什么
-
天天百事通!真葡萄酒的鑒別方法?
-
西藏那曲市尼瑪縣發(fā)生3.7級地震 震源深度10千米 環(huán)球訊息
-
問后|已完工,終于通車了!
-
人壽保險(xiǎn)可靠嗎?分享中國人壽養(yǎng)老保險(xiǎn)價(jià)格表 每日頭條
-
6月13日 13:05分 普萊柯(603566)股價(jià)快速拉升
-
焦點(diǎn)要聞:江歌母親:劉鑫不服二審判決申請?jiān)賹?/div>遇到急事、險(xiǎn)情別怕!他們隨時(shí)準(zhǔn)備來救你! 天天報(bào)資訊77歲生日前夕,特朗普因刑事指控抵達(dá)佛州準(zhǔn)備出庭 全球快資訊北京14日至17日將出現(xiàn)持續(xù)性高溫天氣 局地最高溫可達(dá)39℃_焦點(diǎn)速訊鄉(xiāng)村籃球賽場上逐夢的年輕人|每日簡訊《人民日報(bào)》關(guān)注貴州:從“村超”看縣域體育生長當(dāng)前動(dòng)態(tài):針對這一病毒,中疾控提醒主食吃不夠,真的會(huì)折壽!5 種常見錯(cuò)誤吃法,快看你中招沒?_天天精選V觀財(cái)報(bào)|“7天6板”威龍股份:一季度業(yè)績與同行存一定背離 環(huán)球短訊A股午評:滬指窄幅震蕩跌0.06%,AI概念板塊持續(xù)活躍湘西州衛(wèi)監(jiān)局組織觀看警示教育片 堅(jiān)守安全生產(chǎn)“紅線” 滾動(dòng)談組詞_漢字談怎么組詞-要聞全球觀速訊丨2023年6月13日云南省西蘭花批發(fā)價(jià)格行情當(dāng)前資訊!撫養(yǎng)人因傷致死被扶養(yǎng)人生活費(fèi)應(yīng)該如何賠償流竄碰瓷團(tuán)伙四處作案 北京通州警方出手3人被刑拘禁錮怎么讀_禁錮的意思