我简历面试题

序言:自我介绍

各位面试官你们好,我叫王建,来自于东南大学计算机科学与工程学院,专业读的是人工智能。目前也是担任人工智能班级的团支书一职,平时的话兴趣爱好就喜欢健身、打打球。我是一个喜欢去主动学习的人,善于和别人合作完成任务,敢于挑战困难问题,对于不懂的知识追根究底,同时也可以在短期内适应对新知识的学习。

一、Java基础

1、可以同时存在两个类名完全相同的类吗?

答:Java中是可以存在两个类名完全相同的类的,但是它们必须在不同的包中。如果在同一个包中,就会出现编译错误。

2、Java的锁了解吗?

答:Java中的锁有很多种,比如synchronized、Lock、ReadWriteLock等。其中synchronized是Java中最基本的锁机制,它是一种悲观锁,即当一个线程获得了锁之后,其他线程就必须等待这个线程释放锁之后才能继续执行。而Lock和ReadWriteLock则是Java中比较高级的锁机制,它们可以实现更加灵活的锁操作。

3、类加载的过程

答:Java虚拟机在运行时会动态加载类,这个过程被称为类加载。类加载过程分为三个阶段:加载、连接和初始化。其中加载阶段主要是将.class文件读入内存,并生成对应的Class对象;连接阶段主要是进行验证、准备和解析操作;初始化阶段则是执行类构造器方法<clinit>()的过程。

4、泛型擦除,泛型中具体的类别信息可以获取吗

答:Java中的泛型是使用擦除实现的,这意味着当你在使用泛型的时候,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String> 和List<Integer>在运行时实际上是相同的类型。这两种类型都被擦除成他们的"原生类型",即List。但是你可以通过反射来获取泛型信息。

5、类重载和重写的区别

重载是指在同一个类中定义多个方法,它们的方法名相同,但参数列表不同。而重写是指子类重新定义了父类中已有的方法,方法名、参数列表和返回值类型都相同。

这两个概念的区别主要有以下几点:

  • 重载发生在本类,重写发生在父类与子类之间。
  • 重载的方法名必须相同,重写的方法名相同且返回值类型必须相同。
  • 重载的参数列表不同,重写的参数列表必须相同

6、JVM垃圾回收机制

JVM的垃圾回收机制是指在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行。垃圾回收的过程主要包括以下几个步骤:

  • 判定垃圾回收的对象。回收垃圾之前,首先要找到需要被当作垃圾而回收的对象。JVM分为五个区域——程序计数器、虚拟机栈、本地方法栈、堆、方法区。我们知道程序计数器与栈均是线程私有的,其生命周期取决于线程的生命周期。

  • 标记存活对象。可达性算法是为了标记存活的对象,知道哪些是可回收对象。

  • 垃圾回收算法进行回收。见的几种垃圾回收算法有标记清除、复制算法、标记整理和分代收集算法。

  • 压缩内存空间。在进行完垃圾回收之后,可能会出现内存空间不连续的情况,需要进行内存压缩。

7、HashMap

(1)hashmap的实现

HashMap是一种基于哈希表的Map接口实现,主要是基于数组和链表来实现的。HashMap中通过key的hashCode来计算 hash 值,由这个hash值计算在数组中的位置,将新插入的元素放到数组的这个位置,如果新插入的元素的hash值跟这个位置上已有元素的hash值相同,就会出现hash冲突,这时候,就在该位置通过链表来插入新的元素。

(2)hashmap中负载因子的作用和意义

HashMap中的负载因子是指哈希表中元素的数量与哈希表长度的比值。当哈希表中元素的数量超过了负载因子与哈希表长度的乘积时,就需要对哈希表进行扩容,以保证哈希表的性能。负载因子越大,哈希冲突的概率就越大,因此,负载因子不能太大。HashMap默认的负载因子是0.75,这是一个比较合理的值。

HashMap会在元素数量超过负载因子与哈希表长度的乘积时进行扩容。扩容会重新计算每个元素在新的哈希表中的位置,并将它们放到新的位置上。扩容会导致一定的性能损失,但是它可以保证哈希表的性能。

(3)hashmap会缩容吗,怎么缩容的

HashMap不会缩容,因为缩容会导致哈希表中元素的位置发生变化,需要重新计算哈希值,这样会影响哈希表的性能。

