分享

中厂,面试就问了4道题,凉了!

 田维常 2023-04-23 发布于广东

你好,我是田哥

所谓的金三银四,已变成铜三铁四了。很多人基本上莫有面试机会,更可惜的是机会有了,却没有把握住。

今天早上,一个朋友和我说面试中被问了下面四道题目,最后一道是真的搞不定。

条件:五年工作,普通本科,基本在外包

面一家中厂,期望薪资24K

面试结果:就问了四个题,前面三个题回答的马马虎虎,最后一道完全不知如何下手,凉了!

1:MySQL性能优化方法有哪些?

MySQL性能优化方法包括以下几个方面:

1. 优化SQL语句:

SQL语句是MySQL性能优化的重要方面。优化SQL语句可以提高查询效率和减少资源消耗。有以下几个方法:避免使用SELECT *,避免使用子查询,使用索引,使用JOIN代替子查询等。

2. 配置MySQL服务器参数:

MySQL服务器参数的设置直接影响MySQL的性能,包括缓存大小、连接数、线程池大小等。根据实际应用场景,合理配置MySQL服务器参数可以提高MySQL的性能。

3. 数据库表结构优化:

数据库表结构设计的好坏直接影响MySQL的性能。应该尽量避免使用大量的NULL值、重复的列、过多的索引等。

4. 数据库表分区:

将大的数据库表分区可以提高MySQL的性能。分区可以减少数据检索时的扫描范围,从而提高查询效率。

5. 使用缓存技术:

使用缓存技术可以减少数据库访问次数,提高MySQL的性能。常见的缓存技术包括Memcached和Redis。

6. 数据库读写分离:

将读写操作分离可以提高MySQL的性能。读操作可以分配到从服务器,写操作可以分配到主服务器。这样可以提高MySQL的并发性能。

7. 使用分布式数据库:

使用分布式数据库可以提高MySQL的性能。分布式数据库将数据分配到多个节点,可以提高MySQL的并发性能和可扩展性。

总之,对于MySQL的优化来说,需要根据具体情况进行优化,从SQL语句优化、服务器参数配置、数据库表结构优化等多个方面入手,才能提高MySQL的性能。

2:分布式事务实现方案有哪些?

常见的分布式事务实现方案有以下几种:

1. 两阶段提交(Two-Phase Commit,2PC)

两阶段提交是最常用的分布式事务实现方案之一,主要思想是将事务分为两个阶段,第一阶段是准备阶段,第二阶段是提交阶段。在准备阶段,所有参与者向协调者发送事务准备请求,协调者收到请求后向所有参与者发送准备请求,如果所有参与者都准备就绪,则进入提交阶段,否则回滚事务。

优点:实现简单,可靠性高。

缺点:存在单点故障,性能较差,容易出现阻塞。

2. 三阶段提交(Three-Phase Commit,3PC)

三阶段提交是对两阶段提交的改进,主要思想是在两阶段提交的基础上增加一个超时机制。在准备阶段,如果协调者接收到参与者的准备请求后一段时间内没有收到提交请求,则会向参与者发送中止请求,参与者接收到中止请求后回滚事务。

优点:解决了两阶段提交的阻塞问题,容错性更好。

缺点:实现复杂,性能较差。

3. 补偿事务(Compensating Transaction)

补偿事务是一种基于业务逻辑的分布式事务实现方案,主要思想是在每个参与者上定义一个补偿事务,当事务出现异常时,执行相应的补偿事务以保证数据的一致性。

优点:实现简单,可靠性高。

缺点:需要对业务逻辑进行深入分析,复杂度较高。

4. 基于消息的最终一致性(Message-Based Eventual Consistency)

基于消息的最终一致性是一种异步的分布式事务实现方案,主要思想是在每个参与者上定义一个消息队列,将事务操作转化为消息发送到队列中,通过消息的异步通信实现最终一致性。

优点:实现简单,性能高。

缺点:对消息队列的可靠性和性能要求较高。

5. Paxos算法

Paxos算法是一种基于消息传递的一致性算法,用于解决分布式系统中的一致性问题。Paxos算法可以用来实现分布式事务,其主要思想是通过选举一个领导者来协调事务的执行。

优点:实现简单,容错性高。

缺点:性能较差,需要多次消息传递。

3:JVM性能调优手段有哪些?

1. 内存调优:

JVM的内存管理是非常重要的一方面,可以通过调整JVM的内存参数来优化JVM的性能,如-Xms(初始堆大小)、-Xmx(最大堆大小)、-Xmn(年轻代大小)、-XX:PermSize(永久代大小)等。

