2020 面试题精选

1.java.util.concurrent.locks.Lock&ReentrantLock和synchronized的区别

答:Lock是Java 5以后引入的新的API,和关键字synchronized相比

    主要相同点:Lock 能完成synchronized所实现的所有功能;
    主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)。
    synchronized是和if、else、for、while一样的关键字&ReentrantLock是类   
    ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁
    ReentrantLock可以获取各种锁的信息
    ReentrantLock可以灵活地实现多路通知


ReentrantLock是Lock的默认实现,在聊ReentranLock之前,我们需要先弄清楚一些概念:

可重入锁:可重入锁是指同一个线程可以多次获得同一把锁;ReentrantLock和关键字Synchronized都是可重入锁
可中断锁:可中断锁时只线程在获取锁的过程中,是否可以相应线程中断操作。synchronized是不可中断的,ReentrantLock是可中断的
公平锁和非公平锁:公平锁是指多个线程尝试获取同一把锁的时候,获取锁的顺序按照线程到达的先后顺序获取,而不是随机插队的方式获取。synchronized是非公平锁,而ReentrantLock是两种都可以实现,不过默认是非公平锁
Object中wait类似的方法Condition相同


2.数据库事务的ACID是指什么
原子性/一致性/隔离性/持久性
default 可重复读 不可避免幻读 --事务A读取了符合条件的行,发现插入了事务B插入的数据

脏读:A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。
不可重复读:事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。
幻读:事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行


3.获得一个类的类对象有哪些方式

方法1:类型.class,例如:String.class
方法2:对象.getClass(),例如:"hello".getClass()
方法3:Class.forName(),例如:Class.forName("java.lang.String")

4.如何通过反射创建对象

方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象, 
  例如:String.class.getConstructor(String.class).newInstance("Hello");  

5.如何通过反射调用对象的方法

String str = "hello";
Method m = str.getClass().getMethod("toUpperCase");
System.out.println(m.invoke(str));

 

6.常用设计模式

共23种设计模式,包括:

Abstract Factory(抽象工厂模式),Builder(建造者模式),Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式);Facade(门面模式),Adapter(适配器模式),Bridge(桥梁模式),Composite(合成模式),Decorator(装饰模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解释器模式),Visitor(访问者模式),Iterator(迭代子模式),Mediator(调停者模式),Memento(备忘录模式),Observer(观察者模式),State(状态模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(责任链模式)

7.用Java写一个单例类

饿汉

private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}

懒汉

private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}

8.CyclicBarrier&CountDownLatch区别
CyclicBarrier的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行
CyclicBarrier只能唤起一个任务,CountDownLatch可以唤起多个任务
CyclicBarrier可重用,CountDownLatch不可重用,计数值为0该CountDownLatch就不可再用了
CountDownLatch则不是,某线程运行到某个点上之后,只是给某个数值-1而已,该线程继续运行

CountDownLatch:
假如有这样一个需求,当我们需要解析一个Excel里多个sheet的数据时,可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要统计解析总耗时。分析一下:解析每个sheet耗时可能不一样,总耗时就是最长耗时的那个操作。
CountDownLatch称之为闭锁,它可以使一个或一批线程在闭锁上等待,等到其他线程执行完相应操作后,闭锁打开,这些等待的线程才可以继续执行。确切的说,闭锁在内部维护了一个倒计数器。通过该计数器的值来决定闭锁的状态,从而决定是否允许等待的线程继续执行。

创建CountDownLatch对象
调用其实例方法 await(),让当前线程等待
调用 countDown()方法,让计数器减1
当计数器变为0的时候, await()方法会返回
Semaphore常用场景:限流
有5个空位,门口有个门卫,手中5把钥匙分别对应5个车位上面的锁,来一辆车,门卫会给司机一把钥匙,然后进去找到对应的车位停下来,出去的时候司机将钥匙归还给门卫。停车场生意比较好,同时来了100两车,门卫手中只有5把钥匙,同时只能放5辆车进入,其他车只能等待,等有人将钥匙归还给门卫之后,才能让其他车辆进入

 

9.volatile关键字的作用

