首页 > 聚焦 > > 正文

解剖屎山,寻觅黄金之第二弹

2023-05-04 05:45:09 来源:程序员客栈

大家好,我3y啊。由于去重逻辑重构了几次,好多股东直呼看不懂,于是我今天再安排一波对代码的解析吧。austin支持两种去重的类型:N分钟相同内容达到N次去重和一天内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);//运营总规则去重(一天内用户收到最多同一个渠道的消息次数)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);}

那时候很简单,基本主体逻辑都写在这个入口上了,应该都能看得懂。后来,群里滴滴哥表示这种代码不行,不能一眼看出来它干了什么。于是怒提了一波pull request重构了一版,入口是这样的:

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);}});}

我猜想他的思路就是把构建去重参数和选择具体的去重服务给封装起来了,在最外层的代码看起来就很简洁了。后来又跟他聊了下,他的设计思路是这样的:考虑到以后会有其他规则的去重就把去重逻辑单独封装起来了,之后用策略模版的设计模式进行了重构,重构后的代码 模版不变,支持各种不同策略的去重,扩展性更高更强更简洁

确实牛逼。

我基于上面的思路微改了下入口,代码最终演变成这样:

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);}}}

到这,应该大多数人还能跟上吧?在讲具体的代码之前,我们先来简单看看去重功能的代码结构(这会对后面看代码有帮助)

去重的逻辑可以统一抽象为:在X时间段内达到了Y阈值,还记得我曾经说过:「去重」的本质:「业务Key」+「存储」。那么去重实现的步骤可以简单分为(我这边存储就用的Redis):

通过Key从Redis获取记录判断该Key在Redis的记录是否符合条件符合条件的则去重,不符合条件的则重新塞进Redis更新记录

为了方便调整去重的参数,我把X时间段和Y阈值都放到了配置里{"deduplication_10":{"num":1,"time":300},"deduplication_20":{"num":5}}。目前有两种去重的具体实现:

1、5分钟内相同用户如果收到相同的内容,则应该被过滤掉

2、一天内相同的用户如果已经收到某渠道内容5次,则应该被过滤掉

从配置中心拿到配置信息了以后,Builder就是根据这两种类型去构建出DeduplicationParam,就是以下代码:

DeduplicationParamdeduplicationParam=deduplicationHolder.selectBuilder(deduplicationType).build(deduplicationConfig,taskInfo);

Builder和DeduplicationService都用了类似的写法(在子类初始化的时候指定类型,在父类统一接收,放到Map里管理)

而统一管理着这些服务有个中心的地方,我把这取名为DeduplicationHolder

/***@authorhuskey*@date2022/1/18*/@ServicepublicclassDeduplicationHolder{privatefinalMapbuilderHolder=newHashMap<>(4);privatefinalMapserviceHolder=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);}}

前面提到的业务Key,是在AbstractDeduplicationService的子类下构建的:

而具体的去重逻辑实现则都在LimitService下,{一天内相同的用户如果已经收到某渠道内容5次}是在SimpleLimitService中处理使用mget和pipelineSetEX就完成了实现。而{5分钟内相同用户如果收到相同的内容}是在SlideWindowLimitService中处理,使用了lua脚本完成了实现。

LimitService的代码都来源于@caolongxiu的pull request,建议大家可以对比commit再学习一番:https://gitee.com/zhongfucheng/austin/pulls/19

1、频次去重采用普通的计数去重方法,限制的是每天发送的条数。

2、内容去重采用的是新开发的基于redis中zset的滑动窗口去重,可以做到严格控制单位时间内的频次。

3、redis使用lua脚本来保证原子性和减少网络io的损耗

4、redis的key增加前缀做到数据隔离(后期可能有动态更换去重方法的需求)

5、把具体限流去重方法从DeduplicationService抽取出来,DeduplicationService只需设置构造器注入时注入的AbstractLimitService(具体限流去重服务)类型即可动态更换去重的方法 6、使用雪花算法生成zset的唯一value,score使用的是当前的时间戳

针对滑动窗口去重,有会引申出新的问题:limit.lua的逻辑?为什么要移除时间窗口的之前的数据?为什么ARGV[4]参数要唯一?为什么要expire?

A: 使用滑动窗口可以保证N分钟达到N次进行去重。滑动窗口可以回顾下TCP的,也可以回顾下刷LeetCode时的一些题,那这为什么要移除,就不陌生了。

为什么ARGV[4]要唯一,具体可以看看zadd这条命令,我们只需要保证每次add进窗口内的成员是唯一的,那么就不会触发有更新的操作(我认为这样设计会更加简单些),而唯一Key用雪花算法比较方便。