(4)hashmap并发如何实现

ava中的ConcurrentHashMap是线程安全的HashMap,它通过分段锁来实现并发访问ConcurrentHashMap将整个Map分成N个Segment,每个Segment独立地进行加锁操作,不同Segment之间互不影响,这样就可以支持多线程并发访问,提高了并发访问效率。

二、Mysql和Redis

1、MySQL 锁

MyISAM 仅仅支持表级锁(table-level locking),一锁就锁整张表,这在并发写的情况下性非常差。InnoDB 不光支持表级锁(table-level locking),还支持行级锁(row-level locking),默认为行级锁。

行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。

(1)表级锁和行级锁对比 

  • 表级锁: MySQL 中锁定粒度最大的一种锁(全局锁除外),是针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
  • 行级锁: MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。

(2)InnoDB 行锁是通过对索引数据页上的记录加锁实现的,MySQL InnoDB 支持三种行锁定方式

  • 记录锁(Record Lock) :也被称为记录锁,属于单个行记录上的锁。
  • 间隙锁(Gap Lock) :锁定一个范围,不包括记录本身。
  • 临键锁(Next-Key Lock) :Record Lock+Gap Lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题(MySQL 事务部分提到过)。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。

在 InnoDB 默认的隔离级别 REPEATABLE-READ 下,行锁默认使用的是 临键锁(Next-Key Lock)。但是,如果操作的索引是唯一索引或主键,InnoDB 会对 Next-Key Lock 进行优化,将其降级为 记录锁(Record Lock),即仅锁住索引本身,而不是范围。

(3)不论是表级锁还是行级锁,都存在共享锁(Share Lock,S 锁)和排他锁(Exclusive Lock,X 锁)这两类:

  • 共享锁(S 锁)又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
  • 排他锁(X 锁)又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。

排他锁与任何的锁都不兼容,共享锁仅和共享锁兼容。

(4)意向锁

如果需要用到表锁的话,如何判断表中的记录没有行锁呢,一行一行遍历肯定是不行,性能太差。我们需要用到一个叫做意向锁的东东来快速判断是否可以对某个表使用表锁。

意向锁是表级锁,共有两种:

  • 意向共享锁(Intention Shared Lock,IS 锁):事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁。
  • 意向排他锁(Intention Exclusive Lock,IX 锁):事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁。
  • 意向锁之间是互相兼容的,意向锁和共享锁和排它锁互斥。

2、MySQL 索引

(1)MySQL索引结构

索引底层数据结构存在很多种类型,常见的索引结构有: B 树, B+树 和 Hash、红黑树。在 MySQL 中,无论是 Innodb 还是 MyIsam,都使用了 B+树作为索引结构。在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景建议选择BTree索引。

(2)索引的优缺点

优点

  • 使用索引可以大大加快 数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因。
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

缺点

  • 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
  • 索引需要使用物理文件存储,也会耗费一定空间。

但是,使用索引一定能提高查询性能吗?

大多数情况下,索引查询都是比全表扫描要快的。但是如果数据库的数据量不大,那么使用索引也不一定能够带来很大提升。

(3)索引的底层数据结构

1) Hash 表

哈希算法有个 Hash 冲突 问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 链地址法。链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 HashMap 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后HashMap为了减少链表过长的时候搜索时间过长引入了红黑树

为了减少 Hash 冲突的发生,一个好的哈希函数应该“均匀地”将数据分布在整个可能的哈希值集合中。既然哈希表这么快,为什么 MySQL 没有使用其作为索引的数据结构呢? 主要是因为 Hash 索引不支持顺序和范围查询。假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了。并且,每次 IO 只能取一个。

2) B 树& B+树

B 树也称 B-树,全称为 多路平衡查找树 ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 Balanced (平衡)的意思。

目前大部分数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。

B 树& B+树两者有何异同呢?

  • B 树的所有节点既存放键(key) 也存放 数据(data),而 B+树只有叶子节点存放 key 和 data,其他内节点只存放 key。
  • B 树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
  • B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

(3) MySQL索引类型总结

