快手 | 后端Java实习生 | 一面

news2025/4/15 14:56:33

目录

    • 1.Redis缓存和MySQL数据一致性如何保证?
    • 2.你使用缓存,在高并发的情况下,如果多个缓存同时过期了怎么办?
    • 3.消息队列积压了怎么办?
    • 4.jdk1.8之后Java内存模型分别哪几个部分?每个部分用一句话概括一下?
    • 5.哪几个部分是线程私有的?哪几个是线程共有的?
    • 6.哪些部分会造成OOM问题?
    • 7.讲一下Java异常的体系结构?
    • 8.项目中有自定义异常吗?
    • 9.线程调用start()之后再次调用start()会抛异常还是没反应吗?
    • 10.说一下TCP三次握手?
    • 11.线程和进程的区别?
    • 12.常用的进程的通信方式有哪些?

1.Redis缓存和MySQL数据一致性如何保证?

如果不熟悉可以看这篇
深入理解redis_缓存双写一致性之更新策略探讨

考点:redis和数据库双写一致性问题
跟着这三点去答

先更新数据库,再更新缓存
先删除缓存,再更新数据库
先更新数据库,再删除缓存

先更新数据库,再更新缓存

  • 先更新mysql的某商品的库存,当前商品的库存是100,更新为99个。
    先更新mysql修改为99成功,然后更新redis。
    此时假设异常出现,更新redis失败了,这导致mysql里面的库存是99而redis里面的还是100 。
    上述发生,会让数据库里面和缓存redis里面数据不一致,读到脏数据
  • 举个例子:如果数据库1小时内更新了1000次,那么缓存也要更新1000次,但是这个缓存可能在1小时内只被读取了1次,那么这1000次的更新有必要吗?
    反过来,如果是删除的话,就算数据库更新了1000次,那么也只是做了1次缓存删除,只有当缓存真正被读取的时候才去数据库加载。

先删除缓存,再更新数据库
如果数据库更新失败,导致B线程请求再次访问缓存时,发现redis里面没数据,缓存缺失,再去读取mysql时,从数据库中读取到旧值
解决方式:采用延时双删策略
在这里插入图片描述
在这里插入图片描述
先更新数据库,再删除缓存
假如缓存删除失败或者来不及,导致请求再次访问redis时缓存命中,读取到的是缓存旧值。
解决方案:canal

方案2和方案3用那个?
个人建议是,优先使用先更新数据库,再删除缓存的方案。理由如下:
1 先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来压力,严重导致打满mysql。
2 如果业务应用中读取数据库和写缓存的时间不好估算,那么,延迟双删中的等待时间就不好设置。

2.你使用缓存,在高并发的情况下,如果多个缓存同时过期了怎么办?

大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去
简单说就是热点key突然失效了,暴打mysql
在这里插入图片描述

方案1:对于访问频繁的热点key,干脆就不设置过期时间
互斥独占锁防止击穿
方案2:互斥独占锁防止击穿
多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。
在这里插入图片描述
方案3:定时轮询,互斥更新,差异失效时间
举一个案例例子
QPS上1000后导致可怕的缓存击穿
在这里插入图片描述
在这里插入图片描述
解决方法
定时轮询,互斥更新,差异失效时间
在这里插入图片描述
相当于B穿了一件防弹衣
在这里插入图片描述
我们先缓存B,然后在缓存A,设置B的过期时间要比A的长

在这里插入图片描述
我们先查询A,如果A为空,我们再查询B
在这里插入图片描述

3.消息队列积压了怎么办?

当 RabbitMQ 消息队列积压时,可以采取以下措施:

  1. 增加消费者:增加消费者可以加快消息的消费速度从而减少队列中的积情况。

  2. 增加队列容量:增加队列容量可以使队列能够存储更多的消息,从而减少消息被丢弃的情况。

  3. 优化消费者代码:优化消费者代码可以使消费者快地处理消息,从而减少队列中的压情况。

  4. 优化生产者代码:优化生产者代码可以使生产更快地发送消息,从而减少队列中的积压情况。

  5. 使用 TTL:使用 TTL(Time To Live)可以设置消息的过期时间,从而减少队列中的积压情况。

  6. 使用死信队列:使用信队列可以将无法被消费的消息转移到另一个队列中,从而减少队列中的积压情况。