多线程主要围绕可见性和原子性两个特性而展开,使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据

使用volatile则会对禁止语义重排序,当然这也一定程度上降低了代码执行效率

volatile的一个重要作用就是和CAS结合,保证了原子性,详细的可以参见java.util.concurrent.atomic包下的类,比如AtomicInteger。

 

10.什么是线程安全如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是线程安全的。
不可变
像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用
绝对线程安全
不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet
相对线程安全
相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。
线程非安全
这个就没什么好说的了,ArrayList、LinkedList、HashMap等都是线程非安全的类

 

11.如何在两个线程之间共享数据
通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待,比方说阻塞队列BlockingQueue(有界阻塞队列&无界阻塞队列)就是为线程之间共享数据而设计的

 

12.Linux环境下如何查找哪个线程使用CPU最长
(1)获取项目的pid,jps或者ps -ef | grep java,这个前面有讲过
(2)top -H -p pid,顺序不能改变

 

13.面向服务分布式架构SOA:
拆分架构 :
1.分担服务器压力。
2.提高项目并发能力。
拆分原则 :
1.根据业务和职能拆分。
为了减轻数据库压力,提高数据库效率?
解决方案 :
1.集群(主主,主备,读写分离)
2.分表,分库。
3.开启缓存。
4.开启索引.
5.sql语句优化。
6.数据库设计优化。


数据库本身优化,还可以加redis缓存?
1.减轻数据库压力(查询缓存,不再查询数据库)。
2.提高查询效率(redis是内存版nosql数据库)
3.提高并发能力。
dubbo :服务治理中间件(分布式服务架构)
特点 :
1.rpc 远程通信
2.NIO new IO 异步通信。
dubbo优化 :
1.服务集群。
2.序列化优化 kryo
3.失败重试。

 

第一级优化 :
1.集群(主主,主备,读写分离)

作用 :高可用和高并发。
2.分表和分库(大数据查询效率低)
3.开启缓存
4.开启索引
5.优化sql查询
5.数据库设计

 

第二级优化 :redis缓存
作用 :
1.减轻数据库压力
2.提高项目查询效率
(redis是一个nosql版内存版数据库)
redis服务器本身优化:
1.内存淘汰策略。
2.线程安全问题。
3.redis3.0 :自动高可用,自动容错。

 

第三极优化 :solr进行搜索
作用 :
1.减轻数据库压力。
2.提高检索效率(搜索索引)
案例 :
solr服务器本身优化:
1.集群(高可用,高容错)

 

第四级优化 :SOA面向服务分布式的架构
作用 :
1.分担服务器压力。
2.提高项目并发能力。jvm优化。
优化 :soa使用dubbo+zookeeper tomcat服务器优化
dubbo优化 :
1.服务集群。
2.序列化优化 kryo
3.失败重试。


第五级优化 :fastDFS分布式文件系统
作用 :存储图片
1.访问效率高。
2.自动容错。
3.线性扩容。


第六级优化 :

使用mq消息服务器,应用于服务与服务之间进行通信。
作用 :1.异步通信。2.任务异步处理。优势:流量削峰。
优化mq :集群。


第七级优化 :页面静态化
1.查询效率提高(访问静态数据)
2.并发能力提高。
技术 :freemarket实现静态化。
思考 : 优化。
缺点 :
html页面商品数据。
商品描述,规格,详情。
不能及时和数据库同步。
优化 :
mq进行同步静态页面。
同步流程:
商品添加,修改,删除。
发送消息
详情系统接收消息动态生成,删除html页面。


第8级优化 :nginx的使用
1.http服务器。
2.负载均衡。
优化:
集群。
页面静态化 :
技术选型 ;freemarket
优势 :简单,容易上手,语法简单,功能更强大。

 

14.TCP如何保证可靠传输?三次握手过程?

在TCP的连接中,数据流必须以正确的顺序送达对方。TCP的可靠性是通过顺序编号和确认(ACK)来实现的。TCP 连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。第一次是客户端发起连接;第二次表示服务器收到了客户端的请求;第三次表示客户端收到了服务器的反馈。

 

