掘金 后端 ( ) • 2024-04-19 11:12

theme: Chinese-red

SQL题

有以下4张表

图片3.png

图片4.png

图片1.png

图片2.png

请写出以下sql的查询语句

查询Score表中成绩为60或者为80的所有记录

select * from Score where Degree in (60,80)

查询Student表中学生不在C_001的所有记录

select * from Student where Class not in (‘C_001’)

查询Score表中的最底分的学生学号和课程号

select SNO,CNO from Score where Degree=(select MIN(Degree) from Score)

查询Score表中的最高分的学生学号和课程号

select SNO,CNO from Score where Degree=(select MAX(Degree) from Score)

查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录

select * from student,Score where student.Sno=Score.Sno and Score.Degree>(select Degree from Score where Cno=‘3-105’ and Sno=‘109’)

查询Student表中不姓“王”的同学记录

select * from student where Sname not like (‘王%’)

以班号和年龄从大到小的顺序查询Student表中的全部记录

select * from student order by Class desc,Sbirthday asc

查询Student表中出生年月不为空的同学记录

select * from student where Sbirthday is not null

以年龄从大到小的顺序查询Student表中的全部记录

select * from student order by Sbirthday asc

Redis 专题

Redis为什么那么快?

  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,

HashMap的优势就是查找和操作的时间复杂度都是O(1)。

  • 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的。

  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,

不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗

(Redis6.0后引入了多线程,但是为了重复利用CPU多核的优势,线程数量取决于CPU核数,

而不是每个请求开启一个新线程)。

  • 使用多路I/O复用模型,非阻塞IO。I/O多路复用就是通过一种机制,让一个进程可以监视多个描述符,

一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

常用的IO多路复用的实现有:select、poll、epoll。多路复用IO 技术最适用的是“高并发”场景。

  • 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了

VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

Redis的五大数据类型,使用场景,底层原理?

图片5.png

Redis有哪些持久化机制?它们分别是如何工作的?

图片6.png

需要注意的是,Redis还支持持久化的混合模式,即同时使用RDB和AOF持久化机制。这样可以在某种程度上兼顾RDB和AOF的优点,并根据实际需求进行配置。

选择合适的持久化机制取决于应用的要求和场景。如果对数据完整性要求较高,可以选择AOF持久化。如果对性能和快速恢复较为重要,可以选择RDB持久化。无持久化模式适用于对数据持久性要求不高但追求最高性能和响应速度的场景。

对于AOF持久化,可以根据需求配置不同的策略,如每个写操作都同步到磁盘(fsync),或根据时间或操作数来定期同步。同步频率的选择可以根据数据的重要性和系统的容忍度来平衡性能和数据安全性。

综上所述,选择适当的持久化机制需要综合考虑应用需求、性能要求和数据安全性,并进行相应的配置和调优。

Redis主从复制集群中配置哨兵能起到什么作用?

通过配置哨兵的主从复制,可以实现Redis集群的高可用性和故障转移能力,提高系统的稳定性和可靠性。

Redis 主从复制原理?

主要步骤:假设我们有一个包含一个主节点(Master)和两个从节点(Slave1和Slave2)的Redis集群。下面是Redis主从复制的原理:

1. 配置主节点(Master):我们将其中一个节点配置为主节点,它负责接收写操作并广播数据变更。

2. 配置从节点(Slave):将其他节点配置为从节点,它们复制主节点的数据并提供读服务。

3. 初始连接:从节点通过发送SYNC命令与主节点建立连接。

4. 快照同步:主节点执行BGSAVE命令生成RDB文件(持久化快照),然后将该文件发送给从节点。从节点接收并加载RDB文件,将主节点的数据进行初始化。

5. 命令传播:当主节点接收到写命令时,它会将命令发送给所有从节点。从节点按照相同的顺序执行这些写命令,以保持数据的一致性。

6. 增量复制:主节点将自己执行的写命令及其数据变更发送给从节点。从节点根据接收到的命令进行数据更新。

7. 主从节点通信:主节点和从节点之间通过心跳机制保持连接,并定期交换信息以检测状态和同步数据。

8. 故障恢复:如果主节点发生故障或宕机,从节点会自动选举出一个新的主节点,并进行重新同步。

通过主从复制,Redis实现了数据的备份和读写分离。主节点负责处理写操作,而从节点提供读服务,从而减轻了主节点的压力,并提高了系统的可用性和性能。

图片7.png

Redis是单线程还是多线程?为什么能支持访问量和高并发?

单线程。

1) 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

2) 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗

3) 使用多路I/O复用模型,非阻塞IO