为什么expire?,如果这个key只被调用一次。那就很有可能在redis内存常驻了,expire能避免这种情况。

推荐项目

最后再叨叨吧,很多人可能会发一段截图,跑来问我为什么要这样写,为什么要以这种方式实现,能不能以这种方式实现。这时候,我更想看到的是:你已经实现了第二种方式了,然后探讨你写的这种方案好不好,现有的代码差在哪里。

毕竟问问题很简单,我又不是客服,总不能没诚意的问题我都得一一回答吧。

如果想学Java项目的,我还是强烈推荐我的开源项目消息推送平台Austin,可以用作毕业设计,可以用作校招,可以看看生产环境是怎么推送消息的。

仓库地址(可点击阅读原文跳转):https://gitee.com/zhongfucheng/austin

我开通了股东服务内容,感兴趣可以点击下方看看,主要针对的是项目哟

VIP服务

标签:

解剖屎山,寻觅黄金之第二弹

大家好,我3y啊。由于去重逻辑重构了几次,好多股东直呼看不懂,于是我今天再安排一波对代码的解析吧。aust

2023-05-04 05:45:09

飞蛾扑火歌曲原唱_飞蛾扑火的意思

1、飞蛾扑火,从科学的角度上来说,其实飞蛾只是保持自己的飞行方向与光源成一定角度,随着它不断的飞,它

2023-05-04 03:49:23

绿茶冲泡时间_应该怎么泡 当前快播

欢迎观看本篇文章,小勉来为大家解答以上问题。绿茶冲泡时间,应该怎么泡很多人还不知道,现在让我们一起来

2023-05-04 00:57:14

千亿“锂王”高价买矿受挫

时隔近五年,天齐锂业再次对海外锂矿资源出手,却遭拒绝,背后原因何在?此事又会否影响天齐锂业接下来的买

2023-05-03 22:39:27

天天头条:男子向白金汉宫空地投爆炸物后被捕,究竟是怎么一回事?

正文摘要:央视新闻客户端消息,当地时间5月2日晚,一名男子在向英国白金汉宫空地投掷爆炸物后被捕。英国警

2023-05-03 21:51:14

环球速读:总收入和经营利润创新高 百胜中国一季度业绩“开门红”

5月3日,百胜中国控股有限公司(以下简称“百胜中国”)公布了截至2023年3月31日第一季度业绩。

2023-05-03 21:00:51

分期乐借款综合评分不足是怎么回事?

若分期乐借款综合评分不足,很可能是以下几点原因导致的:1、分期乐还款逾期了用户之前在分期乐申请的借款

2023-05-03 20:07:44

本兮吧难唱_本兮吧

1、唔。2、这个的确是兮爷的说。3、本兮,本名马晓晨,90后原创女生第一人。4、擅长词曲创作。5、15岁开始

2023-05-03 19:00:17

一斤等于多少两黄金_1斤黄金等于多少两

1、简单告诉你一下吧:内地(新算法)都用10两称来称,那么1斤=10两。2、1两=10钱,1钱=5克;

2023-05-03 18:08:12

通讯!四川攀枝花的抗旱“保卫战”

封面新闻记者周翼4月26日下午2点,一张对流性云层的气象图片,让四川攀枝花市米易县一个“三农”微信工...

2023-05-03 17:19:38

天天最资讯丨猪肉有粪臭是怎么回事 猪肉有粪臭味

1、饲料所致的劣质肉有废水或药等气味;病理所致的有油脂、粪臭、腐败、怪甜等气味。种用公母猪肌肉较红,结

2023-05-03 16:20:41

环球速讯:预计5月2日到达旅客58万人次!铁路上海站迎来返程客流高峰

记者从铁路上海站(下辖上海站、上海南站、上海虹桥站、上海西站、南翔北站、安亭北站、安亭西站)获悉,5

2023-05-03 15:56:30

全球速读:小说下载网站哪个好趣书_小说下载网站哪个好

1、搜狗,在这个网站下载的资源丰富,而且是用迅雷,速度有保障。2、安全方面也无病毒,我下小说就在这下。

2023-05-03 14:58:06

【全球新要闻】老鹅怎么烧好吃王刚_老鹅怎么烧好吃

1、主要材料:五花肉500g,鹅肉500克,冰糖30克,桂皮1个,八角1个,生抽20毫升,老抽5毫升,葱段1把,生姜适量

2023-05-03 13:55:10

菊花晶的功效与作用是什么_菊花晶的功效与作用

1、您好,菊花晶以优质菊花经科学提炼成膏后,配白糖粉等加工制作而成。2、适用于兑在牛奶中饮用,也可作清