15.常用的hash算法有哪些?
(1)加法hash:所谓的加法Hash就是把输入元素一个一个的加起来构成最后的结果。
(2)位运算hash:这类型Hash函数通过利用各种位运算(常见的是移位和异或)来充分的混合输入元素
(3)乘法hash:33*hash + key.charAt(i)

 

16.什么是一致性哈希?
设计目标是为了解决因特网中的热点(Hot spot)问题,一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义:平衡性(Balance) ;单调性(Monotonicity) ;分散性(Spread) ;负载(Load)


17.数据库中的范式有哪些?
第一范式----数据库中的表(所有字段值)都是不可分割的原子数据项。
第二范式----数据库表中的每一列都和主键相关,而不能只和主键的某一部分相关。
第三范式----数据库表中每一列数据都和主键直接相关,不能间接相关。范式是为了减小数据冗余。

 

18.数据库中的索引的结构?什么情况下适合建索引?
数据库中索引的结构是一种排序的数据结构,数据库索引是通过B树和变形的B+树实现的。什么情况下不适合建立索引:1.对于在查询过程中很少使用或参考的列;对于那些只有很少数据值的列;对于那些定义为image,text和bit数据类型的列;当修改性能远大于检索性能。
根据系统自身的环境情况,有效的限制执行线程的数量,使得运行效果达到最佳。线程主要是通过控制执行的线程的数量,超出数量的线程排队等候,等待有任务执行完毕,再从队列最前面取出任务执行

 

19.TCP 协议与 UDP 协议有什么区别?
TCP(Tranfer Control Protocol)的缩写,是一种面向连接的保证传输的协议,在传输数据流前,双方会先建立一条虚拟的通信道。可以很少差错传输数据。
UDP(User DataGram Protocol)的缩写,是一种无连接的协议,使用UDP传输数据时,每个数据段都是一个独立的信息,包括完整的源地址和目的地,在网络上以任何可能的 路径传到目的地,因此,能否到达目的地,以及到达目的地的时间和内容的完整性都不能保证。
所以TCP比UDP多了建立连接的时间。相对UDP而言,TCP具有更高的安全性和可靠性。
TCP协议传输的大小不限制,一旦连接被建立,双方可以按照一定的格式传输大量的数据,而UDP是一个不可靠的协议,大小有限制,每次不能超过64K。

 

20.tomcat 如何调优,涉及哪些参数。
硬件上选择,操作系统选择,版本选择,jdk选择,配置jvm参数,配置connector的线程数量,开启gzip压缩,trimSpaces,集群等
a) 内存优化:主要是对Tomcat启动参数进行优化,我们可以在Tomcat启动脚本中修改它的最大内存数等等。
b) 线程数优化:Tomcat的并发连接参数,主要在Tomcat配置文件中server.xml中配置,比如修改最小空闲连接线程数,用于提高系统处理性能等等。
c) 优化缓存:打开压缩功能,修改参数,比如压缩的输出内容大小默认为2KB,可以适当的修改

 

21.说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的。
AOP与IOC的概念(即spring的核心)
a) IOC:Spring是开源框架,使用框架可以使我们减少工作量,提高工作效率并且它是分层结构,即相对应的层处理对应的业务逻辑,减少代码的耦合度。而spring的核心是IOC控制反转和AOP面向切面编程。IOC控制反转主要强调的是程序之间的关系是由容器控制的,容器控制对象,控制了对外部资源的获取。而反转即为,在传统的编程中都是由我们创建对象获取依赖对象,而在IOC中是容器帮我们创建对象并注入依赖对象,正是容器帮我们查找和注入对象,对象是被获取,所以叫反转。
b) AOP:面向切面编程,主要是管理系统层的业务,比如日志,权限,事物等。AOP是将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为切面(aspect),切面将那些与业务逻辑无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。
核心组件:bean,context,core,单例注入是通过单例beanFactory进行创建,生命周期是在创建的时候通过接口实现开启,循环注入是通过后置处理器,aop其实就是通过反射进行动态代理,pointcut,advice等。

 

