解剖屎山,寻觅黄金之第二弹 全球看点
大家好,我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);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);}}
前面提到的业务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端午节石家庄景点汇总(持续更新) 环球最新
- 罗氏药物Columvi获FDA批准,预计未来几周在美国上市 今日热文
- 中国移动发布短视频生态合作计划!
- 覃海宁:生物多样性保护可以从原地保护和迁地保护着手|世界看点
- 女子右手卡进机器滚轮,聊城消防员5分钟快速救援
- 环球讯息:云南白药CEO董明谈云南白药的“变与不变”
- 大悦城控股:“20大悦01”不行使赎回选择权 下调票面利率为3.15%-全球新要闻
- 看热讯:中国著名出版社联合发布学术图书英译成果 力推中国学术走向世界
- ET5 Touring引人瞩目 可蔚来还是更需要一款“Model Y”
- 一图读懂“亮剑浦江”上海个人信息保护专项行动:为期半年,“剑”指八大消费场景
- 2023合肥城乡居民医保补缴流程
- IMF:欧元区通胀仍强劲 欧洲央行需进一步加息并保持紧缩
- 胎动是什么(胎动的症状是什么样的)|当前要闻
- 新一轮防守反击打响,A股夏季攻势焦点
- 观城·宜宾丨2023动力电池大会硕果累累,促高校毕业生就业如火如荼-今日热闻
- 每日速讯:Brand Finance发布全球酒店品牌Top50榜单
- 豪捐3.5亿人民币,盛赞袁隆平,“访华常客”比尔盖茨这次来华在关注什么?
- 当前通讯!卓创资讯:白羽肉鸡6-7月市场行情或延续季节性下滑走势
- 贵州省普安县发布雷电黄色预警
- 2023秋季学期湖南开学时间是几号
- 焦点热议:年内三季度风电新增装机534万千瓦 同比增长0.72%
- 梦幻西游2008买下4000亿经验角色,9年前6k5买满修号还带装备和BB
- 环球热点评!英特尔发布全新硅自旋量子比特芯片Tunnel Falls,推动量子计算走向实用
- 在大连打进国足首球 林良铭:我会贡献所有的力量给国家队
- 五部门:支持保险机构扩大农村居民意外伤害险、健康保险、养老保险等产品供给 看点
- 报道:宝馨科技
- 坐地铁直达上海!苏州11号线轨交今日免费试乘:6月运营 今日讯
- 远大再定合肥滨湖高端改善,万众瞩目的BK202303号地块案名正式发布!|新动态
- 奖励一套房,慰问金10万!最新回应:都不收
- 湖人后悔了吗?湖人旧将再夺总冠军成热火克星!_当前头条
- 世界球精选!智明达: 公司有将AI技术用于项目研发,目前暂无研发生产AI服务器的计划
- 环球头条:业内人士:预计PC换机潮将在2024年出现 对相关芯片需求有望明显增长
- “八大突破”提供更实用住房保障服务 苏州公积金灵活就业试点2.0版7月1日实施
- 分享米饭团子的简单做法 ,秒变米饭杀手_微资讯
- 打造新团队!Woj:蒙蒂聘请杰克担任活塞助理教练|天天滚动
- 渤海银行积极参与2023年全民反诈宣传活动_今日热门
- 芯片初创公司【Etched.ai】完成536万美元种子轮融资,Primary Venture Partners 领投
- 【世界聚看点】2023昆明市第一中学高中招生公告 附学费+咨询电话+人数
- 【全球报资讯】服务设计为互联网剪辑类工具带来新机遇
- 当前头条:大泽电极近期获得首批由昆明市市场监督管理局审定批准的“知识产权运营服务体系建设专利密集型产品”的认定
- (聚焦海峡论坛)“海峡金融论坛·台企发展峰会”启幕 台港澳青年创新创业获“大礼包”-环球视点
- 添新规了!故宫管理更规范更细致
- 环球即时:华脉科技:控股股东筹划重大事项 股票6月19日开市起停牌
- 环球焦点!安康还有这样一所大学,你知道吗?
- 惠同新材北交所IPO注册获批:拟募资约1.66亿元 用于年产350吨金属纤维项目等
- 纳尔股份(002825.SZ):股东王树明及杨建堂减持期过半 已减持合计3.86%股份
- 当前看点!粤港澳大湾区车展:坦克500 Hi4-T 月底上市,坦克400 Hi4-T华南首秀
- 打造开放高地 江西赣州国际陆港“融湾”再加速
- 家长反对家委会收费犒劳考生被班主任踢出群,当地教育局介入_每日快播
- 每日焦点!IPO观察丨从亿晶光电套现超30亿后 荀建华家族再建“小号”冲击上市引质疑
- 世界快资讯丨阿里巴巴全球数学竞赛决赛6月17日正式打响
- 热门看点:郑州高新区枫杨办事处深入开展“随手拍”宣传活动
- 怀孕8个月女子遭连开4枪,母子皆亡,被害时正与丈夫在车里等红灯-天天热闻
- 省委召开专题会议研究推进小流域综合治理试点工作 每日讯息
- 全球速看:抖音如何开橱窗卖东西?怎么引入流量?
- 世界微动态丨无尽剑路西法口诀(无尽剑路西法)
- 四川省1-5月规模以上工业增加值同比增长2.9% 天天播报
- win7如何加密磁盘 windows7怎样给磁盘加密-当前热门
- 环球今日报丨2023昆明市第七届运动会志愿者福利有哪些?
- 莲湖区红庙坡街道召开重点项目·企业招商推介大会 奏响地区高质量发展强音|环球滚动
- 每年花300亿吃榴莲,中国人为何榴莲成瘾?
- 环球观天下!孩子改随母姓,父亲就能不用再付抚养费了?
- 预见:探讨近期分布式光伏的变化 每日热文
- 美国得州等多地遭遇龙卷风,5000万人受恶劣天气威胁金十期货6月16日讯,6月16日,据美国有线电视新闻网报道,美国多地遭遇龙卷风,大片地区有超过5000万人受到恶劣天气的威胁,可能会再次出现风暴、冰雹、强风和龙卷风等恶劣天气 天天讯息
- 芯海科技通过ISO 26262功能安全管理体系ASIL D认证_当前关注
- 激发国内市场活力 二季度消费市场有望保持平稳增长态势|当前快讯
- 世界快看点丨618活动火热进行中!龙腾四海止盈通力科技超50%!
- 当前短讯!(聚焦中国高质量发展)以侨为桥 泉州优品“扬帆出海”
- 西延高铁马坊隧道及北村隧道相继贯通 天天快报
- 世界热议:预计年内上市 奇瑞TJ-1官方定名探索06
- 34.5亿+15%溢价率!城建竞得朝阳奶西29-315-1地块_当前报道
- “天擎”诞生记——高效制取绿氢 降低终端用氢成本!
- 硬核科技论|别被洗脑 双电机有时候并非你所想 天天关注
- 当前短讯!电小二SG 2000 Plus户外电源亮相慕尼黑太阳能展会,支持光伏充电
- 天天观速讯丨选华为,还是特斯拉,或者自研?车企们要面临三选一了
- 我国成立绿色建筑全国重点实验室推动建筑业清洁低碳转型|环球观点
- “防溺水”应急演练走进郑州水务集团水源厂 环球快看点
- 财政部:1-5月全国税收收入84774亿元,同比增长17%_全球百事通
- 天津市路灯管理处组织开展达沃斯灯杆道旗宣传布展_天天时快讯
- 局部大暴雨 安徽启动暴雨Ⅳ级应急响应
- 世界关注:中国商业智能行业发展现状分析2023
- Global licensing industry optimistic about Chinese market 今日热闻
- 全球微速讯:平安人寿重庆分公司:关于理性消费、合理借贷的提示
- 河南郑州航空港组织开展“粽香传情 爱在港区”主题党员志愿服务活动
- 怎样看病最能省钱?
- 华昌达副董事长突然失联 或与第二大股东涉嫌合同诈骗相关 世界实时
- 五部门:截至4月末涉农贷款余额53.16万亿元 同比增长16.4%
- 模拟输入24位立体声ADC(数模转换器)CJC1808
- 天天通讯!“2022十大重庆经济年度创新人物”参评人|唐浩夫:以投资创造价值,为中国医疗产业升级贡献力量
- 天天看热讯:青岛首批供地:14宗地揽金106亿元 海信、中海、越秀落子
- 《雨世界》7月11日推出PS5和Xbox版 主机DLC同日发售|天天资讯
- 合盛硅业: 朋友公司目前尚无有机硅期货业务,仅有工业硅期货业务 当前快报
- 盛会将至!第十三届烟台国际葡萄酒博览会6月16日开幕|热点评
- 昔日石山今披绿装 重庆石漠化土地五年减逾440万亩_新要闻
- 今日看点:“微手术”避免“通天口” 青滨附院实现一次手术治疗两种疾病
- 环球快讯:拼多多如何摆脱“小玩意儿”
- 2023西安美术馆6到7月展览活动内容
- 【在希望的田野上】小麦主产区多措并举稳产保丰
- 长兴制药将持有的长兴恒力小额贷款有限公司5%股权以323.3万转让给标的公司股东韩玲玉 最新