24面--整理内容--待补充

自我介绍
大概学校里什么专业,班级部门什么职务,拿过什么奖,有什么证,有几段实习经验干了多久,我会什么技术栈…spring boot redis mysql

一般会问到你为什么从上一家公司离开,理由是什么
为了职业成长和发展,寻找更多学习和发展的机会,寻找与你的职业目标更加吻合的机会,我意识到我想要朝着一个更具体的方向发展我的职业生涯,这个方向是我在上个岗位中无法实现的。

项目上 分布式存储系统

1.介绍一下这个系统

分布式存储系统是一个文件存储系统,由一个自定义注册中心、一个客户端和多个文件存储服务器组成,其中注册中心实现了服务注册和心跳检测的功能。主要有大文件分片上传、小文件不分片上传、文件下载等功能。
可以介绍一下和单机存储的服务器的区别、有什么优势
处理能力不同:单机系统通常只有一台计算机,处理能力有限;而分布式系统可以利用多台计算机的处理能力,提高处理效率。
数据传输效率不同:在分布式系统中,由于存在网络通信等因素,数据传输效率通常较低,会增加系统的延迟和开销。
资源占用不同:分布式系统通常需要占用更多的资源,如存储空间、带宽、处理器等,因此需要更高的成本来支持分布式系统的运行。
故障处理效率不同:在分布式系统中,由于存在多个节点和网络通信等因素,故障处理效率较低,需要更多的时间和资源来进行故障排查和修复。
数据一致性效率不同:在分布式系统中,由于数据存储在多个节点上,数据一致性的维护需要更多的时间和资源,因此会影响系统的效率。

讲一下写的过程中遇到的两个问题以及解决思路

第一个问题:文件过大上传速度超时的问题
解决方法:把他拆成小分片然后一起上传
第二个问题:文件很大时在落盘的时候速度很慢
使用completableFuture 多线程上传,多线程落盘的过程中,可能会有几个线程抛出异常,导致文件上传不完整,使用completableFuture.allof和anyof方法保证所有要么线程的任务都执行完,要么都不执行

GFS(Google File System )中心化思想

分布式存储技术有:Ceph、GFS、HDFS、Swift、Lustre
中心化思想是因为这个系统的文件元数据都统一存放到meta了,所有的文件存储必须依赖于meta,meta成了整个系统唯一的核心,在这种情况下,这个系统可以称为是一个中心化的系统;反之,有的实现是将元数据直接分散存储到文件服务器中,避免了中心化存储可能带来的一些问题,比如meta如果挂了,整个系统直接瘫痪这种情况出现.

Client: 与应用直接交互的服务,提供文件操作的相关接口
Meta: 维持文件元数据,统一管理 chunk 信息
chunk-server: 实际文件存储服务器

Binlog如何实现Mysql主从复制

步骤一:主库开启binlog日志,开启后主库的更新事件(update、insert、delete)被写到binlog
步骤二:从库发起连接,连接到主库
步骤三:此时主库创建一个binlog dump thread线程,把binlog的内容发送到从库
步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
步骤五:还会创建一个SQL线程,从relay log里面读取内容,将更新内容写入到slave的db

Nginx如何配置,配置反向代理,要配置哪些东西

第一步
在nginx.conf配置文件中找到http这个标签块,在http标签块中添加如下代码:

upstream backend {
	ip_hash;#定义的使用那个负载均衡策略
    server 127.0.0.1:8080;#这里放置要被代理的服务器域名或ip加端口,当然也可以不加
}

这个upstream是为了定义反向代理的后端服务器列表backend是名称,upstream还可以指定负载均衡算法,使用ip_hash算法对后端服务器进行负载均衡,即根据客户端IP地址的hash值来选择后端服务器。这样可以保证同一个客户端的请求始终由同一个后端服务器处理,从而避免数据不一致的问题。

第二步
找到一个server,在server内部的location规则区域下写入proxy_pass http://backend;这端代码,这里就是进行代理的操作,当有用户去访问你服务器的时就会执行你代理的这个域名地址了。proxy_pass指令使用http://backend作为反向代理的后端服务器,这里的backend就是之前定义的upstream名字。