你是如何理解redis是单线程,多路I/O复用?

在Redis中,单线程的含义是指Redis服务器在处理客户端请求时,使用单个线程逐个处理命令。这个单线程负责接收客户端连接、解析命令、执行命令和返回结果。因为只有一个线程在处理请求,所以不需要进行线程切换、上下文切换或锁竞争,避免了这些开销和潜在的并发问题。

Redis的多路I/O复用是指它利用操作系统提供的机制,同时监视和处理多个输入/输出通道(如网络套接字),以实现高并发的网络通信。

案例:

假设你是一个餐厅的服务员,你需要同时处理多个桌子上的点菜和结账请求。每个桌子都有不同的客人,他们需要你的服务。

在传统的方式中,你只能一次处理一个桌子的请求,即一次只能为一个桌子点菜或结账。

现在,为了提高效率,你采用了Redis多路I/O复用的方式来处理餐厅的请求。你站在一个中央服务台前,桌子上放置着多个点餐和结账设备。每个设备都连接到中央服务台的Redis服务器,并使用多路I/O复用技术进行管理。

当一个桌子需要点菜或结账时,服务员将其请求输入到相应的设备中,并将设备连接到Redis服务器。你可以同时处理多个桌子的请求,每个请求都在不同的设备上进行操作。

当一个桌子的请求处理完成后,设备会发送信号给Redis服务器,告知请求已经完成。Redis服务器收到信号后,将请求的结果返回给服务员,然后你可以继续处理其他桌子的请求。

通过这种多路I/O复用的方式,你能够高效地处理多个桌子的请求,而不需要一次只处理一个桌子。你可以同时处理多个桌子的点菜和结账,根据需要进行相应的操作。这样,你能够更快地为客人提供服务,提高了工作效率。

为什么尽管redis 是单线程的,但它仍然能够实现高性能和并发的处理能力?

这归功于以下几个因素:

1. 基于内存:Redis将数据存储在内存中,而内存的读写速度远高于磁盘和数据库的访问速度。通过避免磁盘I/O的开销,Redis能够实现非常高的吞吐量和低延迟。

2. 非阻塞I/O:Redis使用了多路I/O复用技术,如epoll、kqueue等,通过监听和处理多个网络连接,实现了非阻塞的I/O操作。这使得Redis能够同时处理多个客户端请求,支持高并发访问。

单线程优化:Redis通过优化算法和数据结构,以及在内存中进行原子操作,最大程度地利用了单线程的优势。它避免了多线程带来的线程同步和资源竞争问题,简化了代码逻辑和维护成本。

说说Redis哈希槽的概念?

Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

Redis 淘汰机制?

  1. noeviction

不进行数据淘汰,也是Redis的默认配置。这时,当缓存被写满时,再有写请求进来,Redis不再提供服务,直接返回错误。

2.volatile-random

缓存满了之后,在设置了过期时间的键值对中进行随机删除。

3.volatile-ttl

缓存满了之后,会针对设置了过期时间的键值对中,根据过期时间的先后顺序进行删除,越早过期的越先被删除。

4.volatile-lru

缓存满了之后,针对设置了过期时间的键值对,采用LRU算法进行淘汰,不熟悉LRU的可以看这篇文章。

5.volatile-lfu

缓存满了之后,针对设置了过期时间的键值对,采用LFU的算法进行淘汰。

6.allkeys-random

缓存满了之后,从所有键值对中随机选择并删除数据。

7.allkeys-lru

缓存写满之后,使用LRU算法在所有的数据中进行筛选删除。

8.allkeys-lfu

缓存满了之后,使用LRU算法在所有的数据中进行筛选删除。

在日常使用过程中,主要根据你的数据要求来配置相应的策略,这里我给你三点建议。

1. 我们优先使用allkeys-lru 策略。这样,我们就可以借助LRU算法去淘汰那些不常用的数据,把最近最常用的放在缓存中,从而提高应用的性能。如果你的数据有明显的冷热区分,建议你使用allkeys-lru策略。

2. 如果你的数据的访问频率相差不大,也没有冷热之分,直接使用allkeys-random 策略,随机选择淘汰的数据就行。

3.如果你的数据有置顶要求,比如置顶新闻等。那么我们就选择volatile-lru策略,同时不给置顶数据设置过期时间,这样一来,置顶的数据永远不会被删除,而其他设置了过期时间的数据,会更加LRU算法进行淘汰

Git专题

Git的分支管理是怎样的? 写出相关分支命令并做出解释

Git的分支管理是非常灵活的,每个分支可以独立开展工作,不同分支之间的内容可以合并。