1)按照数据结构维度划分:

  • BTree 索引:MySQL 里默认和最常用的索引类型。只有叶子节点存储 value,非叶子节点只有指针和 key。存储引擎 MyISAM 和 InnoDB 实现 BTree 索引都是使用 B+Tree,但二者实现方式不一样
  • 哈希索引:类似键值对的形式,一次即可定位。
  • RTree 索引:一般不会使用,仅支持 geometry 数据类型,优势在于范围查找,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
  • 全文索引:对文本的内容进行分词,进行搜索。目前只有 CHARVARCHARTEXT 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。

2)按照底层存储方式角度划分:

  • 聚簇索引(聚集索引):索引结构和数据一起存放的索引InnoDB 中的主键索引就属于聚簇索引。
  • 非聚簇索引(非聚集索引):索引结构和数据分开存放的索引二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。

3)按照应用维度划分:

  • 主键索引:加速查询 + 列值唯一(不可以有 NULL)+ 表中只有一个。
  • 普通索引:仅加速查询。
  • 唯一索引:加速查询 + 列值唯一(可以有 NULL)。
  • 覆盖索引:一个索引包含(或者说覆盖)所有需要查询的字段的值。
  • 联合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。
  • 全文索引:对文本的内容进行分词,进行搜索。目前只有 CHARVARCHARTEXT 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。

(4)二级索引

二级索引(Secondary Index)又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。

  • 唯一索引(Unique Key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  • 普通索引(Index)普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
  • 前缀索引(Prefix)前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。
  • 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。

(5)  B+树作为索引的优点

  • B+树的查询效率更高,因为B+树的非叶子节点只存储索引信息,而不存储数据信息,这样可以使得每个节点能够存储更多的索引信息,从而使得树的高度更低,查询效率更高。
  • B+树的插入和删除效率更高,因为B+树的叶子节点之间是通过链表相连的,所以插入和删除操作只需要修改相邻两个叶子节点之间的指针即可,不需要移动其他节点。
  • B+树支持范围查询,因为B+树的叶子节点之间是通过链表相连的,所以可以很方便地进行范围查询。

(6)联合索引

使用表中的多个字段创建索引,就是 联合索引,也叫 组合索引 或 复合索引

最左前缀匹配原则:

最左前缀匹配原则指的是,在使用联合索引时,MySQL 会根据联合索引中的字段顺序,从左到右依次到查询条件中去匹配,如果查询条件中存在与联合索引中最左侧字段相匹配的字段,则就会使用该字段过滤一批数据,直至联合索引中全部字段匹配完成,或者在执行过程中遇到范围查询(如 ><)才会停止匹配对于 >=<=BETWEENlike 前缀匹配的范围查询,并不会停止匹配。所以,我们在使用联合索引时,可以将区分度高的字段放在最左边,这也可以过滤更多数据。

3、MySQL为什么说单表的数据量不要超过500w

  • 如果单表容量大(大于2G),但是索引少(只通过主键ID查),性能也不会慢
  • 如果数据量大(大于500W),但是索引容量小(都是小字节字段),性能也不会慢
  • 所以,单表查询的性能取决于索引的大小(因为会放内存里),而索引的查询速度又受硬件的影响。
  • 建议:大表(数据量大、容量大)。先拆成主表(字段多)、detail表(容量高)。主表严格控制索引的质量,detail表只能用主键ID查(后期可以通过主键ID分表)。

事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为,MySQL 为了提高性能,会将表的索引装载到内存中。InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。

那么,我对于分库分表的观点是,需要结合实际需求,不宜过度设计,在项目一开始不采用分库与分表设计,而是随着业务的增长,在无法继续优化的情况下,再考虑分库与分表提高系统的性能。(500 万行作为分库分表的界限比较合适)

4、MySQL 事务

(1)那数据库事务有什么作用

简单来说,数据库事务可以保证多个对数据库的操作(也就是 SQL 语句)构成一个逻辑上的整体。构成这个逻辑上的整体的这些数据库操作遵循:要么全部执行成功,要么全部不执行。

(2)关系型数据库(例如:MySQLSQL ServerOracle 等)事务都有 ACID 特性: 

  • 原子性Atomicity) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  • 一致性Consistency): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
  • 隔离性Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  • 持久性Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障

(3)并发事务的控制方式有哪些

MySQL 中并发事务的控制方式无非就两种:锁 和 MVCC。锁可以看作是悲观控制的模式,多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式。 控制方式下会通过锁来显示控制共享资源而不是通过调度手段,MySQL 中主要是通过 读写锁 来实现并发控制。

