美团财务科技后端一面:如何保证数据一致性?延时双删第二次失败如何解决?

更多大厂面试内容可见 -> http://11come.cn

美团财务科技后端一面:项目内容拷打

美团财务科技后端一面:项目相关面试题,主要包含 Zset、延时双删失败重试、热点数据解决、ThreadLocal 这几个方面相关的内容

由于前几个问题是对个人项目的介绍,根据自己项目进行回答即可

是个人进行项目开发的吗?

如何进行系统设计的?

项目是否已经上线?

在项目开发中遇到的难点?如何解决?

项目开发过程中有什么收获?

Zset 底层数据结构,为什么要用Zset?

Zset 的底层实现是:压缩列表 + 跳表

什么时候使用压缩列表?

  • 有序集合保存的元素个数小于 128 个
  • 有序集合保存的所有元素成员的长度都必须小于 64 字节

否则使用跳表

跳表在 Redis 中的作用就是作为有序集合类型的底层数据结构,

跳表中每个节点保存着其他节点的指针,高层的指针越过的元素数量大于等于低层的指针,因此在跳表中,在查找元素时可以一次跳过多个节点,当找到大于或等于目标元素的节点后,再使用普通指针开始移动(可以向后移动,也可以向前移动,跳表含有前边节点的指针)寻找目标元素,跳表可以在 O(logn) 的时间内遍历跳表

跳表结构图:

1697874023019

至于为什么要用 Zset 结合自己的项目说的合理即可

你如何保证缓存与数据库一致性,延时双删的第二次删除缓存失败了呢,如何解决?

这个要看延时双删具体如何实现了,先说一下它的流程:

用户发起更新数据的请求
1、删除数据对应缓存
2、更新数据库
3、休眠一段时间(等待数据库更新完毕之后)
4、再次删除数据对应缓存

这里要休眠一段时间等待第二次删除缓存,因此可以通过 Redisson 的延时队列来做,将第二次删除缓存的信息发送到延时队列中,等待被消费

在消费的时候可以去对失败操作进行处理,从延时队列中取出消息进行消费,如果失败了,可以进行指定次数的重试,如果只是因为网络抖动失败,那么一般重试就可以成功消费了,但是如果是 Redis 出现了问题,那么这一段时间内重试可能都还会存在问题,因此要考虑将失败的消息给放在数据库中存储起来,再定时进行消费对失败的消息进行补偿(不过 Redis 宕机的概率很小,一般不会发生)

上边是个人思路,如有不足欢迎补充

Redis 如何存储热点数据?

热点数据就是某些数据访问频率过高

首先对于热点数据要先可以检测到,检测之后再看具体如何解决

检测的话,可以使用京东零售开源的 hotkey 框架,是一个轻量级通用热 key 探测中间件,可以快速将热数据推送到 JVM 内存,减少大量请求对下游服务、Redis、MySQL 的冲击

那么热点数据的存储的话,可以存储一份到 JVM 内存中,进一步提升数据的查询性能,可以选用 Caffeine (Java 高性能缓存库)来管理 Redis 的热点数据,Caffeine 是基于 Google Guava 改进的,因此 Caffeine 的性能表现、缓存命中率相对来说更好

项目为什么要用 ThreadLocal?ThreadLocal 如何保证线程隔离的?

项目为什么要用 ThreadLocal ,这个可以基于 ThreadLocal 的特性来回答

在多线程环境下,有些数据是你当前线程上下文中要使用到的,但是如果每次调用方法都将这些数据传递过去,或者每次使用的时候都重新过去是比较麻烦的,并且也会带来一定的时间开销,因此可以存储在 ThreadLocal 中,在当前线程的上下文中进行使用

这样在用到数据的时候,直接从 ThreadLocal 中取出来,既保证了线程之间的数据隔离性,又保证了较好的性能(不必重复去获取)

ThreadLocal 如何保证线程隔离的?

如下图,在每一个线程 Thread 中都会定义一个 ThreadLocalMap 属性,该属性就存储 ThreadLocal 所对应的值,那么每个线程中都有一份 ThreadLocalMap 的变量,以此来实现线程隔离

ThreadLocal保证线程之间数据隔离

扩展:ThreadLocal 正确使用姿势

ThreadLocal 的使用规范:将 ThreadLocal 变量定义为 private static final ,并且在使用完,记得通过 try finally 来 remove 掉,避免出现脏数据

扩展:ThreadLocal 内存泄漏问题

ThreadLocal的内存泄漏问题

这里假设将 ThreadLocal 定义为方法中的局部变量,那么当线程进入该方法的时候,就会将 ThreadLocal 的引用给加载到线程的栈 Stack 中

如上图所示,在线程栈 Stack 中,有两个变量,ThreadLocalRef 和 CurrentThreadRef,分别指向了声明的局部变量 ThreadLocal ,以及当前执行的线程

而 ThreadLocalMap 中的 key 是弱引用,当线程执行完该方法之后,Stack 线程栈中的 ThreadLocalRef 变量就会被弹出栈,因此 ThreadLocal 变量的强引用(ThreadLocalRef)消失了,那么 ThreadLocal 变量只有 Entry 中的 key 对他引用,并且还是弱引用,因此这个 ThreadLocal 变量会被回收掉,导致 Entry 中的 key 为 null,而 value 还指向了对 Object 的强引用,因此 value 还一直存在 ThreadLocalMap 变量中

