1. MySQL 分库分表
为什么要分表:当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。
单库单表:单库单表是最常见的数据库设计,例如,有一张用户(user)表放在数据库db中,所有的用户都可以在db库中的user表中查到。
单库多表:随着用户数量的增加,user表的数据量会越来越大,当数据量达到一定程度的时候对user表的查询会渐渐的变慢,从而影响整个DB的性能。如果使用mysql, 还有一个更严重的问题是,当需要添加一列的时候,mysql会锁表,期间所有的读写操作只能等待。
可以通过某种方式将user进行水平的切分,产生两个表结构完全一样的user_0000,user_0001等表,user_0000 + user_0001 + …的数据刚好是一份完整的数据。
多库多表:随着数据量增加也许单台DB的存储空间不够,随着查询量的增加单台数据库服务器已经没办法支撑。这个时候可以再对数据库进行水平区分。
分库分表规则:设计表的时候需要确定此表按照什么样的规则进行分库分表。例如,当有新用户时,程序得确定将此用户信息添加到哪个表中;同理,当登录的时候我们得通过用户的账号找到数据库中对应的记录,所有的这些都需要按照某一规则进行。
路由:通过分库分表规则查找到对应的表和库的过程。如分库分表的规则是user_id mod 4的方式,当用户新注册了一个账号,账号id的123,我们可以通过id mod 4的方式确定此账号应该保存到User_0003表中。当用户123登录的时候,我们通过123 mod 4后确定记录在User_0003中。
CV于 MySQL 分库分表
水平分库、水平分表、垂直分库、垂直分表
知乎MySQL 分库分表
水平分库分表切分规则:RANGE、MOD、地理区域、时间、HASH取模
某博客园
2. Set(集)、Map(映射)、List(列表)三种集合的差别
CV于集合的详解
List:继承Collection接口,定义了一个允许重复项的有序集合。
Set:继承Collection接口,是无序的,而且不允许集合中存在重复元素。因为Set接口提供的数据结构是数学意义上的集合概念的抽象,因此他支持对象的添加和删除。
Map:Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。
3.MQ(Message Queue)消息队列
ActiveMQ:Apache出品,完全支持JMS规范,API丰富;性能有瓶颈,吞吐量不高。
Kafka:Apache顶级项目,高吞吐量;不支持事务,对消息的重复、丢失没有严格要求
RocketMQ:阿里,Kafka的升级版;收费
RabbitMQ:基于AMQP协议协议实现,可以与springboot框架无缝对接,对数据的一致性要求非常严格;性能略输于Kafka
4.Java中==和equal有什么区别
== 表示对内存地址进行比较,表示引用是否相同。
equals()表示对字符串的内容进行比较,表示值是否相同。
5.堆栈区别
- 申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
- 申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
- 申请效率的不同。栈速度较快,而堆一般速度比较慢;
- 存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
- 底层不同。栈是连续的空间,而堆是不连续的空间。
堆和栈的区别可以引用一位前辈的比喻来看:
使用栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
class A{
private String a = "aa";
public boolean methodB() {
String b = "bb";
final String c ="ccc";
}
}
a在堆中存放 bc在栈内存放。
a属于类所以在堆中。bc属于方法,b c为局部变量,局部变量不属于任何类或者实例,因此它总是保存在其所在方法的栈内存中!
6.继承 封装 多态
7.redis数据类型 redis的部署方式
1.string 字符串(可以为整形、浮点型和字符串,统称为元素)
2.list 列表(实现队列,元素不唯一,先入先出原则)
3.set 集合(各不相同的元素)
4.hash hash散列值(hash的key必须是唯一的)
5.sort set 有序集合
8.java八大基本数据类型及其封装类
Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。JAVA中的数值类型不存在无符号的,它们的取值范围是固定的,不会随着机器硬件环境或者操作系统的改变而改变。实际上,JAVA中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。8 中类型表示范围如下:
byte: 8位,最大存储数据量是255,存放的数据范围是-128~127之间。
short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。
int: 32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
long: 64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
float: 32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有true和false两个取值。
char:16位,存储Unicode码,用单引号赋值。
Java决定了每种简单类型的大小。这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。下表列出了Java中定义的简单类型、占用二进制位数及对应的封装器类。
9.string stringbuffer stringbuilder区别
1.在字符串不经常发生变化的业务场景优先使用String(代码更清晰简洁)。如常量的声明,少量的字符串操作(拼接,删除等)。
2.在单线程情况下,如有大量的字符串操作情况,应该使用StringBuilder来操作字符串。不能使用String"+"来拼接而是使用,避免产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。如JSON的封装等。
3.在多线程情况下,如有大量的字符串操作情况,应该使用StringBuffer。如HTTP参数解析和封装等。
10.sql调优
11.map的扩容
HashMap扩容和ArrayList的扩容源码
HashMap和ArrayList扩容倍数
12.数据库加锁方式
13.Mysql隔离事务级别
mysql事务隔离级别案例讲解
事务隔离级别的选择
图形展示
14.数据库索引
普通索引 唯一索引 主键索引 组合索引
数据库的索引
组合索引的失效场景
15.左连接 右连接
16.mybatis-plus插件保存后如何返回数据id
会直接赋值给入参,故可直接操作入参。
17.线程守护方式!! 多线程!!
多线程详解+四种实现方式+ 守护线程+优先级+死锁+案例
Java四种多线程实现方式以及守护线程
18.垃圾回收机制
JVM的4种垃圾回收算法、垃圾回收机制与总结
java面试之简述一下 Java 垃圾回收机制?
深入理解 JVM 垃圾回收机制及其实现原理
19.JRE、JDK、JVM 之间的区别与联系
JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。
JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
显然,这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。
20.使用递归调用时需要注意的问题
1.若递归方法中存在循环,循环中反复调用递归方法时,必须注意其循环外定义的变量,每次循环都会初始为定义的变量,所以为了动态生成其外变量,一般为循环的返回值。
2.递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出.跳出递归方法的位置一般放在循环的最开始
3.在递归中虽然有限定条件,但是递归次数不能太多,否则也会发生栈内存溢出
4.构造方法,禁止递归
21.http协议相关
22.PageHelper实现原理
总结:PageHelper分页的实现是在我们执行SQL语句之前动态的将SQL语句拼接了分页的语句,从而实现了从数据库中分页获取的过程。
23.MyBatis中# $的区别
1、$字符串拼接,# 参数站位相当于jdbc中的 ?号
2、$不能够防止sql注入,#可以防止sql注入的
3、$可以替换sql语句任何一个内容,#只能替换参数
4、$如果操作字符串,需要在sql中使用单引号。 #不需要(不需要判断数据类型,会自动转换)($要考虑参类型 ,#不用考虑参数类型)
总结:
#{} 解析的是占位符?可以防止SQL注入, 打印出来的语句 select * from table where id= ?
然而${} 作为字符串拼接来用,则是不能防止SQL注入打印出来的语句 select * from table where id=2 实实在在的参数 (sql注入:通过字符串拼接达到串改sql语句的目地)
24.取yml里的数
@Value("#{'${eureka.server.allowed.address}'}")
private String[] allowedAddress1;
@Value("#{'${eureka.server.allowed.address}'.split(',')}")
private List nameList1;
--------yml格式配置文件------------
test:
application:
properties:
list1: aaa,bbb,ccc
25.linux 软连接 硬链接
Linux:软连接和硬链接其他须知
【硬连接】(Hard Link)硬连接指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(Inode Index)。在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,因为对应该目录的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。
【软连接】另外一种连接称之为符号连接(Symbolic Link),也叫软连接。软连接实际上是通过名字引用另外一个文件,软连接和目标文件有着不同的inode号,说明软连接是一个独立的文件。可以理解为软连接存放的是目标文件的路径,包括目标文件的名称。
软连接我们可以想象成是windos系统下的快捷方式,可以快速访问目标文件。
通过实验加深理解
[oracle@Linux]$ touch f1 #创建一个测试文件f1
[oracle@Linux]$ ln f1 f2 #创建f1的一个硬连接文件f2
[oracle@Linux]$ ln -s f1 f3 #创建f1的一个符号连接文件f3
[oracle@Linux]$ ls -li # -i参数显示文件的inode节点信息
total 0
9797648 -rw-r–r-- 2 oracle oinstall 0 Apr 21 08:11 f1
9797648 -rw-r–r-- 2 oracle oinstall 0 Apr 21 08:11 f2
9797649 lrwxrwxrwx 1 oracle oinstall 2 Apr 21 08:11 f3 -> f1
从上面的结果中可以看出,硬连接文件f2与原文件f1的inode节点相同,均为9797648,然而符号连接文件的inode节点不同。
[oracle@Linux]$ echo “I am f1 file” >>f1
[oracle@Linux]$ cat f1
I am f1 file
[oracle@Linux]$ cat f2
I am f1 file
[oracle@Linux]$ cat f3
I am f1 file
[oracle@Linux]$ rm -f f1
[oracle@Linux]$ cat f2
I am f1 file
[oracle@Linux]$ cat f3
cat: f3: No such file or directory
通过上面的测试可以看出:当删除原始文件f1后,硬连接f2不受影响,但是符号连接f1文件无效。
总结
1).删除符号连接f3,对f1,f2无影响;
2).删除硬连接f2,对f1,f3也无影响;
3).删除原文件f1,对硬连接f2没有影响,导致符号连接f3失效;
4).同时删除原文件f1,硬连接f2,整个文件会真正的被删除。
26.Linux下/bin和/sbin的区别
简单归纳:
/bin目录(binary)是二进制执行文件目录,主要用于具体应用
/sbin目录(system binary)是系统管理员专用的二进制代码存放目录,主要用于系统管理
/bin,/sbin,/usr/bin,/usr/sbin区别
/ : this is root directory root 用户根目录
/bin : commandsin this dir are all system installed user commands 系统的一些指令
/sbin: commands in this dir are all system installedsuper user commands 超级用户指令系统管理命令,这里存放的是系统管理员使用的管理程序
/usr/bin: usercommands for applications 后期安装的一些软件的运行脚本
/usr/sbin:super user commands for applications 超级用户的一些管理程序
/usr/X11R6/bin: X application user commands
/usr/X11R6/sbin: X application super usercommands
Linux中的某些重要的目录:
•主目录:/root、/home/username
•用户可执行文件:/bin、/usr/bin、/usr/local/bin
•系统可执行文件:/sbin、/usr/sbin、/usr/local/sbin
•其他挂载点:/media、/mnt
•配置:/etc
•临时文件:/tmp
•内核和Bootloader:/boot
•服务器数据:/var、/srv
•系统信息:/proc、/sys
•共享库:/lib、/usr/lib、/usr/local/lib
每个用户都拥有一个主目录。所有用户的个人文件(配置、数据甚至应用程序)都放在其中。根的主目录为/root。大多数非根主目录包含在/home 树中,通常以用户命名。重要的二进制位于 /bin(用户二进制)以及 /sbin(系统二进制)中。不重要的二进制(如图形环境或Office 工具)安装在/usr/bin 和 /usr/sbin中。进行这种分隔是为了尽可能地缩小根分区。使用源代码编译的软件通常位于 /usr/local/bin 和/usr/local/sbin中。
27.设计模式
28.线程安全的集合
Vector
Vector集合是对ArrayList集合线程安全的实现,它们两者在方法的实现上没有什么太大的区别,最大的区别就是,Vector在方法前面加上了synchronized关键字,用于保证线程安全。
Vector存在的问题:
1、它的add()和get()方法都能够获取当前Vector对象的对象锁,但是有可能会发生读读互斥。
2、当threadA在1下标处添加一个元素,threadB在2下标处修改一个元素时,同样有可能会发生互斥现象
因此,我们可以看出Vector所存在的锁的粒度是非常大的,这也就会导致在多线程情况下,程序执行的效率有可能会十分低下。
HashTable
HashTable集合是对HashMap集合线程安全的实现,它们两者在方法的实现上没有什么太大的区别,最大的区别就是,HashTable在方法前面加上了synchronized关键字,用于保证线程安全。
HashTable存在的问题:
由于HashTable和Vector在本质上都是在方法前面加上synchronized关键字,因此,它们两个存在的问题也是同样相同的,均有可能发生互斥现象。
由此可知,HashTable所存在的锁的粒度也是非常大的,也同样会导致在多线程情况下,程序执行的效率有可能会十分低下。
为了解决Vector集合和HashTable集合效率低下的问题,我们在选取线程安全的集合时一般会选择CopyOnWriteArrayList集合和ConcurrentHashMap集合,它的锁的粒度相较于Vector和HashTable更小,因此能够高效率的解决Vector和HashTable所存在的问题。
29.springboot的优点,如何管理依赖的
1.快速进行开发和部署
2.内嵌Tomcat,可直接启动
3.提供了大量的自动配置,约定优于配置
30.数据回滚时,MySQL数据库的操作
31.java对数据库事务的调用
void reject(@Param("costId")Integer costId,@Param("userId") Integer userId,@Param("auditComment") String auditComment);
<select id="reject" statementType="CALLABLE" >
{call resettingBill
(
#{costId,mode=IN},
#{userId,mode=IN},
#{auditComment,mode=IN}
)
}
</select>
32.AOP的具体用法及注解执行顺序
aop注解执行顺序
结论
1.在一个方法只被一个aspect类拦截时,aspect类内部的 advice 将按照以下的顺序进行执行:around.pjp.proceed()前半部分->before->方法->around.pjp.proceed()后半部分(上一步方法抛错,不执行此步)->After->AfterReturning(AfterThrowing)
2.在一个方法被多个aspect类拦截时,@Order是值越小的 aspect 越先执行。
33.如何查MySQL的各种语句执行用时
34.事务的四大特征
ACID,原子性(Atomicity)、一致性(Correspondence)、隔离
性(Isolation)、持久性(Durability)
事务及事务的四大特征
35.redis和数据库的一致性问题的解决方案
先删除缓存,再更新数据库,在查询时,发现缓存已经不存在,去数据库查询之后,同步到redis缓存。
redis和数据库的一致性问题的解决方案
36.依赖注入和控制反转
依赖注入和控制反转含义相同,它们是从两个角度描述的同一个概念。
当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的实例,而使用 Spring 框架后,被调用者的实例不再由调用者创建,而是由 Spring 容器创建,这称为控制反转。
Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入。
依赖注入与控制反转
37.ArrayList与LinkList对比
1.ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
2.对于随机访问元素,Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很大的,因为这需要重排数组中的所有数据。ArrayList想要get(int index)元素时,直接返回index位置上的元素,而LinkedList需要通过for循环进行查找,虽然LinkedList已经在查找方法上做了优化,比如index < size / 2,则从左边开始查找,反之从右边开始查找,但是还是比ArrayList要慢。
3.对于添加和删除操作add和remove,LinkedList是更快的。
ArrayList与LinkList对比
38.主从库相关
1、读写分离,缓解数据库压力(主数据库用于数据写入,数据库用于数据读取),提高性能瓶颈。
2、一主多从,系统可扩展性和可用性高。
3、数据备份容灾,异地双活,保证主库异常随时切换,提高系统容错能力。
主从库搭建