22.Springmvc 中 DispatcherServlet 初始化过程。
入口是web.xml中配置的ds,ds继承了HttpServletBean,FrameworkServlet,通过其中的init方法进行初始化装载bean和实例,initServletBean是实际完成上下文工作和bean初始化的方法。

 

23.springMVC的执行流程
springMVC是由dispatchservlet为核心的分层控制框架。首先客户端发出一个请求web服务器解析请求url并去匹配dispatchservlet的映射url,如果匹配上就将这个请求放入到dispatchservlet,dispatchservlet根据mapping映射配置去寻找相对应的handel,然后把处理权交给找到的handel,handel封装了处理业务逻辑的代码,当handel处理完后会返回一个逻辑视图modelandview给dispatchservlet,此时的modelandview是一个逻辑视图不是一个正式视图,所以dispatchservlet会通过viewresource视图资源去解析modelandview,然后将解析后的参数放到view中返回到客户端并展现。

 

24.事物的理解
a) 事物具有原子性,一致性,持久性,隔离性
b) 原子性:是指在一个事物中,要么全部执行成功,要么全部失败回滚。
c) 一致性:事物执行之前和执行之后都处于一致性状态
d) 持久性:事物多数据的操作是永久性
e) 隔离性:当一个事物正在对数据进行操作时,另一个事物不可以对数据进行操作,也就是多个并发事物之间相互隔离。


25.spring 的 controller 是单例还是多例,怎么保证并发的安全。
单例
通过单例工厂 DefaultSingletonBeanRegistry实现单例
通过AsyncTaskExecutor保持安全

 

26.redis 的持久化的机制,aof 和 rdb 的区别。

RDB 定时快照方式(snapshot):定时备份,可能会丢失数据

AOF 基于语句追加方式 只追加写操作

AOF 持久化和 RDB 持久化的最主要区别在于,前者记录了数据的变更,而后者是保存了数据本身

 

27.elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段。elasticsearch 的倒排索引是什么。

ElasticSearch(简称ES)是一个分布式、Restful的搜索及分析服务器,设计用于分布式计算;能够达到实时搜索,稳定,可靠,快速。和Apache Solr一样,它也是基于Lucence的索引服务器,而ElasticSearch对比Solr的优点在于:

1.轻量级:安装启动方便,下载文件之后一条命令就可以启动。
2.Schema free:可以向服务器提交任意结构的JSON对象,Solr中使用schema.xml指定了索引结构。
3.多索引文件支持:使用不同的index参数就能创建另一个索引文件,Solr中需要另行配置。
4.分布式:Solr Cloud的配置比较复杂。

倒排索引是实现“单词-文档矩阵”的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

##elasticsearch 索引数据多了怎么办,如何调优,部署。

使用bulk API

初次索引的时候,把 replica 设置为 0

增大 threadpool.index.queue_size

增大 indices.memory.index_buffer_size

增大 index.translog.flush_threshold_ops

增大 index.translog.sync_interval

增大 index.engine.robin.refresh_interval

 

28.有 3n+1 个数字,其中 3n 个中是重复的,只有 1 个是不重复的,怎么找出来。

##常用的排序算法,快排,归并、冒泡。快排的最优时间复杂度,最差复杂度。冒泡排序的优化方案。

##二分查找的时间复杂度,优势。

##一个已经构建好的 TreeSet,怎么完成倒排序。

//冒泡
  public static void mp(int a[]) {
    int swap = 0;
    for (int i = 0; i < a.length; i++) {
       for (int j = i; j < a.length; j++) {
            if (a[j] > a[i]) {
                swap = a[i];
                a[i] = a[j];
                a[j] = swap;
             }
          }
       }
     System.out.println(Arrays.toString(a));
   }

 