MVCC 是多版本并发控制方法,即对一份数据会存储多个版本,通过事务的可见性来保证事务能看到自己应该看到的版本。通常会有一个全局的版本分配器来为每一行数据设置版本号,版本号是唯一的。

MVCC 在 MySQL 中实现所依赖的手段主要是: 隐藏字段、read view、undo log

  • undo log : undo log 用于记录某行数据的多个版本的数据。
  • read view 和 隐藏字段 : 用来判断当前版本数据的可见性。

5、Redis 常用的数据结构有哪些

  • 5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
  • 3 种特殊数据结构 :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。

6、Redis 生产问题(重要)

(1)缓存穿透

缓存穿透说简单点就是大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

有哪些解决办法?

1)缓存无效 key

如果非要用这种方式来解决穿透问题的话,尽量将无效的 key 的过期时间设置短一点比如 1 分钟。

2)布隆过滤器

具体是这样做的:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

(2)缓存击穿

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

有哪些解决办法?

  • 设置热点数据永不过期或者过期时间比较长。
  • 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  • 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。

缓存穿透和缓存击穿有什么区别?

  • 缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。
  • 缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)

(3)缓存雪崩

实际上,缓存雪崩描述的就是这样一个简单的场景:缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。另外,缓存服务宕机也会导致缓存雪崩现象,导致所有的请求都落到了数据库上。

有哪些解决办法?

针对 Redis 服务不可用的情况:

  • 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
  • 限流,避免同时处理大量的请求。

针对热点缓存失效的情况:

  • 设置不同的失效时间比如随机设置缓存的失效时间。
  • 缓存永不失效(不太推荐,实用性太差)。
  • 设置二级缓存。

缓存雪崩和缓存击穿有什么区别?

缓存雪崩和缓存击穿比较像,但缓存雪崩导致的原因是缓存中的大量或者所有数据失效,缓存击穿导致的原因主要是某个热点数据不存在与缓存中(通常是因为缓存中的那份数据已经过期)

7、Redis 持久化机制(重要)

(1)Redis 支持持久化,而且支持 3 种持久化方式

  • 快照(snapshotting,RDB)
  • 只追加文件(append-only file, AOF)
  • RDB 和 AOF 的混合持久化(Redis 4.0 新增)

(2)快照(RDB)

Redis 可以通过创建快照来获得存储在内存里面的数据在 某个时间点 上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。

(3) 只追加文件(append-only file, AOF)

AOF 持久化功能的实现可以简单分为 5 步:

  • 命令追加(append) :所有的写命令会追加到 AOF 缓冲区中。
  • 文件写入(write) :将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
  • 文件同步(fsync) :AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
  • 文件重写(rewrite) :随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
  • 重启加载(load) :当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

三、RPC和Dubbo 

1、RPC的原理图和调用过程

图中服务端启动时将自己的服务节点信息注册到注册中心,客户端调用远程方法时会订阅注册中心中的可用服务节点信息,拿到可用服务节点之后远程调用方法,当注册中心中的可用服务节点发生变化时会通知客户端,避免客户端继续调用已经失效的节点。那客户端是如何调用远程方法的呢,来看一下远程调用示意图:

  • 客户端模块代理所有远程方法的调用
  • 将目标服务、目标方法、调用目标方法的参数等必要信息序列化
  • 序列化之后的数据包进一步压缩,压缩后的数据包通过网络通信传输到目标服务节点
  • 服务节点将接受到的数据包进行解压
  • 解压后的数据包反序列化成目标服务、目标方法、目标方法的调用参数
  • 通过服务端代理调用目标方法获取结果,结果同样需要序列化、压缩然后回传给客户端

2、RPC有几种模式,ping-pong,服务端streaming,客户端streaming,双向streaming,听说过么?

(1)RPC有模式

RPC(Remote Procedure Call)是一种远程过程调用协议,它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编写远程调用代码。RPC有多种模式,其中比较常见的有:

  • 基于同步阻塞的模式
  • 基于异步操作的回调函数
  • 基于Promise的回调函数