4.jdk1.8之后Java内存模型分别哪几个部分?每个部分用一句话概括一下?

在 JDK1.8 之后,Java 内存模型分为以下几个部分:

  1. 堆:用于存储对象实例,是 Java 程序中最大的一块存区域。

  2. 虚拟机栈:用于存储方法调用时的局部变量、方法参数和返回值等数据,是线程私有的。

  3. 方法区:用于存储类的信息、常量、静态变量、即时编译器编译后的代码等数据,是线程共享的。

  4. 本地方法栈:与虚拟机栈类似,不过只能执行native修饰的方法。

  5. 程序计数器:用于记录线程执行的位置,是线程私有的。

5.哪几个部分是线程私有的?哪几个是线程共有的?

共有:堆,方法区
私有:栈,本地方法栈,虚拟机栈

6.哪些部分会造成OOM问题?

除了程序计数器不会发生OOM,其他都要发生OOM
堆内存
如果在堆中没有内存完成对象实例的分配,并且堆无法再扩展时,将抛出OutOfMemoryError异常,抛出的错误信息是“java.lang.OutOfMemoryError:Java heap space”。
当前主流的JVM可以通过-Xmx和-Xms来控制堆内存的大小,发生堆上OOM的可能是存在内存泄露,也可能是堆大小分配不合理。

虚拟机栈和本地方法栈
这两个区域的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务,在内存分配异常上是相同的。
在JVM规范中,对Java虚拟机栈规定了两种异常:
a. 如果线程请求的栈大于所分配的栈大小,则抛出StackOverFlowError错误,比如进行了一个不会停止的递归调用;
b. 如果虚拟机栈是可以动态拓展的,拓展时无法申请到足够的内存,则抛出OutOfMemoryError错误。

方法区
方法区用于存储的信息、常量、静态变量、即时编译器编译后的代码等数据。如果程序中使用了大量的类或者字符串常量,就会导致方法区溢出。

7.讲一下Java异常的体系结构?

在这里插入图片描述

8.项目中有自定义异常吗?

在service_utils中创建com.donglin.yygh.common.handler包,建统一异常处理类GlobalExceptionHandler.java:

import com.donglin.yygh.common.result.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//凡是由@ControllerAdvice 标记的类都表示全局异常类
@RestControllerAdvice  //@ControllerAdvice+@RequestBody=@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)  //粒度有点大
    public R handleException(Exception ex){
        ex.printStackTrace();
        return R.error().message(ex.getMessage());
    }
}

JAVA异常getMessage(),printStackTrace()方法的区别https://donglin.blog.csdn.net/article/details/125471865
添加异常处理方法
GlobalExceptionHandler.java中添加

    @ExceptionHandler(value = SQLException.class)  
    public R handleException(SQLException ex){
        ex.printStackTrace();
        return R.error().message("Sql异常");
    }

    @ExceptionHandler(value = ArithmeticException.class)  
    public R handleException(ArithmeticException ex){
        ex.printStackTrace();
        return R.error().message("数学异常");
    }

9.线程调用start()之后再次调用start()会抛异常还是没反应吗?

抛出异常

如果不熟悉可以看这篇
Thread启动线程的start方法能执行多次吗?

start()方法源码:

public synchronized void start() {  
        // 如果线程不是"NEW状态",则抛出异常!  
        if (threadStatus != 0)  
            throw new IllegalThreadStateException();  
        // 将线程添加到ThreadGroup中  
        group.add(this);  
        boolean started = false;  
        try {  
            // 通过start0()启动线程,新线程会调用run()方法  
            start0();  
            // 设置started标记=true  
            started = true;  
        } finally {  
            try {  
                if (!started) {  
                    group.threadStartFailed(this);  
                }  
            } catch (Throwable ignore) {  
            }  
        }  
    }

run方法源码:

public void run() {  
    if (target != null) {  
        target.run();  
    }  
}

10.说一下TCP三次握手?