/**
     * 不使用递归的二分查找
     *title:commonBinarySearch
     *@param arr
     *@param key
     *@return 关键字位置
     */
    public static int commonBinarySearch(int[] arr,int key){
        int low = 0;
        int high = arr.length - 1;
        int middle = 0;//定义middle
    }

 

 /**
   * 使用递归的二分查找
   *title:recursionBinarySearch
   *@param arr 有序数组
   *@param key 待查找关键字
   *@return 找到的位置
   */
  public static int recursionBinarySearch(int[] arr,int key,int low,int high){

    if(key < arr[low] || key > arr[high] || low > high){
      return -1;        
    }
    int middle = (low + high) / 2;//初始中间位置
    if(arr[middle] > key){
      //比关键字大则关键字在左区域
      return recursionBinarySearch(arr, key, low, middle - 1);
    }else if(arr[middle] < key){
      //比关键字小则关键字在右区域
      return recursionBinarySearch(arr, key, middle + 1, high);
    }else {
      return middle;
    }  
  }

29.数据库隔离级别有哪些,各自的含义是什么,MYSQL 默认的隔离级别是是什么。
 

1.未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
2.提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
3.可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
4.串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

MYSQL默认是RepeatedRead级别

30.SQL 优化的一般步骤是什么,怎么看执行计划,如何理解其中各个字段的含义。

查看慢日志(show [session|gobal] status ),定位慢查询,查看慢查询执行计划 根据执行计划确认优化方案

Explain sql

select_type:表示select类型。常见的取值有SIMPLE(简单表,即不使用连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(union中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个SELECT)等。

talbe:输出结果集的表。

type:表的连接类型。性能由高到底:system(表中仅有一行)、const(表中最多有一个匹配行)、eq_ref、ref、ref_null、index_merge、unique_subquery、index_subquery、range、idnex等

possible_keys:查询时,可能使用的索引

key:实际使用的索引

key_len:索引字段的长度

rows:扫描行的数量

Extra:执行情况的说明和描述

Oracle优化

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like ‘%abc%’
若要提高效率,可以考虑全文检索。
7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)=‘abc’ // oracle总有的是substr函数。
select id from t where datediff(day,createdate,‘2005-11-30’)=0 //查过了确实没有datediff函数。
应改为:
select id from t where name like ‘abc%’
select id from t where createdate>=‘2005-11-30’ and createdate<‘2005-12-1’ //
oracle 中时间应该把char 转换成 date 如:createdate >= to_date(‘2005-11-30’,‘yyyy-mm-dd’)
10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
12.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(…)
13.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
29.尽量避免大事务操作,提高系统并发能力。
30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

31.数据库会死锁吗,举一个死锁的例子,mysql 怎么解决死锁。

产生死锁的原因主要是:

(1)系统资源不足。

(2) 进程运行推进的顺序不合适。

(3)资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

这里提供两个解决数据库死锁的方法:

1)重启数据库(谁用谁知道)

2)杀掉抢资源的进程:

先查哪些进程在抢资源:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

杀掉它们:Kill trx_mysql_thread_id;

 

32.mysql的索引原理,索引的类型有哪些,如何创建合理的索引,索引如何优化。

索引是通过复杂的算法,提高数据查询性能的手段。从磁盘io到内存io的转变

普通索引,主键,唯一,单列/多列索引建索引的几大原则

1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可

##聚集索引和非聚集索引的区别。

“聚簇”就是索引和记录紧密在一起。

非聚簇索引 索引文件和数据文件分开存放,索引文件的叶子页只保存了主键值,要定位记录还要去查找相应的数据块。

 

33.MQ 系统的数据如何保证不丢失。

基本都是对数据进行持久化,多盘存储

 

34.rabbitmq 如何实现集群高可用。

集群是保证服务可靠性的一种方式,同时可以通过水平扩展以提升消息吞吐能力。RabbitMQ是用分布式程序设计语言erlang开发的,所以天生就支持集群。接下来,将介绍RabbitMQ分布式消息处理方式、集群模式、节点类型,并动手搭建一个高可用集群环境,最后通过java程序来验证集群的高可用性。

三种分布式消息处理方式

RabbitMQ分布式的消息处理方式有以下三种:

1、Clustering:不支持跨网段,各节点需运行同版本的Erlang和RabbitMQ, 应用于同网段局域网。

2、Federation:允许单台服务器上的Exchange或Queue接收发布到另一台服务器上Exchange或Queue的消息, 应用于广域网,。