(2)当我们使用gRPC时,我们可以使用以下四种通信模式:

  • 简单 RPC(Unary RPC):客户端向服务器发送一个请求并等待响应,就像一次普通的函数调用一样。
  • 服务端流式 RPC (Server streaming RPC):客户端向服务器发送一个请求,服务器返回一个数据流,客户端从该流中读取数据直到没有数据为止。
  • 客户端流式 RPC (Client streaming RPC):客户端向服务器发送一个数据流,直到没有数据为止,然后等待服务器的响应。
  • 双向流式 RPC(Bi-directional streaming RPC):客户端和服务器都可以通过单独的数据流发送消息。这两个数据流在运行时组合在一起,形成一个双向数据流。

3、服务启动的时候服务基本信息被注册到注册中心,如果服务提供者挂了,注册中心如何知道服务不可用了呢?

服务掉线分为主动下线和心跳检测。

比如服务由于发版时,在重启之前先主动通知注册中心:我要重启了,有流量进来先不要分给我,让别的机器服务,等我重启成功后在放流量进来,或者是在管理后台手动直接摘掉机器,这个是主动下线。

 增加 Netty 心跳机制 : 保证客户端和服务端的连接不被断掉,避免重连。

心跳检测处理服务非正常下线(如断电断网)的情况,这个时候如果注册中心不知道该服务已经掉线,一旦被其调用就会带来问题。为了避免出现这样的情况,注册中心增加一个心跳检测功能,它会对服务提供者(Provider)进行心跳检测,比如每隔 30s 发送一个心跳,如果三次心跳结果都没有返回值,就认为该服务已下线,赶紧更新 Consumer 的服务列表,告诉 Consumer 调用别的机器

4、如果注册中心挂了,比如你用的是 Zookeeper,如果 Zookeeper 挂了,那服务之间还能相互调用吗?

首先注册中心挂掉也要分两种情况,如果数据库挂了,ZK 还是能用的,因为 ZK 会缓存注册机列表在缓存里。其次 ZK 本身就是一个集群的,一台机器挂了,ZK 会选举出集群中的其他机器作为 Master 继续提供服务,如果整个集群都挂了也没问题,因为调用者本地会缓存注册中心获取的服务列表。省略和注册中心的交互,Consumer 和 Provider 采用直连方式,这些策略都是可配置的。

5、服务端如何处理请求?有哪些方式?

  • 同步阻塞方式(BIO):客户端发一次请求,服务端生成一个对应线程去处理。当客户端同时发起的请求很多时,服务端需要创建多个线程去处理每一个请求,当达到了系统最大的线程数时,新来的请求就无法处理了。
  • 同步非阻塞方式 (NIO):客户端发一次请求,服务端并不是每次都创建一个新线程来处理,而是通过 I/O 多路复用技术进行处理。就是把多个 I/O 的阻塞复用到同一个 select 的阻塞上,从而使系统在单线程的情况下可以同时处理多个客户端请求。这种方式的优势是开销小,不用为每个请求创建一个线程,可以节省系统开销。
  • 异步非阻塞方式(AIO):客户端发起一个 I/O 操作然后立即返回,等 I/O 操作真正完成以后,客户端会得到 I/O 操作完成的通知,此时客户端只需要对数据进行处理就好了,不需要进行实际的 I/O 读写操作,因为真正的 I/O 读取或者写入操作已经由内核完成了。这种方式的优势是客户端无需等待,不存在阻塞等待问题。

6、为什么要进行序列化和反序列化

  • 解决内存中数据结构字节序列的映射过程中,如何保留各个结构和字段间的关系而生的技术 
  • 解决异构系统的数据传输,比如大小端、远端的持久存储;
  • 压缩数据,加快网络传输

7、在RPC框架中Netty 如何实现 Client 端与 Server 端的异步通信

在 Netty 中,RPC 框架的实现是基于 Netty 的异步通信机制的。RPC 框架中,客户端与服务端的异步通信是通过 Channel 和 EventLoop 实现的。Channel 是一个连接到网络套接字的组件,而 EventLoop 是处理 Channel 事件的线程。在 Netty 中,每个 Channel 都有一个与之相关联的 EventLoop,它会处理所有的 I/O 事件和请求。

具体步骤如下:

  • 客户端通过 Channel 向服务端发送请求。
  • 服务端通过 Channel 接收请求。
  • 服务端将请求交给 EventLoop 处理。
  • EventLoop 处理请求并返回结果。
  • 服务端通过 Channel 将结果返回给客户端。
  • 客户端通过 Channel 接收结果。