在这里插入图片描述
三次握手是建立连接的过程,当客户端向服务端发起连接时,会先发一包连接请求数据,过去询问一下,能否与你建立连接,这包数据我们称之为SYN包。如果对端同意连接,则回复一包SYN+ACK包,客户端收到之后回复一包ACK包连接建立。
因为这个过程中互相发送了三包数据,所以称之为三次握手。
Q:为什么要三次握手,而不是两次握手,服务端回复完SYN+ACK包之后就建立连接
A:这是为了防止因为已失效的请求报文突然又传到服务器引起错误。解决网络信道不可靠的问题
如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,服务器端是不知道客户端有没有接收到服务器端返回的信息的。服务端就认为这个连接是可用的,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。
这样一来,就会有很多无效的连接端口白白地开着,导致资源的浪费。
在这里插入图片描述
还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。
在这里插入图片描述
Q:为什么不是四次握手?
A:因为通信不可能100%可靠,而上面的三次握手已经做好了通信的准备工作,再四次握手,并不能显著提高可靠性,而且也没有必要。

11.线程和进程的区别?

进程
是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是系统进行『资源分配和调度』的一个独立单位。
线程
进行运算调度的最小单位,其实是进程中的一个执行任务(控制单元),负责当前进程中程序的执行
两者之间的区别

  • 「本质区别」:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
  • 「在开销方面」:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小
  • 「所处环境」:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
  • 「内存分配方面」:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源
  • 「包含关系」:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程

12.常用的进程的通信方式有哪些?

如果不熟悉可以看这篇
进程的通信方式有哪些?

  • 管道
  • 消息队列
  • 共享内存
  • 信号量
  • 信号
  • 套接字

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GaussDB云数据库SQL应用系列-定时任务管理

前言 GaussDB数据库定时任务主要可以用于实现定期的备份、统计信息采集、数据汇总、数据清理与优化等,它是指在指定的时间间隔内自动执行一次或多次SQL语句的程序。 一、GaussDB数据库定时任务介绍 GaussDB数据库兼容Oracle定时任务功能主要通过DBE_TASK高级功能…

POSTGRESQL PSQL 命令中如何使用变量带入查询和函数

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

chatgpt赋能python:Python如何删除已经写好的代码?

Python如何删除已经写好的代码? 在编程中,大多数时候写出来的代码都是需要保留的。但是,随着项目的发展和需求的变化,有些代码可能就没有用了。这时,我们需要删除这些无用的代码,以保持程序的简洁性和效率…

Nginx、location匹配、Rewrite重写模块

Nginx、location匹配、Rewrite重写模块 一、常用的Nginx正则表达式二、location匹配概述1、location大致可以分为三类2、location常用的匹配规则3、location 优先级4、location 示例说明5、实际网站使用中,至少有三个匹配规则定义 三、rewrite重写1、rewrite 跳转场…

记录--JavaScript 中有趣的 9 个常用编码套路

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1️⃣ set对象:数组快速去重 常规情况下,我们想要筛选唯一值,一般会想到遍历数组然后逐个对比,或者使用成熟的库比如lodash之类的。 不过,ES…

Spark RDD分区

文章目录 一、RRD分区(一)RDD分区概念(二)RDD分区作用 二、RDD分区数量(一)RDD分区原则(二)影响分区的因素(三)使用parallelize()方法创建RDD时的分区数量1、…

软件测试之环境搭建—苏汽web系统测试环境搭建

一、搭建环境的准备工作 1、安装好RedHat,输入用户名:root,密码:123456,右键点击桌面,打开终端输入“ifconfig”查询IP地址 2.打开xshell,点击文件,选择新建连接,在输入…

【数据分析之道-Matplotlib(七)】Matplotlib直方图

文章目录 专栏导读1、hist()基本语法2、使用 hist() 函数绘制多个数据组的直方图3、修改直方图的颜色及边框颜色4、六一儿童节为主题,使用直方图进行可视化 专栏导读 ✍ 作者简介:i阿极,CSDN Python领域新星创作者,专注于分享pyth…

POI报表的高级应用

