面试集锦

栏目: 数据库 · Mysql · 发布时间: 6年前

内容简介:1、浏览器层或者APP层限制同一个用户或者IP的操作每x秒只能执行一次2、浏览器或者APP做页面缓存,3、图片和短信验证码的验证也能有效的限流
  • https://blog.csdn.net/sinat_27143551/article/details/80216842
  • https://www.cnblogs.com/li1992/articles/9217391.html
  • 第一范式: 要求数据库中的每个字段都是不可再分的(原子性),比如地址这个字段可以拆分成省份、城市等字段,不满足第一范式
  • 第二范式:
    • 满足第一范式
    • 所有的非主属性都必须 完全依赖(如果主键是两个字段,必须依赖这两个字段,不能部分依赖) 于主键
  • 第三范式:
    • 满足第二范式(即是同时满足第一范式和第二范式)
    • 属性不依赖于其他非主属性
    • 例如:存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。

mysql性能优化(索引,分库分表,升级硬盘SSD,主从部署,读写分离)

硬件优化

  • 升级内存,带宽等
  • 提升读写速度

索引优化

全值匹配

最佳左前缀,并且不能组合索引的中间字段

不要在索引列上做任何的操作(函数,计算等)

使用覆盖索引,少使用select *

mysql在使用不等于(!=或者<>)的时候无法使用导致全表扫描

在使用or的时候,前后两个都是索引的时候才会生效

is null和is not null 导致索引失效

like使用%开头的将会导致索引失效

字符串不加单引号导致索引失效

索引的优缺点

  • 优点:
    • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
    • 大大加快查询的速度
  • 缺点:
    • 创建索引和维护索引要耗费时间,这种时间随着数据 量的增加而增加。
    • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
    • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

开启查询缓存

分库分表

重构查询方式

  • 一个复杂查询能够解决就不要使用多个简单的查询
  • 切分查询,将一个大的查询方式切分成多个小的查询,比如删除数据,可以尽可能的多次删除
  • 分解关联查询:将关联查询分解成多个子查询,利用查询缓存

使用冗余的字段避免多表联合查询

禁用外键关联

事务的ACID

  • 原子性: 一个事务中的所有操作要么同时完成要么同时失败
  • 一致性: 无论事务是否执行成功,必须保证一个一致性的标准,比如转账,必须保证转账前后的总金额不变
  • 隔离性: 事务与事务之间互不影响
  • 持久性: 事务执行完成之后数据将会持久的保存到数据库中