创建分支:通过命令git branch 可以创建一个新的分支,分支名可以自定义。

切换分支:通过命令git checkout 可以切换到指定的分支,Git会自动将工作区的文件更新到指定分支的最新提交状态。

合并分支:通过命令git merge 可以将指定分支的内容合并到当前分支,Git会尝试自动合并变化,如果有冲突则需要手动解决。

删除分支:通过命令git branch -d 可以删除指定的分支。

查看分支:通过命令git branch可以查看所有分支,当前分支会以特殊符号标识。

Git中的HEAD是什么? 谈谈你对HEAD的理解

HEAD是Git中的一个特殊指针,用来指向当前分支的最新提交。HEAD的指向可以通过切换分支或者执行提交操作来改变。 Git切换版本,底层其实是移动的HEAD指针。

Git中的暂存区(stage/index)是什么?

暂存区是Git中的一个重要概念,它是用来存放待提交的文件 的区域。当我们修改了工作区的文件后,可以通过命令git add 将修改的文件添加到暂存区,然后通过命令git commit将暂存区的内容提交到当前分支。

Git中如何撤销操作?你知道的有哪些?

撤销修改:通过命令git checkout -- 可以撤销对工作区文件的修改,恢复到最近一次提交的状态。

撤销暂存:通过命令git reset HEAD 可以将暂存区的修改撤销,重新放回到工作区。

撤销提交:通过命令git revert 可以创建一个新的提交,将指定提交的修改撤销。

Git中如何解决合并冲突?

合并冲突是在将分支内容合并时可能遇到的问题,可以通过以下步骤解决:

执行合并操作:通过命令git merge 将指定分支的内容合并到当前分支。 例如,git merge feature将会将feature分支合并到当前分支。

Git无法自动解决冲突时,会提示合并冲突,并在冲突文件中标记出冲突的部分。

手动解决冲突:打开冲突文件,根据标记修改文件内容,解决冲突。

解决冲突后,通过命令git add 将冲突文件标记为已解决。

最后,执行命令git commit完成合并提交。

什么是Git? Git的工作原理是什么?

Git是一个分布式版本控制系统,用于跟踪文件的更改并协调多人协作开发。

Git将代码仓库视为一个存储所有文件历史记录的快照数据库,每次提交会创建一个新的快照,并记录一个指向该快照的指针。Git使用哈希算法来生成每个提交的唯一标识。Git还使用分支来支持并行开发,每个分支都是指向提交的指针。

写出你所知道的Git的相关命令操作并做出解释(写出五个以上)

git init

作用:将当前目录初始化为一个Git仓库。

解释:通过执行该命令,Git会在当前目录创建一个新的空的Git仓库,用于跟踪管理项目的版本。

git clone [url]:

作用:从远程仓库克隆代码到本地。

解释:该命令用于将远程仓库中的代码完整地复制到本地,创建一个本地的Git仓库副本,并与远程仓库保持同步。

git add [文件/目录]:

作用:将文件添加到Git的暂存区。

解释:执行该命令后,Git会将指定的文件或目录添加到暂存区,以便在后续的提交中包含它们。

git commit -m "提交信息":

作用:提交暂存区中的文件到本地仓库。

解释:该命令用于将暂存区中的文件提交到本地仓库,同时可以附加一条提交信息,用于描述本次提交的内容。

git push:

作用:将本地仓库的代码推送到远程仓库。

解释:执行该命令后,Git会将本地仓库的代码推送到与之关联的远程仓库,以使得远程仓库与本地仓库保持同步。

git pull:

作用:从远程仓库拉取最新的代码到本地。

解释:该命令用于从与之关联的远程仓库拉取最新的代码,以使得本地仓库与远程仓库保持同步。

git branch:

作用:列出所有分支。

解释:执行该命令后,Git会返回当前仓库中存在的所有分支列表,并且会高亮显示当前所在的分支。

git checkout [分支名]:

作用:切换到指定的分支。

解释:该命令用于从当前分支切换到指定的分支,以便开始在该分支上进行开发或其他操作。

git merge[分支名]:

作用:合并指定分支到当前分支。

解释:执行该命令后,Git会将指定分支的代码合并到当前分支中,以便将两个分支的修改内容合并在一起。

git log:

作用:显示提交日志。

解释:执行该命令后,Git会返回当前分支的所有提交记录,包括每个提交的作者、日期、提交信息等详细信息。

Spring Boot专题

Spring Boot 特性有哪些

快速创建独立 Spring 应用

