当前位置: 首页 > 后端技术 > Java

后端如何实现幂等和去重?

时间:2023-04-01 20:22:00 Java

采访者:说说最近在看的东西吧?大家可以拉出来一起讨论。考生:最近在看“去重”和“幂等”相关的内容。面试官:那你可以先谈谈你对“去重”和“幂等”的理解。考生:我觉得“幂等性”和“去重”很相似,我也分不清它们之间的严格区别。候选人:说说我个人的理解吧,不知道我说的对不对“是在”一定时间内“对一个请求或消息去重”N次“的候选人:”幂等“是保证一个请求或消息在“任意时间内”被处理,需要保证其结果一致候选:无论是“去重”还是“幂等”,都需要有一个“唯一Key”和一个“存储”唯一KeyCandidate的地方:以项目为例,我维护的“消息管理平台”有“去重”功能:“5分钟内对相同内容的消息进行去重”、“消息去重”1小时内模板”、“通道去重一天内达到N倍阈值”……考生:再次强调“幂等性”和“去重”的本质:“唯一键”+“存储”面试官:你怎么做呢?比如“本地缓存”/“Redis”/“MySQL”/“HBase”等等,选择什么也跟业务有关。考生:比如“消息管理平台”的场景,我存储的是选择的“Redis”(读写性能优越),Redis还有一个“过期时间”,方便解决“某段时间”题主:而唯一键自然是根据不同的业务构造的。考生:比如“5分钟内对相同内容的消息进行去重”,我直接使用MD5请求参数作为唯一键。“1小时内模板去重”使用“模板ID+userId”作为唯一key,“一天内通道去重”使用“通道ID+userId”作为唯一key...面试官:既然提到了“去重”,你听说过布隆过滤器吗?应聘者:我当然知道。面试官:说说Bloomfilter,你怎么不用呢?考生:布隆过滤器的底层数据结构可以理解为位图,位图也可以简单理解为数组。元素只存储0和1,所以占用空间比较小。考生:当一个元素要存储在位图中时,其实需要看位图中存储在哪个位置。这时一般使用hash算法,将存储的位置标记为1个候选:标记为1的位置表示存在,标记为0的位置表示不存在候选:布隆过滤器可以判断一个元素是否存在,具有空间占用低,然后用于去重,但它也有相应的缺点候选:只要哈希算法离不开“哈希碰撞”,导致“误判”的候选:在布隆过滤器中,如果一个元素是确定存在,则元素“可能不”实际存在。如果判断元素不存在,那肯定没有候选:不用我解释这么多吧?(结合“哈希算法”和“标记为1的位置表示存在,标记为0的位置表示不存在”可以得出以上结论)考生:Bloomfilter不能“删除”元素(是也是hash算法的一个局限性,无法准确定位到Bloomfilter中的某个元素)考生:如果要用的话,Bloomfilter的实现可以直接用Guava来实现,不过这个是stand-单独应聘者:Redis一般用于分布式Bloomfilters,但并不是每个公司都会部署Redis版本的Bloomfilters(它还是有局限性的,像我之前的公司就没有)。考生:所以目前我负责的项目都没有使用布隆过滤器(:考生:如果“去重”的开销比较大,可以考虑建立一个“多层过滤”的逻辑候选:比如,先看“本地缓存”能不能过滤一部分,剩下的“强验证”交给“远程存储”(常见的Redis或者DB)进行二次过滤面试官:嗯,那我记得你上次回答Kafka面试官:当时你说在处理订单的时候至少实现了一个+幂等面试官:在进行幂等处理的时候:Redis用于预过滤,DB的唯一索引用于强一致性校验,这也是为了提高绩效吧??面试官:好像只有“订单号+订单状态”面试官:面试官你记性真好!面试官:一般我们要检查数据的一致性,所以我们直接上MySQL(DB),毕竟有事务支持的候选:“本地缓存”如果业务合适,可以作为“预判”候选:Redis高性能读写,预判和后判都可以(:考生:而HBase一般用在大数据量的场景下(Redis内存太贵,DB不够灵活,不适合存储大量数据在单表中)考生:至于幂等,一般存储还是“Redis”和“数据库”考生:最最最最常见的是数据库的“唯一索引”实现幂等(几个项目我负责用这个)候选人:建立“唯一键”是业务相关的事情(:通常是和自己的业务ID拼接,生成一个“有意义”的唯一键候选人:当然是“Redis”和“MySQL”"也用于实现分布式锁实现幂等(:考生:但是Redis分布式锁不能完全保证安全,而MySQL实现了分布式锁(乐观锁和悲观锁看业务,我没用过)。考生:网上有很多“幂等”的方案,本质上都是围绕着“存储”和“UniqueKey”做了一些变体,然后取了个名字……考生:总的来说,改汤不换药(:面试官:嗯……明白了,欢迎关注我的微信公众号【Java3y】聊Java面试,在线面试官系列持续更新中!【在线面试官-手机端】】一周连载两篇持续更新中!【在线面试官-电脑】系列一周连续更新两篇!原创不易!!求三连!!