POI报表的高级应用 掌握基于模板打印的POI报表导出理解自定义工具类的执行流程 熟练使用SXSSFWorkbook完成百万数据报表打印理解基于事件驱动的POI报表导入 模板打印 概述 自定义生成Excel报表文件还是有很多不尽如意的地方,特别是针对复杂报表头,单元格…

我们世界中的10个算法

下面的图表展示了我们日常生活中最常用的算法。它们被应用在互联网搜索引擎、社交网络、WiFi、手机甚至卫星等各个领域。 1.排序算法 排序算法用于将一组数据按照特定的顺序进行排列。它们被广泛应用于各种场景,如搜索引擎中的搜索结果排序、数据分析中的数据整理和…

转转前端周刊第六十八期

转转前端周刊 本刊意在将整理业界精华文章给大家,期望大家一起打开视野 如果你有发现一些精华文章想和更多人分享,可以点击我们的公众号名称,将文章链接和你的解读文案发给我们!我们会对内容进行筛选和审核,保留你的推…

基于TensorFlow Object Detection API实现RetinaNet目标检测网络(附源码)

文章目录 一、RetinaNet简介1. Backbone网络2. FPN网络 二、RetinaNet实现1. tf.train.CheckPoint简介2. RetinaNet的TensorFlow源码 一、RetinaNet简介 RetinaNet是作者Tsung-Yi Lin和Kaiming He于2018年发表的论文Focal Loss for Dense Object Detection中提出的网络。Retina…

运维小白必学篇之基础篇第十六集:DNS架构FTP实验

DNS架构FTP实验 目录 DNS架构FTP实验 服务端 客户端 服务端 在ftp架构了安装dns域名服务 yum -y install bind 配置主配置文件 vim /etc/named.conf listen-on port 53 { 192.168.50.1; }; allow-query { 192.168.50.0/24; }; 配置区域文件 vim /etc/named.rfc1912.zones…

深聊丨“紫东太初”大模型背后有哪些值得细读的论文(一)

原创:谭婧 没有人想等待,没有人想落伍。 新鲜论文时兴火热,成为大模型发展迅猛的标志之一,人们用“刷论文”这个游荡意味的动词替代另一个颇为严肃的动作,“读论文”。 论文被当作“教材”和“新知识”,在a…

矢量网络分析仪RS罗德与施瓦ZNB8 9KHZ至8.5GHZ德国二手

Rohde & Schwarz ZNB8网络分析仪,8.5 GHz,2 或 4 端口 ​罗德与施瓦茨 ZNB8 Rohde & Schwarz ZNB8 矢量网络分析仪具有高达 140 dB(10 Hz IF 带宽)的宽动态范围、低于 0.004 dB RMS(10 kHz IF 带宽&#xff…

React--Component组件浅析

目录 一 前言二 什么是React组件?三 二种不同 React 组件1 class类组件2 函数组件 四 组件通信方式五 组件的强化方式六 总结 一 前言 在 React 世界里,一切皆组件,我们写的 React 项目全部起源于组件。组件可以分为两类,一类是类…

驱动开发:内核扫描SSDT挂钩状态

在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于《驱动开…

【Unity-UGUI控件全面解析】| Layout自动布局组件详解

🎬【Unity-UGUI控件全面解析】| Layout自动布局组件详解一、组件介绍二、组件属性面板2.1 布局元素 (Layout Element)2.2 水平布局组 (Horizontal Layout Group)2.3 垂直布局组 (Vertical Layout Group)2.4 网格布局组 (Grid Layout Group)三、代码操作组件四、组件常用方法示…

把 AI 装进即时通讯,会发生什么?

今年以来,AIGC 技术以“天”为单位快速进化,刷足了存在感。科技公司迅速将 AI 嵌入自家的产品中,追逐 AI 带来的生产力变革,解决日益复杂的需求。从文学到音乐,从绘画到编程,无一领域不受其影响。 在这些领…

网络编程(1)

获取本网络信息相关接口 接口说明: QHostInfo类为主机信息,为主机名查找提供静态函数 QHostAddress类为主机地址类,管理IPV4或IPV6地址信息。 QNetworkInterface类为网络接口类,提供主机IP地址和网络接口的列表。 QNetworkAd…