http {
  upstream backend {
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    server_name localhost;

    location / {
      proxy_pass http://backend;
    }
  }
}

Redis 存储客户端请求头中的 token,如何实现登录鉴权

登录鉴权 :服务端登录成功后会向客户端返回一个token(uuid字符串为key,userId为value的键值对)给客户端,并存储在redis中,客户端每次发起请求都携带token,后端的过滤器会对所有请求进行拦截,然后去redis中寻找看有没有这个token,有的话就刷新redis中token的剩余存活时间。
退出登录就直接删除redis中对应的token。

为什么用ReentrantReadWriteLock 优势在哪 这个锁有什么用

解决读写冲突问题,如果你在写文件得过程中,有人正好在读文件,ReentrantReadWriteLock可以让读得时候,锁住,让写得线程在后面排队,写得时候让所有线程都在后面排队。
ReentrantLock虽然可以灵活地实现线程安全,但是他是一种完全互斥锁,即某一时刻永远只允许一个线程访问共享资源,不管是读数据的线程还是写数据的线程。这导致的结果就是,效率低下。
ReentrantReadWriteLock中维护了读锁和写锁。允许线程同时读取共享资源;但是如果有一个线程是写数据,那么其他线程就不能去读写该资源。即会出现三种情况:读读共享,写写互斥,读写互斥。

心跳机制

为了确保注册中心中的服务状态是实时的,我实现了心跳检测机制。每个服务会定期通过heartbeat方法向注册中心发送心跳信息,表明自己仍然存活。注册中心在收到心跳信息后,会更新对应服务的preTimeStamp字段,并设置alive字段为true。如果注册中心在一段时间内没有收到某个服务的心跳信息,它会认为该服务已经下线,并将其从SERVER_MAP中移除或标记为不可用。
为了定期检查服务的存活状态,我使用了Spring框架提供的@Scheduled注解来创建一个定时任务。该定时任务每隔一定时间(在您的代码中为每10秒)执行一次checkIsAlive方法,检查所有服务的存活状态。如果某个服务的存活时间超过了预设的阈值(在您的代码中为30秒),则将其标记为不可用;如果存活时间小于60秒,则保持其状态不变。通过这种方式,注册中心可以实时地反映服务的存活状态,为其他服务或客户端提供准确的服务发现功能。

其余部分

.java和.class文件区别

.java文件,就是当前编写的代码文件
.class文件,就是编译过后的文件

javac用来编译java文件,java用来执行。
1.javac命令用来编译java文件,例如编写一个Test.java文件,使用javac Test.java可以执行编译操作,将生成一个Test.class文件。

2.java命令可以执行生成的class文件,使用java Test可以执行编写的代码。

java的异常类型分为几种

Exception的直接子类:编译时异常

RuntimeException:运行时异常

equals和==的区别

== 的作用:
  基本类型:比较值是否相等
  引用类型:比较内存地址值是否相等

equals 的作用:
  引用类型:默认情况下,比较内存地址值是否相等。可以按照需求逻辑,重写对象的equals方法

HashMap的到底是有序还是无序

HashMap不保证插入顺序,但是循环遍历时,输出顺序是不会改变的。

HashMap的数据结构:数组+单链表

浅克隆和深克隆区别

浅克隆: 被Clone的对象的所有变量都含有原来对象相同的值,而引用变量还是原来对用的引用【拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。】
深克隆: 被克隆对象的所有变量都含有原来的对象相同的值,引用变量也重新复制了一份【不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象】

object类中的常用方法:

1、 getClass():获取类的class对象。
2、 hashCode:获取对象的hashCode值
3、 equals():比较对象是否相等,比较的是值和地址,子类可重写以自定义。
4、 clone():克隆方法。
5、 toString():如果没有重写,应用对象将打印的是地址值。
6、 notify():随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
7、 notifyall():解除所有那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
8、 wait():导致线程进入等待状态,直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
9、 finalize():对象回收时调用

java的序列化

在 Java 中,只要一个类实现了 java.io.Serializable 接口,它就可以被序列化(枚举类也可以被序列化)。

强、软、弱、虚引用的区别

在这里插入图片描述

左连接和右连接的区别