由于 ThreadLocal 被回收了,无法通过 key 去访问到这个 value,导致这个 value 一直无法被回收, ThreadLocalMap 变量的生命周期是和当前线程的生命周期一样长的,只有在当前线程运行结束之后才会清除掉 value,因此会导致这个 value 一直停留在内存中,导致内存泄漏

当然 JDK 的开发者想到了这个问题,在使用 set get remove 的时候,会对 key 为 null 的 value 进行清理,使得程序的稳定性提升。

当然,我们要保持良好的编程习惯,在线程对于 ThreadLocal 变量使用的代码块中,在代码块的末尾调用 remove 将 value 的空间释放,防止内存泄露。

ThearLocal 内存泄漏的根源是:

由于 ThreadLocalMap 的生命周期跟 Thread 一样长,如果没有手动删除对应 key 就会导致内存泄漏

ThreadLocal 正确的使用方法:

  • 每次使用完 ThreadLocal 都调用它的 remove() 方法清除数据
  • 将 ThreadLocal 变量定义成 private static final,这样就一直存在 ThreadLocal 的强引用,也能保证任何时候都能通过 ThreadLocal 的弱引用访问到 Entry 的 value 值,进而清除掉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/630816.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java在MySQL数据报错Data truncation: Data too long for column ‘**‘ at row 1 处理

问题 在Java SpringBoot MyBatis 框架的项目中,一切正常,不过在一个接口的参数字段传入过大的数据就会报此错误: 请求常:org.springframework.dao.DataIntegrityViolationException: Error updating database.Cause:com.mysql.cj.jdbc.excep…

华为手机p70即将上市,国内手机市场或迎来新局面?

4月15日,华为官宣手机品牌全新升级,p系列品牌升级为Pura。华为P70系列手机预计将于2024年第一季度末发布,而网友也纷纷表示期待p70在拍照、性能上的全新突破。 网友们对华为P70系列的热情高涨,也印证了国内高端手机市场的潜力巨大…

【MySQL篇】mysqlpump和mysqldump参数区别总汇(第三篇,总共四篇)

☘️博主介绍☘️: ✨又是一天没白过,我是奈斯,DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&am…

NLP vs. LLMs: 理解它们之间的区别

作者:Elastic Platform Team 随着人工智能持续发展并在无数行业解决问题,技术的一个关键部分是能够无缝地桥接人类语言和机器理解之间的差距。这就是自然语言处理(NLP)和大型语言模型(LLMs)的用武之地。它们…

.Net RabbitMQ(消息队列)

文章目录 一.RabbitMQ 介绍以及工作模式1.RabbitMQ的介绍:2.RabbitMQ的工作模式: 二.RabbitMQ安装1.安装Erlang语言环境2.安装RabbitMQ 三.在.Net中使用RabbitMQ1.HelloWorld模式2.工作队列模式3.发布订阅模式4.Routing路由模式和Topics通配符模式 一.Ra…

Html面试题汇总

1. DOCTYPE(⽂档类型) 的作⽤ <!DOCTYPE>文档类型声明&#xff0c;作用就是告诉浏览器使用哪种html版本来显示网页 <!DOCTYPE html> 的作用就是让浏览器进入标准模式&#xff0c;使用最新的 HTML5 标准来解析渲染页面 它是一个文档类型声明标签&#xff0c;不是…

YoloV8改进策略:注意力改进、Neck层改进|自研全新的Mamba注意力|即插即用,简单易懂|附结构图|检测、分割、关键点均适用(独家原创,全世界首发)

摘要 无Mamba不狂欢,本文打造基于Mamba的注意力机制。全世界首发基于Mamba的注意力啊!对Mamba感兴趣的朋友一定不要错过啊! 基于Mamba的高效注意力代码和结构图 import torch import torch.nn as nn # 导入自定义的Mamba模块 from mamba_ssm import Mamba class Eff…

EPSON晶振应用到汽车电子产品上的型号有哪些?

EPSON品牌应用在汽车电子产品上的晶振.&#xff0c;当然也少不了晶振可能最熟悉的就是32.768K系列和26MHZGPS晶振用的多。 在汽车里每一个部件都应有的不一样,甚至多次使用到同一尺寸,不同频率的晶振.爱普生品牌晶振型号就有几百种,很容易混淆,要想记住汽车里所应用到的不是件…

Debian12 中重新安装MSSQL 并指定服务器、数据库、数据表字段的字符排序规则和默认语言等参数

在 Linux 上配置 SQL Server 设置 - SQL Server | Microsoft Learn 零、查看sql server 服务器支持的字符排序规则 SELECT Name from sys.fn_helpcollations() where name Like Chinese% go------ Chinese_PRC_CI_AI Chinese_PRC_CI_AI_WS Chinese_PRC_CI_AI_KS Chinese_PRC_…

第十四届蓝桥杯Java B组省赛部分题解

1、阶乘求和 解析 当n足够大时,阶乘和的后几个数字会趋于稳定,即相等,所以只需要多试几次,找到后9位相同部分。 答案 420940313代码实现 package contest;import java.util.*;public class Main

数据库--Sqlite3

1、思维导图 2sqlite3在linux中是实现数据的增删&#xff0c;改 #include<myhead.h> int main(int argc, const char *argv[]) { //1、定义一个数据库句柄指针 sqlite3* ppDb NULL; //2、创建或打开数据库 if(sqlite3_open("./mydb…

CSS导读 (CSS的三大特性 上)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 五、CSS的三大特性 5.1 层叠性 5.2 继承性 5.2.1 行高的继承 5.3 优先级 小练习 五、CSS的三大特性 …