java虚拟机
何时会触发full gcjava
- System.gc()方法的调用
- 老年代空间不足
- 永生区空间不足(JVM规范中运行时数据区域中的方法区,在HotSpot虚拟机中又被习惯称为永生代或者永生区,Permanet Generation中存放的为一些class的信息、常量、静态变量等数据)
- GC时出现promotion failed和concurrent mode failure
- 统计获得的Minor GC晋升到旧生代平均大小大于老年代剩余空间
- 堆中分配很大的对象
能够做为root的对象:mysql
- 类中的静态变量,当它持有一个指向一个对象的引用时,它就做为root
- 活动着的线程,能够做为root
- 一个Java方法的参数或者该方法中的局部变量,这两种对象能够做为root
- JNI方法中的局部变量或者参数,这两种对象能够做为root
例子:下述的Something和Apple均可以做为root对象。面试
Java方法的参数和方法中的局部变量,能够做为root.redis
新生代转移到老年代的触发条件算法
- 长期存活的对象
- 大对象直接进入老年代
- minor gc后,survivor仍然放不下
- 动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代
redis
redis单线程问题sql
单线程指的是网络请求模块使用了一个线程(因此不需考虑并发安全性),即一个线程处理全部网络请求,其余模块仍用了多个线程。数据库
为何说redis可以快速执行缓存
- 绝大部分请求是纯粹的内存操做(很是快速)
- 采用单线程,避免了没必要要的上下文切换和竞争条件
- 非阻塞IO - IO多路复用
redis的内部实现安全
内部实现采用epoll,采用了epoll+本身实现的简单的事件框架。epoll中的读、写、关闭、链接都转化成了事件,而后利用epoll的多路复用特性,毫不在io上浪费一点时间 这3个条件不是相互独立的,特别是第一条,若是请求都是耗时的,采用单线程吞吐量及性能可想而知了。应该说redis为特殊的场景选择了合适的技术方案。网络
Redis关于线程安全问题
redis其实是采用了线程封闭的观念,把任务封闭在一个线程,天然避免了线程安全问题,不过对于须要依赖多个redis操做的复合操做来讲,依然须要锁,并且有多是分布式锁。
使用redis有哪些好处?
- 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间复杂度都是O(1)
- 支持丰富数据类型,支持string,list,set,sorted set,hash
- 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不执行
- 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除
redis相比memcached有哪些优点?
- memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型
- redis的速度比memcached快不少
- redis能够持久化其数据
数据库
B树和B+树的区别
- B树,每一个节点都存储key和data,全部节点组成这棵树,而且叶子节点指针为nul,叶子结点不包含任何关键字信息。
-
- B+树,全部的叶子结点中包含了所有关键字的信息,及指向含有这些关键字记录的指针,且叶子结点自己依关键字的大小自小而大的顺序连接,全部的非终端结点能够当作是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含须要查找的有效信息)
为何说B+比B树更适合实际应用中操做系统的文件索引和数据库索引?
- B+的磁盘读写代价更低 B+的内部结点并无指向关键字具体信息的指针。所以其内部结点相对B树更小。若是把全部同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来讲IO读写次数也就下降了。
- B+-tree的查询效率更加稳定 因为非终结点并非最终指向文件内容的结点,而只是叶子结点中关键字的索引。因此任何关键字的查找必须走一条从根结点到叶子结点的路。全部关键字查询的路径长度相同,致使每个数据的查询效率至关。
为何使用数据索引能提升效率
- 数据索引的存储是有序的
- 在有序的状况下,经过索引查询一个数据是无需遍历索引记录的
- 极端状况下,数据索引的查询效率为二分法查询效率,趋近于 log2(N)
mysql联合索引
- 联合索引是两个或更多个列上的索引。对于联合索引:Mysql从左到右的使用索引中的字段,一个查询能够只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 能够支持a 、 a,b 、 a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。
- 利用索引中的附加列,您能够缩小搜索的范围,但使用一个具备两列的索引 不一样于使用两个单独的索引。复合索引的结构与电话簿相似,人名由姓和名构成,电话簿首先按姓氏对进行排序,而后按名字对有相同姓氏的人进行排序。若是您知 道姓,电话簿将很是有用;若是您知道姓和名,电话簿则更为有用,但若是您只知道名不姓,电话簿将没有用处。
什么状况下应不建或少建索引
- 表记录太少
- 常常插入、删除、修改的表
- 数据重复且分布平均的表字段,假如一个表有10万行记录,有一个字段A只有T和F两种值,且每一个值的分布几率大约为50%,那么对这种表A字段建索引通常不会提升数据库的查询速度。
- 常常和主字段一块查询但主字段索引值比较多的表字段
为何要分区?
- 咱们都知道mysql数据库的数据以文件的形式存储在磁盘,默认是放在/mysql/data下面,一张表对应着三个文件,一个是frm存放表结构,一个是myd存放表数据的,一个是myi存表索引的。
- 假设有一张表的数据量很是大,那么myd,myi就会变得很大,查找数据就会变得很慢,那么咱们的解决方法是什么?就是分区,在物理上将这一张表对应的三个文件,分割成许多个小块,而后咱们查找一条数据时,就不用所有查找了,只需知道这条数据在哪一块,而后在那一块找就行,若是表的数据太大,一个磁盘也放不下,咱们能够把数据分配到不一样的磁盘里面
四种隔离级别
- Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
- Repeatable read (可重复读):可避免脏读、不可重复读的发生。
- Read committed (读已提交):可避免脏读的发生。
- Read uncommitted (读未提交):最低级别,任何状况都没法保证。
行级锁定的优势:
- 当在许多线程中访问不一样的行时只存在少许锁定冲突。
- 回滚时只有少许的更改
- 能够长时间锁定单一的行。
行级锁定的缺点:
- 比页级或表级锁定占用更多的内存。
- 当在表的大部分中使用时,比页级或表级锁定速度慢,由于你必须获取更多的锁。
- 若是你在大部分数据上常常进行GROUP BY操做或者必须常常扫描整个表,比其它锁定明显慢不少。
- 用高级别锁定,经过支持不一样的类型锁定,你也能够很容易地调节应用程序,由于其锁成本小于行级锁定。
MySQL 触发器简单实例
- CREATE TRIGGER <触发器名称> --触发器必须有名字,最多64个字符,可能后面会附有分隔符.它和MySQL中其余对象的命名方式基本相象.
- { BEFORE | AFTER } --触发器有执行的时间设置:能够设置为事件发生前或后。
- { INSERT | UPDATE | DELETE } --一样也能设定触发的事件:它们能够在执行insert、update或delete的过程当中触发。
- ON <表名称> --触发器是属于某一个表的:当在这个表上执行插入、 更新或删除操做的时候就致使触发器的激活. 咱们不能给同一张表的同一个事件安排两个触发器。
- FOR EACH ROW --触发器的执行间隔:FOR EACH ROW子句通知触发器 每隔一行执行一次动做,而不是对整个表执行一次。
- <触发器SQL语句> --触发器包含所要触发的SQL语句:这里的语句能够是任何合法的语句, 包括复合语句,可是这里的语句受的限制和函数的同样。
B+树索引和哈希索引的区别
B+树是一个平衡的多叉树,从根节点到每一个叶子节点的高度差值不超过1,并且同层级的节点间有指针相互连接,是有序的
哈希索引就是采用必定的哈希算法,把键值换算成新的哈希值,检索时不须要相似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法便可,是无序的
哈希索引的优点:
- 等值查询。哈希索引具备绝对优点(前提是:没有大量重复键值,若是大量重复键值时,哈希索引的效率很低,由于存在所谓的哈希碰撞问题。)
哈希索引不适用的场景:
- 不支持范围查询
- 不支持索引完成排序
- 不支持联合索引的最左前缀匹配规则
一般,B+树索引结构适用于绝大多数场景,像下面这种场景用哈希索引才更有优点:
在HEAP表中,若是存储的数据重复度很低(也就是说基数很大),对该列数据以等值查询为主,没有范围查询、没有排序的时候,特别适合采用哈希索引,例如这种SQL:
select id,name from table where name='李明'; — 仅等值查询
而经常使用的InnoDB引擎中默认使用的是B+树索引,它会实时监控表上索引的使用状况,若是认为创建哈希索引能够提升查询效率,则自动在内存中的“自适应哈希索引缓冲区”创建哈希索引(在InnoDB中默认开启自适应哈希索引),经过观察搜索模式,MySQL会利用index key的前缀创建哈希索引,若是一个表几乎大部分都在缓冲池中,那么创建一个哈希索引可以加快等值查询。
注意:在某些工做负载下,经过哈希索引查找带来的性能提高远大于额外的监控索引搜索状况和保持这个哈希表结构所带来的开销。但某些时候,在负载高的状况下,自适应哈希索引中添加的read/write锁也会带来竞争,好比高并发的join操做。like操做和%的通配符操做也不适用于自适应哈希索引,可能要关闭自适应哈希索引。
数据库表建立注意事项
1、字段名及字段配制合理性
- 剔除关系不密切的字段
- 字段命名要有规则及相对应的含义(不要一部分英文,一部分拼音,还有相似a.b.c这样不明含义的字段)
- 字段命名尽可能不要使用缩写(大多数缩写都不能明确字段含义)
- 字段不要大小写混用(想要具备可读性,多个英文单词可以使用下划线形式链接)
- 字段名不要使用保留字或者关键字
- 保持字段名和类型的一致性
- 慎重选择数字类型
- 给文本字段留足余量
2、系统特殊字段处理及建成后建议
- 添加删除标记(例如操做人、删除时间)
- 创建版本机制
3、表结构合理性配置
- 多型字段的处理,就是表中是否存在字段可以分解成更小独立的几部分(例如:人能够分为男人和女人)
- 多值字段的处理,能够将表分为三张表,这样使得检索和排序更加有调理,且保证数据的完整性!
4、其它建议
- 对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段)
- 使用varchar类型代替char,由于varchar会动态分配长度,char指定长度是固定的。
- 给表建立主键,对于没有主键的表,在查询和索引定义上有必定的影响。
- 避免表字段运行为null,建议设置默认值(例如:int类型设置默认值为0)在索引查询上,效率立显!
- 创建索引,最好创建在惟一和非空的字段上,创建太多的索引对后期插入、更新都存在必定的影响(考虑实际状况来建立)。
java高并发
JAVA 线程状态转换图示
synchronized 的底层怎么实现
- 同步代码块(Synchronization)基于进入和退出管程(Monitor)对象实现。每一个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的全部权,过程以下:
- 若是monitor的进入数为0,则该线程进入monitor,而后将进入数设置为1,该线程即为monitor的全部者。
- 若是线程已经占有该monitor,只是从新进入,则进入monitor的进入数加1.
- 若是其余线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再从新尝试获取monitor的全部权。
- 被 synchronized 修饰的同步方法并无经过指令monitorenter和monitorexit来完成(理论上其实也能够经过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,若是设置了,执行线程将先获取monitor,获取成功以后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其余任何线程都没法再得到同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需经过字节码来完成