**左连接和右连接的主要区别在于它们在连接两个表时处理NULL值的方式。**左连接(Left Join)总是以左表(驱动表)为基础,即使右表中没有匹配的记录,左连接也会返回左表中的所有记录,并用NULL值填充右表对应的字段。右连接(Right Join)则总是以右表为基础,如果左表中没有匹配的记录,右连接会返回右表中的所有记录,同样使用NULL值填充左表对应的字段。

  • 左连接:
    • 返回左表中的所有记录。
    • 如果右表中没有匹配的记录,则用NULL值填充右表对应的字段。
    • 以左表为基准,保留左表的所有记录。
  • 右连接:
    • 返回右表中的所有记录。
    • 如果左表中没有匹配的记录,则用NULL值填充左表对应的字段。
    • 以右表为基准,保留右表的所有记录。

内连接(Inner Join)则是只返回两个表中都存在匹配的记录,不满足连接条件的记录将被忽略。全外连接(Full Outer Join)则是左外连接和右外连接的组合,它返回左右表中所有的记录,以及左右表中连接字段相等的记录。

索引的作用

在这里插入图片描述

乐观锁和悲观锁

一、基本概念
乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。
悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
二、实现方式

悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(如Java的synchronized关键字),也可以是对数据加锁(如MySQL中的排它锁)。

乐观锁的实现方式主要有两种:CAS机制和版本号机制

不排序如何找到数组第二大的数

1.找到最大的值,然后remove/delete掉,再找一次

2.第二种方法,用两个变量,将数组第一个数字和第二个数字保存,然后分别和第三位数以后的值对比

给定一个数组找出第一个不重复的数字

方法1:双重循环,外部循环逐个选取元素,内部循环检查元素是否存在多次。

方法2:使用哈希表来存储每个数字出现的次数

介绍一下jvm

JVM是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。
Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。

JVM原理
(1)jvm是java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
(2)java编译器只要面向jvm,生成jvm能理解的字节码文件。java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码,通过特定平台运行。

在这里插入图片描述
服务注册 心跳检测,用了cocurrenthashmap 保证线程安全,springSchedule定时任务(等待完善话术)

服务注册与发现
在注册中心的设计中,我实现了服务的注册和发现功能。当服务启动时,它会通过register方法将自己的信息注册到注册中心。注册中心使用了一个ConcurrentHashMap(在您的代码中为SERVER_MAP)来存储服务信息,保证了在多线程环境下的线程安全性。每个服务的信息都封装在ServerInfo对象中,而ServerInfoDTO则作为数据传输对象,在注册时传递服务的基本信息。
服务发现时,其他服务或客户端可以通过查询SERVER_MAP来获取特定服务的信息列表。由于ConcurrentHashMap支持高效的并发访问,因此服务发现操作也是线程安全的。
心跳检测机制
为了确保注册中心中的服务状态是实时的,我实现了心跳检测机制。每个服务会定期通过heartbeat方法向注册中心发送心跳信息,表明自己仍然存活。注册中心在收到心跳信息后,会更新对应服务的preTimeStamp字段,并设置alive字段为true。如果注册中心在一段时间内没有收到某个服务的心跳信息,它会认为该服务已经下线,并将其从SERVER_MAP中移除或标记为不可用。
数据结构的线程安全性
在选择数据结构时,我考虑到了线程安全性的要求。由于注册中心需要支持多个服务的同时注册和心跳检测,因此我选择了ConcurrentHashMap来存储服务信息。ConcurrentHashMap是Java提供的一种线程安全的哈希表实现,它支持高并发的读写操作,并且在多线程环境下不需要额外的同步措施。
定时任务的处理
为了定期检查服务的存活状态,我使用了Spring框架提供的@Scheduled注解来创建一个定时任务。该定时任务每隔一定时间(在您的代码中为每10秒)执行一次checkIsAlive方法,检查所有服务的存活状态。如果某个服务的存活时间超过了预设的阈值(在您的代码中为30秒),则将其标记为不可用;如果存活时间小于60秒,则保持其状态不变。通过这种方式,注册中心可以实时地反映服务的存活状态,为其他服务或客户端提供准确的服务发现功能。

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值