事务的隔离级别

  • READ UNCOMMITTED(未提交读) :在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为 脏读 (Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。
  • READ COMMITTED(提交读) :大多数数据库系统的默认隔离级别都是READ COMMITTED(但 MySQL 不是)。READ COMMITTED满足前面提到的隔离性的 简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读(nonrepeatable read),因为两次执行同样的查询,可能会得到不一样的结果。
  • REPEATABLE READ(可重复读) :REPEATABLE READ解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个 幻读 (Phantom Read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。本章稍后会做进一步的讨论。 可重复读是MySQL的默认事务隔离级别。
  • SERIALIZABLE(可串行化) :SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

视图

Mysql中的锁

Mysql中的explain的各个属性

算法

算法的稳定性

排序算法的稳定性

排序算法

public static void main(String[] args)throws CloneNotSupportedException {
		int[] arrays= {1,3,2,7,5};
		insertSort(arrays);
		for (Integer a : arrays) {
			System.out.print(a+"\t");
		}
	}

	/**
	 * 冒泡排序
	 * @param arrays
	 */
	public static void bubbleSort(int[] arrays){
		// 外层循环
		for (int i = 0; i < arrays.length - 1; i++) {
			for (int j = arrays.length - 1; j > i; j--) {
				if (arrays[j] < arrays[j - 1]) {
					int c = arrays[j];
					arrays[j] = arrays[j - 1];
					arrays[j - 1] = c;
				}
			}
		}
	}
	
	
	/**
	 * 选择排序
	 * 1、先假设第一个元素是最小的,依次和后面的元素比较,第一轮之后,第一个元素就是最小的,依次经过n轮之后,前n个元素是有序的(由小到大排序)
	 * @param arrays
	 */
	public static void changeSort(int[] arrays){
		for (int i = 0; i < arrays.length-1; i++) {
			int minIndex=i;  //假设第一个元素是最小的
			for(int j=i+1;j<arrays.length;j++) {
				if (arrays[minIndex]>arrays[j]) {
					minIndex=j;
				}
			}
			
			//经过一轮之后,minIndex的值改变了,那么表示出之前定的最小值改变了,此时就需要交换
			if (minIndex!=i) { 
				int c = arrays[minIndex];
				arrays[minIndex] = arrays[i];
				arrays[i] = c;
			}
		}
	}
	
	/**
	 * 插入排序
	 * @param arrays
	 */
	public static void insertSort(int[] arrays){
		//从第二个开始,假设第一个已经是排好序的
		for (int i = 1; i < arrays.length; i++) {
			int target=arrays[i];  //待插入的
			int j=i;
			
			//如果待插入的数字比前面的数字(已经是有序的)小,那么前面的元素就后移,等待这个元素插入
			while(j>0&⌖<arrays[j-1]) {
				arrays[j]=arrays[j-1];
				j--;
			}
			
			//移动完之后,当前的j的位置就是待插入的
			arrays[j]=target;
		}
	}

二分查找算法

二叉树相关概念

  • 二叉树
    • 每个节点最多有两个子树的结构,通常子树被称作“左子树”和“右子树” 。
  • 满二叉树
  • 完全二叉树
  • 二叉查找树
    • 满足二叉树的定义
    • 每个节点的键都大于左子树中任意节点的键而小于右子树中任意节点的键。
  • 平衡二叉树
    • 满足二叉查找树的定义
    • 树的左右两边的层级数相差不会大于1;
  • 红黑树
    • https://www.cnblogs.com/skywang12345/p/3245399.html
    • 特点:
      • 根节点是黑色的
      • 叶子节点必须是黑色的
      • 节点的颜色要么是黑色,要么是红色
      • 如果一个节点是红色的,则它的子节点必须是黑色的。
      • 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

并发编程

定义

  1. 线程:是进程的一个实体,是cpu调度和分派的基本单位,是比进程更小的可以独立运行的基本单位。
  2. 进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独 立单位。

其他

如何确保高并发安全性

1、浏览器层或者APP层限制同一个用户或者IP的操作每x秒只能执行一次

2、浏览器或者APP做页面缓存,

3、图片和短信验证码的验证也能有效的限流

4、服务器层的限流,比如令牌桶算法,保证每秒限制多少个请求

5、数据的缓存,可以将一些热点数据存放到 redis 中,防止击穿db层

6、使用消息队列,既能保证任务的异步执行,也能达到限流的作用。

7、数据库层比如读写分离,分库分表等都能实现一定的优化。

8、服务器做负载均衡,使用分布式

消息队列

  • 路由,路由键(routineKey),队列
  • rabbitMq的四种路由:direct,fanout,topic,header
  • https://segmentfault.com/a/1190000015301449?utm_source=tag-newest
  • 消息队列的优势:解耦、异步、流量削峰
  • 消息队列的缺点
    • 系统的复杂性提高
    • 系统的可用性降低,一旦消息队列挂掉,系统也会随之瘫痪
  • 消息队列的使用场景?
  • 如何保证消息可靠性投递?

    • 生产者丢弄丢数据:只需要在生产者的开启事务,一旦消息投递失败,事务回滚即可,另外一种模式是confirm模式,一种异步的处理模式,一旦消息被成功投递到队列之后会异步发送一个ACK的消息,否则发送一个NACK的消息
    • 消息队列弄丢数据:开启消息队列持久化和消息确认机制,可以在消息持久化之后发送一个ACK消息给生产者,如果持久化之前没有接收到
    • 消费者弄丢数据:采用自动确认的模式即可,如果消费者成功消费了数据,那么发送一个ACK消息,否则发送一个NACK消息
  • 如何保证消息的顺序性
  • 如何保证消息不被重复消费?

    • 开启自动确认机制,一旦消息被成功消费,那么就发送一个ACK消息,否则发送一个NACK
  • 如何保证消息的高可用?

Tomcat性能调优

JDK

HashMap

  • HashMap的底层原理
  • 初始大小为16,负载因子默认为0.75,也就是如果元素个数大于16*0.75=12,那么将会扩容(resize)一倍(32),扩容的过程是非常消耗性能,因此如果清楚知道元素的个数,那么需要创建的时候就指定,避免中途扩容。
  • JDK1.7是使用位桶(数组)+链表的方式实现的
    • 面试集锦
    • 添加元素
      • 通过计算key的hash值找到在数组中的位置,如果此时数组位置为空,直接添加一个元素(Entry)
      • 如果此时数组的位置不为空,通过的equals方法查找当前链表中是否有相同的,如果没有,直接插入到链表的末尾,否则覆盖之前的元素。
    • get
      • 通过计算key的hash值找到数组中的位置
      • 通过key的equals方法在链表中查找和当前key的相等的,如果存在返回这个Entry即可。
    • 问题:
      • 链表的查询很慢,如果有成千上万个元素,那么此时的性能很低。
  • JDK1.8使用的是位桶+链表+红黑树,当 位桶中的链表元素 的个数超过阀值8,那个链表将会转换为红黑树。
    • 链表的时候和JDK1.7是一致的,如果是红黑树,那么就是红黑树的遍历

数组和链表的区别

  • 数组:
    • 初始化需要指定大小
    • 查询性能高
    • 添加、删除需要前后移动元素,性能低
  • 链表:
    • 动态增长,不需要提前指定个数
    • 查询性能较低
    • 添加、删除、修改性能较高

ArrayList

类加载器

  • https://www.cnblogs.com/gdpuzxs/p/7044963.html

  • 类加载器的类型?

    • 根类加载器(Bootstrap) –C++写的 ,看不到源码 (BootStrapClassLoader)
    • 扩展类加载器(Extension) –加载位置 : jre\lib\ext 中 (ExtStrapClassLoader)
    • 系统(应用)类加载器(System\App) –加载位置 : classpath 中 (AppClassLoader)
    • 自定义加载器(必须继承 ClassLoader)
  • 双亲委派机制
  • 自定义类加载器,继承ClassLoader

HTTP

网络七层协议

TCP和UDP

三次握手

四次挥手

长连接

Spring

Spring中的BeanFactory和FactoryBean的区别

FactoryBean的作用

  • https://www.cnblogs.com/davidwang456/p/3688250.html
  • 一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean 。在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在 中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.Springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。FactoryBean接口对于Spring框架来说占有重要的地位,Spring 自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。从Spring 3.0 开始, FactoryBean开始支持泛型,即接口声明改为FactoryBean
/**
 * 创建一个UserFactoryBean,实现FactoryBean,用来创建一个User对象
 * InitializingBean:初始化
 * ApplicationContextAware:设置ApplicationContext
 */
@Component
public class UserFactoryBeanimplements FactoryBean<User>,InitializingBean,ApplicationContextAware{

    //User对象
    private User user;
    //ApplicationContext对象,可以获取指定的Bean
    private ApplicationContext applicationContext;

    /**
     * 返回一个User
     */
    @Override
    public User getObject()throws Exception {
        return user;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public void afterPropertiesSet()throws Exception {
        user=new User();
        user.setName("陈加兵");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.applicationContext=applicationContext;
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro Git

Pro Git

Scott Chacon / Apress / 2009-8-27 / USD 34.99

Git is the version control system developed by Linus Torvalds for Linux kernel development. It took the open source world by storm since its inception in 2005, and is used by small development shops a......一起来看看 《Pro Git》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具