解剖屎山,寻觅黄金之第二弹_今日热搜
大家好,我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服务
标签:
- 世界百事通!初音未来的男朋友叫什么名字_初音未来的男朋友
- 世界观天下!一杯“荷塘咖啡”撬动文旅融合产业链 村民享受文旅发展红利
- 从缅甸逃回男子自述:水牢满地是血,女子遭囚禁虐打,好看的被卖至娱乐场所|看点
- 全球今年恐迎来厄尔尼诺“大烤”_热门看点
- 一张图:2023/07/03黄金原油外汇股指"枢纽点+多空占比"一览
- 黄酒怎么泡红枣?
- 定海浮生录·叁-每日关注
- 午评:两市放量上行沪指涨1.29% 汽车与保险行业领涨 世界即时看
- 【天天速看料】新田:李祥佐走访慰问困难党员和老党员
- 微头条丨服务不间断 持续助力高校毕业生就业
- 同情他们!第一批“吃螃蟹”的那些人,正提心吊胆开电动车
- 焦点简讯:成都东软学院学费多少_成都东软学院学费
- 呼和浩特强降雨引发山洪,致1人死亡2人失联
- 小暑吃黄的好处及方法
- 安控科技7月3日快速上涨
- 十年寒窗无人问一举成名天下知雪怕太阳草怕霜人怕没钱情怕伤_十年寒窗无人问
- 实时焦点:我恨狮子座人数_我恨狮子座
- 株洲桂娟餐饮服务有限责任公司_关于株洲桂娟餐饮服务有限责任公司概略-热推荐
- 毕业生报到证去哪里报到(毕业生报到证)|焦点精选
- 全球热消息:英国脱欧的原因及事件经过(英国脱欧的原因)
- 今日热议:津城天气:雷阵雨“灭火”!别想得美!
- 环球要闻:对虚开骗税等涉税违法行为亮剑出击广州市税务局释放税务稽查执法刚威
- 汕尾陆丰警方通报一加油站发生火灾:涉嫌放火者已被刑拘 全球播报
- 罗马诺:切尔西将继续与布莱顿谈凯塞多转会;球员已同意加盟-当前信息
- 全球今亮点!重庆启动水旱灾害防御Ⅳ级应急响应
- 9月上市/定位高于深蓝SL03 启源A07更多消息露出 全球最资讯
- 十个人电梯超重的问题_十人电梯超重官方答案 天天动态
- 红米手机参数配置对比(红米x40手机参数)
- 今日观点!《红楼梦》《小美人鱼》,“国家队”以芭蕾“明珠”点亮申城夏夜
- 世界最大跨径公轨两用悬索桥进入主塔施工阶段|世界百事通
- 世界观速讯丨喜报!我校7门课程新入选国家级一流本科课程
- 当前信息:蜗牛移动怎么查话费?_蜗牛移动怎么查话费
- 中金岭南韶关冶炼厂新增12万吨锌基新材建设项目(一期)工程开工_通讯
- 注意,发票作废的时代或将结束!
- 每日速看!秦静温乔舜辰最新章节1350章
- 局长信箱怎么查询回信西安医疗保障局(局长信箱怎么查询回信)
- 丹佛斯变频器面板按键说明图_变频器面板按键说明书
- 美国今年已发生186起儿童意外枪击事件 当前简讯
- 温网开赛前迎坏消息!郑钦文的运气太差了,网友:又要白忙活? 环球要闻
- 上财校友会无锡讲座分享会-环球快消息
- 【独家焦点】路面更平整,通行更顺畅!他们积极探索社区治理新模式
- 高校该不该开放?有商家将高校参观做成“付费生意”
- 世界即时看!视点|又见卖菜“小过重罚”11万,执法公平不能只靠法院兜底
- 麦博m111电路图(麦博m-111)_环球观点
- 中东土豪百亿补贴,高合汽车“续”上了?
- “第三支箭”落地 上市房企定增连续获批背后的市场脉搏 头条焦点
- 基督教歌曲耶稣爱你_天主教耶稣爱你网
- 儿童新冠二阳了怎么办 二阳会不会出现新冠后遗症 基本情况讲解
- 雅虎记者:阿努诺比希望在进攻端扮演更重要角色&想要多持球
- 高温催生避暑旅游热 :中信证券及外资扎堆买入加仓长白山,涨停还有几个
- 新资讯:在马赛遇袭中国游客已前往瑞士并提前回国
- 赵鹏获任中国人保党委副书记
- 惠来县发布暴雨橙色预警
- 《夏目友人帐》将制作第七季 ,15周年庆祝影片公开
- 当时明月在——怀念林文月教授丨人来人往
- 王源被人民文娱点评,言辞犀利,句句说到观众的心坎里 世界微头条
- 阿根廷首次使用人民币偿付到期外债 天天速递
- 2022~2023年内蒙古养老金调整新消息和养老金上调细则最新消息(全文)_天天快看点
- 甘肃省中级职称评审需要哪些资料_甘肃省中级职称评审
- 又一家科创型生物医药企业落地宝山!
- 台退役少将于北辰言论被台海军前舰长打脸:我同学真的不知道_全球快看
- 超长约!格兰特5年1.6亿回归开拓者 环球速讯
- 赛尔号格尔顿(查尔顿 赛尔号精灵) 全球聚看点
- 每日速递:党建引领“五共”善治 ——创新基层治理的“大冶样本”
- 焦点简讯:苹果成为首家收盘市值达到3万亿美元的公司 iPhone 15换机周期要来了
- 雄县属于哪个市哪个省(雄县属于哪个市)
- 曝汪姓男艺人性侵19岁女子 具体是什么情况? 当前观察
- 掘金夜经济
- 邢台巨鹿:“红色驿站”里学习忙 世界球精选
- 神十六航天员是哪三位简介(董志川讲天文科普:航天员拍到月亮羞答答溜走)
- 360的老板_360老板是谁
- 世界即时看!张韶涵买的小岛图片(张韶涵买下太平洋小岛)
- AMD R5 5600X3D 处理器海外上架:6 核 12 线程,96MB 三级缓存
- 高考放分了,这些防骗“判断题”要答好-今日精选
- 全球热头条丨金银河:子公司碳酸锂产品中试生产线已投入生产运行并已实现产品销售
- 世界微头条丨word转jpg格式图片怎么弄手机_word转jpg
- 歌尔股份:上半年净利润同比预减76%-84% 全球微速讯
- 台湾黑社会老大(关于台湾黑社会老大的基本详情介绍)
- 播报:集泰股份:与武汉大学共建先进材料研究中心
- 国家外汇管理局公布2023年5月我国国际收支货物和服务贸易数据
- 东风不与周郎便 铜雀春深锁二乔原文 赤壁原文及翻译 世界热资讯
- 每日播报!温暖2023 | 十大最具影响力短视频火热征集中
- 果然是油画大师,丹麦油画之父画的美女,色彩明艳!
- 来自虞美人之坡结局 来自虞美人之坡简介
- 世界微资讯!什么叫开脸观音_什么叫开脸
- 莱音珠宝黄金价格今天多少一克(2023年06月30日)
- 每日观点:演员这首歌的歌词(演员的歌词是什么)
- 曾红娟(关于曾红娟介绍)
- 一天拆除14座桥 湖北交投集团打造“映山红”改扩建特种兵
- you suck翻译(you suck)-全球速讯
- 中航电测6月30日快速上涨 环球精选
- 今日热门!宗地镇戈岜小学志愿服务队
- 全球快资讯丨醉酒后故意伤害怎么判
- 27.77万亿元!公募基金规模再创历史新高
- 【天天报资讯】6.30盘前策略 今天继续实盘实时分享抓涨停
- 雅戈尔(600177):6月29日北向资金减持61.27万股
- 全球微速讯:国乒女单2人出局,钱天一爆冷不敌日本小将,何卓佳完败于孙颖莎
- 贵州和广西,主打一个双向奔赴!
- 装修建材板块6月29日跌1.63%,坚朗五金领跌,主力资金净流出2138.97万元 天天快播
- 世界今热点:一周数读
广告
广告
- 如何验证翡翠的真假?只需要简单8步 天天短讯
- DJI RS 3 Mini发布:2千克负载仅795克,支持快速竖拍 天天新消息
- 形容法律威严的句子(精选187句)
- 《宝可梦》满血情况下受到的伤害减半,能带来多少对战机会?
- 世界热推荐:活力中国丨在忙碌的生产线感知中国经济活力
- 全球消息!海南航空回应男子在航班上喊飞机要出事:该名旅客已移交机场公安
- 陆金贷(小额应急)网贷逾期3年多久上征信|全球百事通
- 比亚迪继续减持比亚迪股份,半年已减持超30%
- 胎压监测板块1月9日涨0.91%,通达电气领涨,主力资金净流出2377.78万元_环球快消息
- 世界速看:陆金贷(小额应急)贷款逾期八天延迟还款会影响征信吗
- 記者觀察|封關壬寅末終落幕 港深雙城記開新篇 世界微动态
- 南开区16岁小孩抚养费一般多少钱
- 世界微头条丨十来万的车,我选卡罗拉
- 新华视点|商圈火、景区旺 各地消费市场显活力|聚焦
- 每日热门:光猫和路由器怎么连接 光猫和路由器的正确连接方法
- 蔬菜生吃还是熟吃?你是哪一派?|天天观点
- 天天消息!九典制药(300705.SZ):非洛地平片获批上市
- 热水泡脚脚痒是怎么回事?-环球时快讯
- 面试时,最可怕的就是背调?-世界视点
- 环球短讯![快讯]广联航空:关于特定股东减持数量过半的进展