2023-05-03 12:58:45

世界热消息:海洋开发与管理重复率_海洋开发与管理

1、1 在保证海洋资源可持续利用的基础上,强化开发深度和广度,提高开发的科技含量,不断提高海洋开发和海

2023-05-03 12:00:50

以色列与加沙地带武装组织达成停火协议 焦点资讯

综合路透社和半岛电视台报道,巴勒斯坦官员表示,以色列和加沙地带的巴勒斯坦武装组织当地时间5月3日已同意

2023-05-03 11:08:28

每日看点!1元的“出行神器”:不到80克,能救命

1元的“出行神器”:不到80克,能救命

2023-05-03 10:10:12

城固有哪些古诗 关于张骞的诗句和歌词_观天下

抄写作文网小编为大家提供城固有哪些古诗关于张骞的诗句和歌词来供大家参考,欢迎阅读。关于张骞的诗句和歌

2023-05-03 09:13:30

每日消息!“一名中国公民受伤”,驻以色列使馆再次提醒!

驻以色列使馆再次特别提醒在以中国公民切实加强安全防范当地时间5月2日下午,以色列南部地区遭受火箭弹袭击

2023-05-03 08:25:48

要闻:劳动者风采丨河钢集团张宣科技氢冶金公司:“氢装”上阵 绿色冶金

“氢装”上阵绿色冶金——河钢集团张宣科技氢冶金公司技术创新引领行业低碳转型图为河钢集团张宣科技氢...

2023-05-03 07:36:34

网友质疑cp29不检票对买票者不公平:大量无票人员混入 观热点

鞭牛士5月2日消息,据沸点视频,今日,上海同人展cp29不检票,出现大量没有票的人混进去的情况,导致场内人

2023-05-03 05:59:00

洛克王国审判者之刃在哪个位置_洛克王国审判者之刃 当前独家

1、获得方法可以在沃尔摩广场。2、击杀六级蜘蛛网就可以调到货的。以上就是【洛克王国审判者之刃在哪个位置

2023-05-03 04:13:26

八拜之交是哪八拜之交典故_八拜之交指哪八拜 焦点简讯

1、八拜之交指:管鲍之交、知音之交、刎颈之交、舍命之交、胶漆之交、鸡黍之交、忘年之交、生死之交。2、管

2023-05-03 01:16:08

Dekek德科康签约奥运冠军张梦雪 简讯

近日,德科康品牌升级发布会暨代言人签约仪式在广西南宁举行。这是Dekek德科康品牌升级的重要战略发布,同

2023-05-02 22:16:42

青柠檬好还是黄柠檬好 减肥 青柠檬好还是黄柠檬好

明日方舟新章孤星读后随笔 环球新资讯

乌克兰议会通过延长战时状态和总动员令的法案-天天热点评

报警!知名首席,终于回应→

前沿热点:大电竞专访BLG下路组Elk&ON:GAM就等着被我们“血虐”吧

科创板光学企业排名(科创板光学公司市值排名)-全球速读

【今日中国】飞越美丽河山 奋斗成就梦想 全球要闻

马斯克:再加息,严重经济衰退将来临 环球热头条

VOGUE官方把蔡徐坤认成王嘉尔事件简单介绍|环球快报

环球今头条!恒宇集团(02448)于盘中短暂停牌

4399游戏币怎么获得_4399游戏币怎么免费得

每日热议!浴盐是什么_浴盐专业解释

救助第一共和后,摩根大通CEO发声:危机已基本结束 焦点日报

每日速讯:2023年5月2日山东省氯磺酸价格最新行情预测

微资讯!“五一”假期前三天发送旅客总量约1.6亿人次

形容时间变化的语录 形容时间变化的语录短句

官方最新回应!租户装修砸掉承重墙,全楼200户居民被紧急疏散... 天天速读

每日播报!让人觉得高攀不起的女孩,大多都有这样5个特质,看看你是否也有

环球信息:考据学兴起的原因_考据学

微头条丨没有劳动合同怎么证明劳动关系_劳动合同期限三个月以上不满一年

端午节吃粽子的由来和风俗_端午节吃粽子的由来作文 天天即时

俄专家:西方银行业危机或加速“去美元化”进程_环球看点

“蛟龙”潜底架通途!大连湾海底隧道今天通车 世界热点

2023年4月28日券商公司市值排行榜|券商排行榜_今日热讯

【世界速看料】华为nova 11真机评测:超感知影像+nova游戏引擎,硬核性能真的香

x 广告
x 广告

Copyright @  2015-2023 非洲家电网版权所有  备案号: 沪ICP备2022005074号-8   联系邮箱:58 55 97 3@qq.com