2. 垃圾回收调优:

JVM的垃圾回收机制是JVM性能调优的一个重要方面。可以通过调整垃圾回收器的类型、参数以及对不同的对象采用不同的垃圾回收策略等方式来优化JVM的垃圾回收性能。

3. 线程调优:

线程是JVM的重要组成部分,可以通过调整线程的数量、优先级、调度策略等方式来优化JVM的性能。

4. 类加载调优:

类加载是JVM的一个重要部分,可以通过调整类加载器的缓存策略、使用预编译技术、优化类的加载顺序等方式来优化JVM的性能。

5. JIT调优:

JIT(即时编译器)是JVM的重要组成部分,可以通过调整JIT的优化级别、选择适合的编译器等方式来优化JVM的性能。

6. I/O调优:

I/O操作是JVM常用的操作之一,可以通过调整I/O缓存、选择合适的I/O方式等方式来优化JVM的性能。

7. 数据库连接池调优:

JVM通常会涉及到数据库连接,可以通过调整数据库连接池的大小、连接超时等方式来优化JVM的性能。

8. 网络调优:

JVM在网络通信方面也非常重要,可以通过调整网络缓存、调整网络传输方式等方式来优化JVM的性能。

4:什么是LRU算法?用java写一个LRU算法

RU算法是一种缓存淘汰策略,Least Recently Used的缩写,即最近最少使用。

实现思路:

  1. 创建一个双向链表,用于存储数据。

  2. 创建一个hashmap,用于存储数据的key和对应的节点。

  3. 当数据被访问时,如果在hashmap中存在对应的节点,则将该节点移动到链表头部。

  4. 当链表满时,删除链表尾部的节点。

Java代码实现:

/**
 * @author tianwc 公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年04月23日 14:14
 * 博客地址:<a href="http:///">博客地址</a>
 *
 */

public class LRUCache<KV{

    private int capacity; // 缓存容量
    private Map<K, Node<K, V>> map; // 缓存存储结构
    private Node<K, V> head; // 链表头部
    private Node<K, V> tail; // 链表尾部

    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>(capacity);
        head = new Node<>(nullnull);
        tail = new Node<>(nullnull);
        head.next = tail;
        tail.prev = head;
    }

    public V get(K key) {
        Node<K, V> node = map.get(key);
        if (node == null) {
            return null;
        }
        // 将访问的节点移动到链表头部
        remove(node);
        addFirst(node);
        return node.value;
    }

    public void put(K key, V value) {
        Node<K, V> node = map.get(key);
        if (node != null) {
            // 更新节点值,并移动到链表头部
            node.value = value;
            remove(node);
            addFirst(node);
        } else {
            node = new Node<>(key, value);
            map.put(key, node);
            // 添加到链表头部
            addFirst(node);
            // 如果容量已满,删除链表尾部节点
            if (map.size() > capacity) {
                map.remove(tail.prev.key);
                remove(tail.prev);
            }
        }
    }

    private void addFirst(Node<K, V> node) {
        node.next = head.next;
        node.prev = head;
        head.next.prev = node;
        head.next = node;
    }

    private void remove(Node<K, V> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private static class Node<KV{
        K key;
        V value;
        Node<K, V> prev;
        Node<K, V> next;

        Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }
}

使用示例:

LRUCache<Integer, String> cache = new LRUCache<>(3);
cache.put(1"one");
cache.put(2"two");
cache.put(3"three");
cache.put(4"four");
System.out.println(cache.get(1)); // 输出null
System.out.println(cache.get(2)); // 输出"two"
cache.put(5"five");
System.out.println(cache.get(3)); // 输出null
System.out.println(cache.get(4)); // 输出null
System.out.println(cache.get(5)); // 输出"five"

输出结果:

null
two
null
null
five

每个面试官都有自己的面试套路,有的人一上来从基础开始,有的人却是从项目开始,还有的人是从你自我介绍内容开始,....

文中的这位朋友是从自我介绍中开始的,因为自我介绍中提到自己有性能调优经验,于是面试官一开始就问性能优化方面,看到她这些题的回答的不怎么样,于是也猜到就是为了吹牛逼而搞上去的“性能调优经验”。

再次,提醒大家,不管是简历内容,还是自我介绍内容,都要慎重,千万别把自己不会写上去,千万别把不会的吹牛逼说自己会,否则,你将会浪费一次面试机会。

好了,今天就分享这么多,我们下期再见,记得点赞收藏

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多