面试中遇到的问题
- 1. 唯一索引和主键索引,哪个快?
主键快
①.主键是一种约束,唯一索引是一种索引;
②.一张表只能有一个主键,但可以创建多个唯一索引;
③.主键创建后一定包含一个唯一索引,唯一索引并一定是主键;
④.主键不能为null,唯一索引可以为null;
⑤.主键可以做为外键,唯一索引不行;
- 2. innodb和myisam储存引擎的区别
(1) 最大的不同是innodb支持事务,而myisam不支持事务
(2) MyISAM只支持表级锁,而InnoDB支持行级锁和表级锁,默认为行级锁
(3) MyISAM引擎不支持外键,InnoDB支持外键
(4) 对于count()查询来说MyISAM更有优势,因为MyISAM存储了表中的行数记录,执行SELECT COUNT() 的时候可以直接获取到结果,而InnoDB需要扫描全部数据后得到结果。
(5) InnoDB是为处理巨大数据量时的最大性能设计,它的CPU效率可能是任何其它基于磁盘的关系数据库引擎所不能匹敌的。
(6) MyISAM支持全文索引(FULLTEXT),InnoDB不支持
(7) MyISAM引擎的表的查询速度要比InnoDB高
(8) InnoDB是聚集索引,数据文件是和(主键)索引绑在一起的,即索引 + 数据 = 整个表数据文件,MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针
(据网上说现在InnoDB的查询速度也不低了,而且MyISAM会经常出现表损坏的大问题,一般用InnoDB)
- 3. hashMap的数据结构,红黑树为啥快
数据结构是数组+(单向链表(Node)表或红黑树(TreeNode)),JDK1.8之后加入了红黑树,当链表的节点数>=8的时候链表变成红黑树,使用红黑树的数据结构能够使查询的时间复杂度降低;数组的特点:查询效率高,插入,删除效率低。链表的特点:查询效率低,插入删除效率高。
- 4. 索引的类型和结构
索引的类型:主键索引,唯一索引,普通索引,组合索引(最左前缀原则),全文索引;
数据结构:
(1) B-Tree索引
(2) 哈希索引
(3) 全文索引
5. 分布式事务
两阶段提交(2PC)
两阶段提交(Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务,参与者都执行成功(但未提交事务,比如我执行完方法用一个标志位阻塞在这儿,所有参与者执行完了,把标志位修改了再向下执行,可以通过用超时时间来避免无限等待),协调者再发送消息让参与者提交事务,否则让参与者回滚。
缺点:所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作;
如果确认提交事务的通知因为网络原因只有一部分接收到,造成数据不一致
补偿事务(TCC)
其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。就是给每个参与者都写一个回滚方法,失败就调用他们的回滚方法
缺点:有可能回滚失败
本地消息表(异步确保)
大致流程是事务操作中把操作内容写入Kafka 等消息队列中(肯定会成功,不成功不执行提交事务),另一方来读取这个消息队列
MQ 事务消息
利用RocketMQ等消息中间件支持事务的特点来实现,类似二段提交,据说难度有点大
- 5. 分布式锁
(1) redis的setnx;
(2) 基于zookeeper临时有序节点可以实现的分布式锁(zookeper的客户端框架curator有获取临时节点的方法);
(3) 基于数据库实现的分布式锁
Redis的SETNX实现
过程:
1.线程1用SETNX命令,如果不存在返回1,获取到锁(用完再删除这个锁),假想线程1挂掉,为防止死锁,所以要有超时时间,那么value为超时时间,key我我们要竞争的锁
2.如果存在返回0,那么不能获取锁,说明是别人正在使用锁,一直循环get获取值并判断是否超时,如果超时,则说明使用锁的线程挂掉或者其他原因,那用getset命令,获取旧值并设置新值,如果旧值大于当前时间了,说明有并发的其他线程2也判断超时并设置了新增,则这个时候还是不能获取锁,再继续判断,直到获取成功(虽然这个时候线程是getset,从新设置了新的值,但是由于并发,设置的值和别人设置的值相差不大,基本没有影响)
缺点:
在这种场景(主从结构)中存在明显的竞态:
客户端A从master获取到锁,
在master将锁同步到slave之前,master宕掉了。
slave节点被晋级为master节点,
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。安全失效!
基于zookeeper临时有序节点实现
每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时(宕机自动清除,避免宕机死锁)有序节点,按照顺序后面的监听前面的节点,前面的处理完成了被删除了,后面的拿到锁
缺点
性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上。
其实,使用Zookeeper也有可能带来并发问题,只是并不常见而已。考虑这样的情况,由于网络抖动,客户端可ZK集群的session连接断了,那么zk以为客户端挂了,就会删除临时节点,这时候其他客户端就可以获取到分布式锁了。就可能产生并发问题。这个问题不常见是因为zk有重试机制,一旦zk集群检测不到客户端的心跳,就会重试,Curator客户端支持多种重试策略。多次重试之后还不行的话才会删除临时节点。(所以,选择一个合适的重试策略也比较重要,要在锁的粒度和并发之间找一个平衡。)
基于数据库实现
在数据库新建一个表,用要锁的方法作为主键做唯一性约束,那么同时只能由一个客户端能插入则获取锁,其余的不能插入则获取锁失败
缺点:
1、这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
2、这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
3、这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
4、这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。
解决方案:
1、数据库是单点?搞两个数据库,数据之前双向同步。一旦挂掉快速切换到备库上。
2、没有失效时间?只要做一个定时任务,每隔一定时间把数据库中的超时数据清理一遍。
3、非阻塞的?搞一个while循环,直到insert成功再返回成功。
4、非重入的?在数据库表中加个字段,记录当前获得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了。
- 6. jvm除了调整参数,还有什么调优方法
- 配置合适的堆大小和比例;
- 选择合理的回收器:串行收集器、并行收集器、并发收集器,JDK5.0以后,JVM会根据当前系统配置进行判断(如操作系统合内存大小,cpu等),使用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器;
(1) 串行收集器:
适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。
缺点:只能用于小型应用
(2) 并行收集器(指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态;对年轻代进行并行垃圾回收,因此可以减少垃圾回收时间):
适用情况:吞吐量优先,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。
缺点:应用响应时间可能较长
(3) 并发收集器(指指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替进行),用户程序在继续镜像,而垃圾收集程序运行于另一个CPU上;可以保证大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,主要减少年老代的暂停时间,就是利用多线程,用一部分线程去把不可达对象回收了,同时我们程序要用的线程自然变少了):
适用情况:相应时间优先,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。
注意:老年代一般采用标记、清除算法的并发回收器(老年大的东西很大部分在垃圾回收的时候都是存活的,所以用复制的方法会占用空间),会有内存碎片的问题,可以在参数中对老年代开启和设置多少次回收后进行碎片压缩
- 7. Jvm内存模型(JDK1.8)
主要分为:程序计数器(字节码指令noOOM),虚拟机栈(java方法SOF&OOM),本地方法栈(native方法SOF&OOM),元数据(类加载信息OOM)和堆(数组和类对象OOM).前面三个线程私有,堆中包括常量池;
程序计数器(Program Counter Register):是一块较小的内存空间,他可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。
虚拟机栈(Java Virtual Machine Stacks):描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame),用于存储局部变量、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。虚拟机栈也是线程私有的,生命周期于线程相同。
本地方法栈(Method Native Stack):与虚拟机栈的作用非常相似,区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。
堆(Java Heap):此内存区域的唯一作用就是用来存放对象实例,几乎所有的对象实例都在这里分配内存。堆是java虚拟机管理的内存中最大的一块,被所有线程共享。由于堆是垃圾收集器管理的主要区域,所以也被称为GC堆。由于现代收集器基本都采用分代收集算法,所以java堆中还可以细分为新生代,老年代。新生代又细分为Edan区、From Survivor区(S0)、To Survivor区(S1)。
元空间(Metaspace):存储已被虚拟机加载的类信息。随着JDK8的到来,JVM不再有方法区(PermGen),原方法区存储的信息被分成两部分:1、虚拟机加载的类信息,2、运行时常量池。分别被移动到了元空间和堆中
- Jvm默认的内存大小比例及调优
堆默认初始化大小为1/64内存大小,最大堆内存为1/4内存大小,受操作系统的限制(32位和64位);
老年代的大小为堆大小减去新生代大小,新生代:老年代 = 1:2;
新生代 = 1个Eden + 2个Survivor(from,to区),默认比例8:1:1;
JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K;
调优:
1.把初始化堆内存和最大堆内存设置为一样大,避免每次垃圾回收完成后JVM重新分配内存;
2可以通过调整Eden 和Survivor区的比例,但是Eden 设置太小,一直进行Minor GC(YGC),如果设置太大,会导致卡顿时间长,因为无论是YGC或是FullGC,都会导致stop-the-world,即整个程序停止一些事务的处理,只有GC进程允许以进行垃圾回收,因此如果垃圾回收时间较长,部分web或socket程序,当终端连接的时候会报connetTimeOut或readTimeOut异常,所有应该按照实际情况来设置其比例;
- 9. Jvm垃圾回收算法
常见算法有五种:
- 1. 引用计数算法(主流虚拟机不用,无法解决循环引用问题)
- 2. 标记清除算法(多用于老年代,有内存碎片问题)
- 3. 复制算法(虚拟机新生代的主要算法,新生代存活的对象少,复制较少,但是要浪费额外的内存)
- 4. 标记整理算法(又叫标记压缩算法,老年代的主要算法,是标记清除算法的优化,又进行了对象移动到一端,开销更大,但是解决了内存碎片)
- 5. 分代回收算法(现在的主流算法,不同的年代使用不同的算法)
10. redis持久化机制
持久化功能有效地避免因进程退出造成的数据丢失问题
两种持久化方式:RDB(快照,默认) 和AOF(日志)
RDB:(到一定条件更新一下快照)
rdb是Redis DataBase缩写,在指定的时间间隔内,把内存中的数据快照写入磁盘,文件名为dump.rdb,你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你可以手工调用命令SAVE或BGSAVE。
AOF:(增量记录在记录在日志中)
Aof是Append-only file缩写,以独立日志的方式记录每次写命令, 重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用 是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式
比较:
1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、rdb性能比aof好
4、如果两个都配了优先加载AOF
9. mybatis的$和#的区别
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,$将传入的数据直接显示生成在sql中,${}方式会引发SQL注入的问题,不安全,但是一般用在排序中或者表名
10. hibernate和mybatis的区别
Hibernate是全自动,而mybatis是半自动(Hibernate拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理)
hibernate数据库移植性远大于mybatis(mybatis的sql和数据库有关,耦合要强一些)
mybatis自己写sql方便、灵活,可以减少查询字段,入门低
hibernate有更好的二级缓存机制,可以使用第三方缓存,入门高
hibernate在数据量大的情况下,用的不好性能较差,还得手写SQL
- 11. 线程池高效的原理
减少了创建和销毁线程的次数,提高了响应速度,每个工作线程都可以被重复利用,可执行多个任务
12. 多线程常用类
CountDownLatch(计数功能,所有子线程执行完了减1,然后减到0的时候主线程再执行,如果要实现主线程等待子线程用join方法也可以)
CyclicBarrier(屏障功能,初始化一定数目,当子线程调用await到达到的数目,所有线程再一起执行)
ThreadLocal(为每个线程单独复制一份对象,线程间互不影响)
- 13. ConcurrentHashMap原理
线程安全且高效的HashMap实现, 其中JDK1.8抛弃了原有的segment分段锁,而采用了 CAS + synchronized 来保证并发安全性,不采用segment而采用node,锁住node来实现减小锁粒度
- 14. java1.8新特性,流用过吗,流的常用方法
主要的新特性有lambda表达式、函数式接口(一个接口有且只有一个抽象方法),Stream API流式计算(操作集合,如foreach),接口中的默认方法与静态方法,新的日期API,Optional对null的处理
- 15. 用过微服务的哪些组件
主要组件简介
Eureka,服务注册中心,有点类似zookeper;
Zuul,API服务网关
Config,分布式配置中心,支持本地仓库、SVN、Git、Jar包内配置等模式
Dashboard,Hystrix仪表盘,监控集群模式和单点模式,其中集群模式需要收集器Turbine配合
Ribbon,客户端负载均衡
Feign,声明式服务调用
Bus,消息总线
组件主要功能
Eureka和Ribbon,一个注册服务,一个消费服务。
Hystrix,为了优化Ribbon,防止整个微服务架构因为某个服务节点的问题导致崩溃,起到保险丝的作用。
Dashboard,给Hystrix统计和展示用,而且监控服务节点的整体压力和健康情况。
Turbine,集群收集器,服务于Dashboard。
Zuul,加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,加强安全保护。
Config,为了解决所有微服务各自维护各自的配置,设置一个统一的配置中心,方便修改配置。
Bus是因为config修改完配置后各个结点都要refresh才能生效实在太麻烦,所以交给bus来通知服务节点刷新配置的
- 16. http的请求流程
- DNS域名解析,把网站解析成IP;
- 到对应的服务器,发起TCP的三次握手
- 建立TCP连接后发起HTTP请求
- 服务器响应HTTP请求,浏览器得到html代码
- 浏览器解析html代码,并请求html代码中的资源(如js、css图片等)(先得到html代码,才能去找这些资源)
- 浏览器对页面进行渲染呈现给用户
- 17. http头有哪些参数
制定客户端能接受的类型,如html,json,编码集和编码类型,指定请求和响应遵循的缓存机制,Cookie,那个域名请求来的,内容长度,发送日期等
- 18. 常见的数据结构了解吗
数组(Array),栈(Stack),队列(Queue),链表(Linked List),双向链表,树(Tree),图(Graph),堆(Heap),散列表(Hash)
- 19. redis删除的时候真的删除了吗
只是先标记,定时清除
20. redis过期策略(定时随机删除过期的,其余的用到的时候再删除)
redis是采用定期删除+惰性删除策略
如果采用定时(如100ms)删除,这样会及时释放内存,但是很耗cpu,所以不能采用单一的定时删除;定时删除如果定时的循环所有key是否过期,那么会很卡,所以定时的只会循环一部分,另外一部分用惰性删除,就是下次查询的话先判断是否过期,过期了就删除了。但是这样如果过期的永远不查询呢,内存占用会越来越高?那么就应该配置内存淘汰机制来解决
内存淘汰策略:
1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。应该没人用吧。
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。不推荐
20. 开发流程是怎样的
21. 带新人遇到的一些问题
22. 遇到过解决的最大的问题
23. java有几种序列化方法
24. IOC和AOP
SimpleDateFormat线程安全吗
SimpleDateFormat线程不安全,他的format方法里面calendar是全局变量,会被别的线程修改;而parse方法实际调用的是CalenderBuilder的establish来进行解析,其方法中主要步骤不是原子操作
解决方法(算是对线程不安全对象的参照的解决方案):
- 加锁同步;
- 使用ThreadLocal来使每个线程都有自己的SimpleDateFormat对象;
- SimpleDateFormat定义为线程的局部变量;
- 使用线程安全的DateTimeFormatter来代替;
- 使用JDK8全新的日期和时间API
Aop(面向切面编程)的好处:
和业务逻辑代码进行隔离,从而使得业务逻辑各部分之间的耦合度降低,不修改源代码的情况下给程序动态统一添加功能
场景:日志记录,性能统计,安全控制,事务处理,异常处理等等
IOC(控制反转)的好处:
IOC容器管理对象间的依赖,交由Spring来管理这些,实现解耦
25. AOP的代理模式是怎么实现的,
动态代理:JDK动态代理和cglib字节码技术
如果代理对象实现了接口,spring会使用JDK代理(针对接口),但可以强制使用cglib(针对类,继承并覆写,所以不要申明为final),没有实现接口必须使用cglib库
字节码技术:
cglib字节码放在永久堆里,操作速度快,但是过多会造成内存区满,造成内存溢出所有spring默认用动态代理,没有接口采用cglib字节码)
26. 项目中用到了哪些设计模式
单例模式,工厂模式,模板方法模式(将这些相同的步骤分解、封装起来,然后利用继承的方式来继承实现),创建者模式,适配器模式(将一个接口转换为客户希望的另外一个接口),装饰模式(通过继承等来给对象添加行为),代理模式(是给一个对象提供一个代理,并由代理对象控制对原对象的引用),享元模式(共享技术对相同或者相似对象实现重用),策略模式(将这些解决问题的方法定义成一个算法群,每一个方法都对应着一个具体的算法,这里的一个算法我就称之为一个策略。)
27. 多线程高并发
28. Jvm调优
29. 线程池
CUP密集型
大部分用在计算上面,避免线程上下文切换,消耗资源,故核心线程数配低一点
IO密集型
大部分用在读取上面,避免所有线程都在阻塞,故核心线程数配高一点
30. 常见的集合的数据结构,如hashMap,ArrayList等
hashMap是数据加链表(JDK1.8当链表长度超过8就变成了红黑树),默认数组大小为16.默认扩展因子为0.75;
因为数组存储区间是连续的,占用内存严重,故空间复杂度很大,但查找快,链表储存区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,数组的特点是:寻址容易,插入,寻址困难,链表的特点是:寻址困难,插入和删除容易,HashMap综合了两者的特性。
31. 锁(Cas,AQS)
说说锁升级的过程
锁的4中状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高)
32. Linux
33. 数据库常见的优化方法
Nginx为什么快
34. Redis的zset结构
Zset是string类型元素的集合,且不允许重复的成员,关联了一个double类型的分数,zset的成员是唯一的,但是分数可以重复;数据结构是跳表
35. Redis分布式锁是怎么实现的
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放
36. 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,如id为-1,攻击导致去查询数据库,数据库压力过大
避免
- 前端校验,如id<0直接返回
- 第一次查询出来不存在的缓存起来,value为null
缓存雪崩
当服务器重启或者同一时间大量key过期,大量的查询引起数据库压力过大甚至宕机
避免
- 缓存的数据过期时间随机,防止同一时间大量过期
- 设置热点数据永远不过期
- 二级缓存,a1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
Redis同步机制
怎么保证redis和mysql数据一致性
多线程
锁
悲观锁:每次执行都加上排他锁,别人不能执行
乐观锁(CAS:比较交换,避免死锁,不竞争锁所以轻量级,性能高些,但是逻辑复杂一些)
排他锁
重入锁(也叫递归锁)
自旋锁:让当前线程在循环中不停的执行,直到其他线程打破循环条件
Synchronized
在一般方法上是锁的this,在静态方法上是锁当前类的字节码文件
ThreadLocal
ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
实现原理一个map集合,线程作作为key,value就是对象, Map.put(“当前线程”,值);
它的public void remove()方法是1.5增加的,移除当前线程的变量,显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度
多线程三大特征
原子性、可见性、有序性
强引用、弱引用、软引用和虚引用
引用类型 被垃圾回收时间 用途 生存时间
强引用 从来不会 对象的一般状态 JVM停止运行时终止
软引用 当内存不足时 对象缓存 内存不足时终止
弱引用 正常垃圾回收时 对象缓存 垃圾回收后终止
虚引用 正常垃圾回收时 跟踪对象的垃圾回收 垃圾回收后终止
BIO和NIO的区别
Synchronized用在service方法里面会影响事务吗?
会,事务是spring的AOP中执行的,当AOP中service方法执行完了,但是事务还没有提交(事务没有保证整个事务方法的原子性)
Linux
怎么删除文件夹下全部文件
怎么查看后面20行数据
怎么查看端口被那个进程占用
Jvm
垃圾回收算法
JDK1.8的Jvm内存区域划分
字符串常量池是存放在哪儿的?
1.8之后存在堆里面的,1.8之前是存在方法区里面
数据库
数据库
怎么执行计划查询
EXPLAIN +sql
高并发
高并发优化方案案例
流量优化:防盗链处理(别人请求我们网站的图片,可用请求头的referer或签名判断)
前端优化:减少HTTP请求,合并css或js,添加异步请求,启用浏览器缓存和文件压缩,CDN加速,建立独立图片服务器,
服务端优化:页面静态化,并发处理,队列处理,异步
数据库优化:数据库缓存,分库分表,分区操作,读写分离,负载均衡
web服务器优化:负载均衡,nginx反向代理,7,4层LVS软件
高并发解决思路
1.应用系统拆分/集群(搭建分布式)
2.缓存(redis等)
3.异步(消息中间件)
4.数据库层的分库分表/读写分离/集群
5.硬件提升
工作中提高效率的工具
- 阿里的开发手册,开发规范
- 代码检视插件,eclipse的code Review,idea的阿里代码检视插件
- postMan调试接口
- Jmeter调试并发
- 夜神模拟器调试app
- Jdk自带的工具调试jvm,jmap,jhat等命令
- Gui反编译class代码
CEO
为什么离职
你的职业规划(看是否和公司相符)
深圳公司离职原因
你有什么想问我的
工作的意义是什么
怎么带团队的
你的优缺点