SSM:导包、写配置、启动运行

  • 直接嵌入Tomcat、Jetty or Undertow(无需部署 war 包)【Servlet容器】

  • linux  java tomcat mysql: war 放到 tomcat 的 webapps下

- jar: java环境;  java -jar

  • 重点:提供可选的starter,简化应用整合

  • 场景启动器(starter):web、json、邮件、oss(对象存储)、异步、定时任务、缓存...

- 导包一堆,控制好版本。

- 为每一种场景准备了一个依赖; web-starter。mybatis-starter

  • 重点:按需自动配置 Spring 以及 第三方库

    • 如果这些场景我要使用(生效)。这个场景的所有配置都会自动配置好。

- 约定大于配置:每个场景都有很多默认配置。

- 自定义:配置文件中修改几项就可以

  • 提供生产级特性:如 监控指标、健康检查、外部化配置等

  • 监控指标、健康检查(k8s)、外部化配置

  • 无代码生成、无xml

你如何理解 Spring Boot 中的 Starters?

Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。

Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。具体请看这篇文章《Spring Boot Starters启动器》。

Spring Boot 自动配置原理是什么?

1、导入starter,就会导入autoconfigure包。

2、autoconfigure 包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定的所有启动要加载的自动配置类

3、@EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来。xxxAutoConfiguration 是有条件注解进行按需加载

4、xxxAutoConfiguration给容器中导入一堆组件,组件都是从 xxxProperties中提取属性值

5、xxxProperties又是和配置文件进行了绑定

效果:导入starter、修改配置文件,就能修改底层行为。

Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:

@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。

@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,

如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

@ComponentScan:Spring组件扫描。

Linux专题

写出Linux根目录下的6个常用目录及其作用

/bin 二进制可执行命令。该目录下存放着普通用户的命令

/dev 系统的设备文件,即设备的驱动程序

/home 存放用户文件的主目录,用户数据

/lib 存放着和系统运行相关的库文件

/mnt 存放临时的映射文件,通常是一些用来安装其他设备的子目录

/boot 存放启动linux的核心文件

/media 存放着可移除的设备,比如软盘,光盘

/proc 存放着用户与内核的交互信息

/sbin 系统的管理命令,这里存放的是系统管理员使用的程序

/srv 系统启动服务时可以访问的数据库目录

/tmp 临时文件,重启后自动清空

/var 存放系统产生的经常变化的文件

/etc 系统所有的配置文件都在这个目录中 (添加环境变量)

/opt (option : 自由选择)主要给源码安装软件时选择的安装目录位置

/root 超级用户的目录

/selinux 主要用来加固操作系统,提高系统的安全性

/sys 管理设备文件

/usr 最大的目录,存放着应用程序和文件

/lost-found 这个目录平时是空的,当系统非正常关机而留下的“无家可归”的文件便会储存

写出Linux常用命令(不少于5个)

一、服务类命令

(1)systemctl start 服务名 - 开启服务

(2)systemctl stop 服务名 - 关闭服务

(3)systemctl restart 服务名 - 重启服务

(4)systemctl status 服务名 - 查看服务

二、文件目录类指令

(1)pwd - 显示当前目录的绝对路径

(2)ls - 显示当前路径下的文件和目录

(3)cd - 切换至指定目录

(4)mkdir - 创建目录

(5)rmdir - 删除目录(空目录)

(6)touch - 创建空文件

(7)cp - 拷贝文件或目录到指定文件或目录

(8)rm - 删除文件或目录

(9)mv - 移动文件与目录或重命名

(10)cat - 查看文件内容

(11)more - 文本过滤器

(12)less - 分屏查看文件内容

(13)echo - 输出内容到控制台

(14)head - 显示文件开头部分

(15)tail - 显示文件尾部的部分

(16)> / >> - 输出重定向/追加

(17)ln - 软链接

(18)history - 查看执行过的的历史命令

三、搜索查找类指令

(1)find - 查找文件

(2)locate - 定位文件路径

(3)which - 定位指令路径

(4)grep - 过滤查找

四、压缩解压类指令

(1)gzip - 压缩文件

(2)gunzip - 解压文件

(3)zip - 压缩文件或目录

(4)unzip - 解压文件或目录

(5)tar - 打包

VMWare三种工作模式

  • bridged(桥接模式):VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。需要手工为虚拟系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信。

  • NAT(网络地址转换模式):让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。虚拟系统无法和本局域网中的其他真实主机进行通讯。

  • host-only(主机模式):所有的虚拟系统是可以相互通信的,但虚拟系统和真实的网络是被隔离开的。虚拟系统和宿主机器系统是可以相互通信的。如果想利用VMWare创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可选择host-only模式。

图片8.png