3、Shovel:与Federation类似,但工作在更低层次。

RabbitMQ对网络延迟很敏感,在LAN环境建议使用clustering方式;在WAN环境中,则使用Federation或Shovel。我们平时说的RabbitMQ集群,说的就是clustering方式,它是RabbitMQ内嵌的一种消息处理方式,而Federation或Shovel则是以plugin形式存在。

 

35.Redis的数据结构都有哪些。

字符串(strings):存储整数(比如计数器)和字符串(废话。。),有些公司也用来存储json/pb等序列化数据,并不推荐,浪费内存;

哈希表(hashes):存储配置,对象(比如用户、商品),优点是可以存取部分key,对于经常变化的或者部分key要求atom操作的适合;

列表(lists):可以用来存最新用户动态,时间轴,优点是有序,确定是元素可重复,不去重集合(sets):无序,唯一,对于要求严格唯一性的可以使用;

有序集合(sorted sets):集合的有序版,很好用,对于排名之类的复杂场景可以考虑。

 

##Redis 的使用要注意什么,讲讲持久化方式,内存设置,集群的应用和优劣势,淘汰策略等。

持久化方式:RDB时间点快照 AOF记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。

内存设置 maxmemory used_memory

虚拟内存:vm-enabled yes

3.0采用Cluster方式,Redis集群相对单机在功能上存在一些限制,需要开发人员提前了解,在使用时做好规避。限制如下:

1) key批量操作支持有限。如mset、mget,目前只支持具有相同slot值的key执行批量操作。对于映射为不同slot值的key由于执行mget、 mget等操作可能存在于多个节点上因此不被支持。

2) key事务操作支持有限。同理只支持多key在同一节点上的事务操作, 当多个key分布在不同的节点上时无法使用事务功能。

3) key作为数据分区的最小粒度, 因此不能将一个大的键值对象如hash、 list等映射到不同的节点。

4) 不支持多数据库空间。单机下的Redis可以支持16个数据库, 集群模式下只能使用一个数据库空间, 即db0。

5) 复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。Redis Cluster是Redis的分布式解决方案,在3.0版本正式推出,有效地解决了Redis分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的目的。之前, Redis分布式方案一般有两种:①客户端分区方案,优点是分区逻辑可控,缺点是需要自己处理数据路由、高可用、故障转移等问题。②代理方案,优点是简化客户端分布式逻辑和升级维护便利,缺点是加重架构部署复杂度和性能损耗。

现在官方为我们提供了专有的集群方案:Redis Cluster, 它非常优雅地解决了Redis集群方面的问题, 因此理解应用好Redis Cluster将极大地解放我们使用分布式Redis的工作量, 同时它也是学习分布式存储的绝佳案例。LRU(近期最少使用算法)TTL(超时算法) 去除ttl最大的键值

 

最后

答题时,先答是什么,再答有什么作用和要注意什么(这部分最重要,展现自己的心得)
答案的段落分别,层次分明,条理清晰都非常重要,从这些表面的东西也可以看出一个人的习惯、办事风格、条理等。

要讲你做出答案的思路过程,或者说你记住答案的思想都写下来。把答题想着是辩论赛。答题就是给别人讲道理、摆事实。答题不局限于什么格式和形式,就是要将自己的学识展现出来!

别因为人家题目本来就模棱两可,你就心里胆怯和没底气了,不敢回答了。你要大胆地指出对方题目很模糊和你的观点,不要把面试官想得有多高,其实他和你就是差不多的,你想想,如果他把你招进去了,你们以后就是同事了,可不是差不多的吗?

关于就业薪水,如果你是应届生,那不能要高工资,好比大饼的故事,没有文凭还想拿高工资,就去中关村缺什么补什么吧!少数人基础确实很好,在校期间确实又做过一些项目,那仍然是可以要到相对高的工资的。

 


整理了学习资料以及学习视频,送给小伙伴们。公号内回复【学习资料】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就扫码加入我们吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

靠谱的内推君

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

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

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

打赏作者

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

抵扣说明:

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

余额充值