8、Zookeeper 如何作为服务注册与发现的注册中心

9、为什么用序列化机制 Protostuff 替代 JDK 自带的序列化机制

  • 使用简单。Protobuf 每次要编写接口定义文件,然后还要编译,操作太繁琐。
  • 高性能。相对 JSON 等文本序列化库,protostuff 是二进制的,因此性能比 JSON 等方式高。
  • 序列化后的数据更小,性能更高。protostuff 占用内存最少,protobuf 其次,XML 最后。
  • 序列化速度快。protostuff 比 protobuf 快 3 倍左右,protobuf 比 XML 快 4-5 倍

10、JDK 如何利用动态代理机制实现 RPC 代理

11、Duboo的四种负载均衡策略

客户端调用远程服务的时候进行负载均衡 :调用服务的时候,从很多服务地址中根据相应的负载均衡算法选取一个服务地址。

(1)RandomLoadBalance:根据权重随机选择(对加权随机算法的实现)。这是Dubbo默认采用的一种负载均衡策略。

(2)LeastActiveLoadBalance:最小活跃数负载均衡。

Dubbo 就认为谁的活跃数越少,谁的处理速度就越快,性能也越好,这样的话,我就优先把请求给活跃数少的服务提供者处理。

(3)ConsistentHashLoadBalance:一致性Hash负载均衡策略

ConsistentHashLoadBalance 中没有权重的概念,具体是哪个服务提供者处理请求是由你的请求的参数决定的,也就是说相同参数的请求总是发到同一个服务提供者。另外,Dubbo 为了避免数据倾斜问题(节点不够分散,大量请求落到同一节点),还引入了虚拟节点的概念。通过虚拟节点可以让节点更加分散,有效均衡各个节点的请求量。

(4)RoundRobinLoadBalance:加权轮询负载均衡。

轮询就是把请求依次分配给每个服务提供者。加权轮询就是在轮询的基础上,让更多的请求落到权重更大的服务提供者上。

四、计算机网路

1、从输入baidu.com到得到网页的全过程

  • 用户在浏览器地址栏输入URL “ https://www.baidu.com/ ”。
  • 浏览器查找当前URL的DNS缓存记录。
  • DNS解析URL对应的IP。
  • 根据IP建立TCP连接(三次握手)。
  • HTTP发起请求。
  • 服务器处理请求并返回HTTP报文。
  • 浏览器解析渲染页面。

2、TCP三次握手和四次挥手

(1)三次握手的步骤如下:

  • 客户端向服务器发送一个SYN包,表示请求建立连接。
  • 服务器接收到客户端发来的SYN包后,对该包进行确认后结束LISTEN阶段,并返回一段TCP报文,表示确认客户端的报文序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接。
  • 客户端接收到服务器发来的TCP报文后,再向服务器发送一段确认报文,表示客户端已经准备好发送数据。

(2)四次挥手的步骤如下:

  • 客户端向服务器发送一个FIN包,表示请求断开连接。
  • 服务器接收到客户端发来的FIN包后,对该包进行确认后进入CLOSE_WAIT状态。
  • 服务器向客户端发送一个ACK包,表示已经准备好断开连接。
  • 客户端接收到服务器发来的ACK包后,进入TIME_WAIT状态,并向服务器发送一个FIN包,表示已经准备好断开连接。

五、Java 设计模式 GOF23

1、这些模式分为三类:创建型模式、结构型模式和行为型模式。

  • 创建型模式包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式;
  • 结构型模式包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式;
  • 行为型模式包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法和访问者模式。

六、Spring、Spring MVC、Spring Boot

七、HTML、 JavaScript、 CSS、Bootstrap 框架
八、基于 LSTM 语言模型的生成食谱

项目内容: 在 LSTM 模型的基础上,加入注意力机制对食谱进行训练和预测,实现对菜谱的准确分离。
• 对数据集进行预处理和清洗,去除噪声、缺失数据和异常数据等
• 构建 Sequence-to-Sequence 没有 attention 机制和有 attention 机制两种训练语言模型
• 选择 Bleu-4 和 Meteor 作为模型量化评估的参数
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金州饿霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值