100道高频题(二)
最近看到有人总结了高频面试题,苦于没有答案,然后自己总结了一篇。
注意:因为内容太多,有错别字,自己总结的也不一定是正确的。欢迎大家指出错误之处!谢谢
###1、 什么是Servlet?
Servlet是用来处理客户端请求并产生动态网页内容的Java类。Servlet主要是用来处理或者是存储HTML表单提交的数据,产生动态内容,在无状态的HTTP协议下管理状态信息。
2、doGet()方法和doPost()方法有什么区别?
- doGet:GET方法会把名值对追加在请求的URL后面。因为URL对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。
- doPOST:POST方法通过把请求参数值放在请求体中来克服GET方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。
3、出发Full GC
- 调用System.gc时,系统建议执行Full GC,但是不必然执行
- 老年代空间不足
- 方法去空间不足
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。
4、 Set的特点(保存不含有重复元素的集合),TreeSet 和HashSet的区别?
-
TreeSet 是二差树(TreeMap红黑树)实现的,Treeset中的数据是自动排好序的,不允许放入null值。
-
HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
-
HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。
TreeSet通过比较来保存,相等就不保存,hashSet通过hashCode和equals来比较。
5、 linux常用的命令,查看线程用哪个?
- chomd 改变文件的权限;a,b,c各为一个八进制数字,分别表示User、Group、及Other的权限。
- ps 查看进程;通过ps aux|grep(通过ps aux然后在通过管道使用grep查找指定的进程)
- ln:链接文件:ln 默认硬链接,ln -s软连接 区别:硬链接创建别名,指向同一个inode号,软连接有自己的inode号和数据块,只不过数据块比较特殊,指向文件名。
6、分布式Session
问题描述: 在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理。如果不做任何处理的话,用户将出现频繁登录的现象,比如集群中存在A、B两台服务器,用户在第一次访问网站时,Nginx通过其负载均衡机制将用户请求转发到A服务器,这时A服务器就会给用户创建一个Session。当用户第二次发送请求时,Nginx将其负载均衡到B服务器,而这时候B服务器并不存在Session,所以就会将用户踢到登录页面。这将大大降低用户体验度,导致用户的流失,这种情况是项目绝不应该出现的。
-
粘性session:粘性Session是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,如果负载均衡器设置了粘性Session的话,那么用户以后的每次请求都会转发到A服务器上,相当于把用户和A服务器粘到了一块,这就是粘性Session机制。
-
服务器session复制:任何一个服务器上的session发生改变(增删改),该节点会把这个 session的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要session,以此来保证Session同步。
-
session共享机制:使用分布式缓存方案比如memcached、Redis,但是要求Memcached或Redis必须是集群。有两种情况:(1)粘性session处理方式:不同的 tomcat指定访问不同的主memcached。多个Memcached之间信息是同步的,能主从备份和高可用。用户访问时首先在tomcat中创建session,然后将session复制一份放到它对应的memcahed上。memcache只起备份作用,读写都在tomcat上。当某一个tomcat挂掉后,集群将用户的访问定位到备tomcat上,然后根据cookie中存储的SessionId找session,找不到时,再去相应的memcached上去session,找到之后将其复制到备tomcat上。(2)memcached做主从复制,写入session都往从memcached服务上写,读取都从主memcached读取,tomcat本身不存储session
-
项目中解决问题:通过UUID生成一个token,用来标识用户;将token写到我们的redis缓存中;再生成一个cookie,然后将我们的token写入到cookie中。然后response.addCookie(cookie)写入到客户端中;当下次访问的时候,直接从cookie中的token然后获取redis缓存中用户信息即可;也就是说通过redis缓存管理我们的Session;
7、GET 和 POST 到底有什么区别?
- GET:读取“一个资源。比如Get到一个html文件。反复读取不应该对访问的数据有副作用。比如”GET一下,用户就下单了,返回订单已受理“,这是不可接受的。没有副作用被称为“幂等“(Idempotent)。因为GET因为是读取,就可以对GET请求的数据做缓存。这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx)
- POST:在页面里 标签会定义一个表单。点击其中的submit元素会发出一个POST请求让服务器做一件事。这件事往往是有副作用的,不幂等的。
幂等:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
高频100题-网络篇
1、TCP三次握手的数据报,三次握手的原因?
- 客户端发起连接请求,发送请求报,置SYN=1,同时选择自己的一个初始序号seq=x;
- 服务端收到连接请求,然后向客户端发送请求报文,置SYN=1,ACK=1,同时应答序列号ack=x+1;同时自己选择初始序号seq=y;
- 客户端收到答复之后,还是要发送确认信号,置ACK=1,同时序号seq=x+1;应答序号ack=y+1;
三次握手的原因:防止过期的连接请求。两次握手的话,
服务端在等待接收答复信号,如果超过一定的时间没收到,会重新回到第二步,当超过一定的次数(5次),服务端就认为当前关闭连接。
2、四次挥手的原因,每次挥手的数据包
- 客户端主动申请释放连接,发送数据报,置FIN=1,选择序号seq=u;客户端处于FIN-WAIT-1状态。
- 服务端收到释放连接请求,并不会马上关闭连接,有可能服务端还在给客户端发送数据,服务端发送数据报,置ACK=1,同时选择序号seq=v(v为最后一次传送字节序号+1),解答号ack=u+1;客户端收到应答之后处于FIN-WAIT-2状态。
- 服务端处理结束之后,发送数据报,置FIN=1,ACK=1;选择序列号seq=v(v为在2阶段可能还是给客户端发了数据最后一个序号+1),解答号ack=u+1;
- 客户端收到数据报之后,给客户端发送数据报,置ACK=1,选择序列号seq=u+1;,解答号ack=v+1;这时候客户端并不会直接关闭连接,而是等待2MIS。服务端收到之后关闭连接。
3、两次握手行不行啊?
不行,没法防止过期的连接请求。比如第一次中A发送连接请求网络时延,最后到了B,发收到之后会在发送确认的时候就建立连接。而A实际并没有给B发送数据,就会造成B资源浪费。
4、首次握手的隐患– SYN超时
客户端发送SYN的时候,客户端给A发送SYN+ACK,一直没收到A的确认信号,导致服务端一直处在SYN-RCVE状态(重复5次【不包括第一次】,从1秒开始,每次重试都翻倍:1+2+4+8+16+32=63秒)。
5、挥手时最后一次ACK如果客户端没收到怎么办(close_wait过多的解决方案)
服务端处于CLOSE-WAIT状态;
可以通过设置TCP的连接时长keep_alive_time还有TCP监控连接的频率以及连接没有活动多长时间被迫断开连接。
HTTP
1、HTTP1.0和HTTP1.1的区别?
- HTTP1.0:浏览器与服务器保持短暂连接,每一个请求都需要与服务器建立一次TCP连接,完成请求之后立即断开TCP,服务器不跟踪每个客户也不记录过去的请求。
- HTTP1.1:支持长连接,一个TCP连接内可以可以传送多个HTTP请求和响应;1.1还增加了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。
2、HTTP的请求方法有哪些?
- GET:请求数据附加在URL中,可以看得见,不安全,同时GET请求有长度限制。处理敏感数据是不可以用GET方法。
- POST:请求数据放在body中,对外界不可见,安全。对长度没有限制。
- HEAD:方法
- PUT:方法
- CONNECT:方法
3、常见的状态码
- 200(ok):一切正常
- 400(bad request):客户端方面的问题。
- 500(Internal server error):服务器问题。
- 301(Move Permanently):客户端出发的动作引起了资源的URL的变化时发送此响应代码。
- 404(Not Found)/410(Gone):客户端请求的URL不对应与任何资源。
- 409(Conflict):客户端试图执行一个"会导致一个或者多个资源处于不一致的状态"。
4、对HTTPS有什么了解?(HTTP/HTTPS有什么区别?)
- HTTP:定义在浏览器和服务器之间的请求和响应的交互,必须按照规定的格式和遵循一定的规则。这就是HTTP协议。
- http是明文传送,这就造成了一定的数据安全性问题,https是在http的基础上加入TLS/SSL协议,从而构建可进行加密传输、身份认证的网络协议。tls/ssl利用了非对称加密+对称加密+散列算法。客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥,然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取。
5、TCP和UDP的区别?
- TCP面向连接的,UDP面向无连接的
- TCP可靠传输,UDP不太可靠;
- TCP是点对点,UDP既可以点对点,一对多;
- TCP速度慢,UDP速度快
- TCP有流量控制,拥塞控制,UDP没有。
- TCP面向字节流,UDP面向报文
- TCP保证数据顺序,UDP不保证;
- TCP数据无边界,UDP有边界;
6、五层网络协议
- 应用层:http,DNS
- 运输层:TCP,UDP
- 网络层:ip,APR()
- 数据链路层:定义网卡物理地址,以及如何解析MAC地址
- 物理层:实体层,光缆,无线电波等。
7、UDP如何实现可靠传输?
类似于TCP的做法,只不过是在应用层上实现了TCP
- 接收方收到UDP之后回复一个确认包。
- 发送方超时重传机制。
- 发送放要有一个发送窗口的限制,根据网络情况来自适应调整。
8、TCP和http的区别?
- tcp是一种面向连接、可靠的、基于字节流的可靠通信;在运输层上。
- http是超文本传输协议,定义了客户端到服务端请求和响应的标准。基于TCP的,在应用层上。
9、TCP协议-如何保证传输可靠性?
- ACK应答
- 超时重传
- 连接管理机制
- 流量控制
10 一个网站请求从客户端到服务端的过程
- DNS域名解析,得到ip地址,然后ARP获得物理地址
- 根据ip地址,找到对应的服务器,建立TCP连接(Socket)
- 发送HTTP请求
- web服务器反向代理(Nginx):在服务器端可能有多台服务器,这需要一个负载均衡设备来平均分配用户请求。
- 应用服务器Servet处理请求,返回数据;
- 关闭TCP连接,浏览器渲染画面;
反响代理:代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将内部服务器得到的结果返回客户端。此时代理服务器对外表现为一个服务器,反响代理服务器对客户端而言,就像是原始服务器。作用:保证内网安全,使用waf功能,阻止web攻击;负载均衡;
正向代理:通常被称为代理,用户无法正常访问外部资源,通过代理的方式绕过防火墙,从而连接到目标网络或者服务。
11 、DNS解析过程
-
先查询浏览器缓存,如果有,则解析结束
-
浏览器没有,OS先查询本地hosts文件,有,解析结束(/etc/hosts);
-
hosts没有,查找本地DNS解析器缓存(一般在城市的某个角落,一般80%到这里就结束了),有,解析结束;
-
如果以上仍未命中,将跳到根域名服务器请求解析,则根据DNS设置(是否设置了转发器)进行查询,未用转发模式,
- (查www.qq.com)本地DNS服务器发送至13台根服务器,根服务器判断.com顶级域名谁管理,并返回给本地DNS服务器。
- 本地DNS服务器根据返回的顶级域名,然后去问顶级域名服务器,顶级域名服务区判断qq.com谁来管理,并返回本地DNS服务器。
- 本地服务器收到qq.com域名服务器之后,然后去问该服务器,该服务器返回www.qq.com的ip地址,返回到本地DNS服务器,解析完成l
-
使用了转发模式:(www.qq.com),根服务器把请求转发到顶级域名.com,顶级域名把请求转发到qq.com,
-
本地域名服务器则将ip返回给用户
MYSQL
1、exlplain中常用列值含义?
- type:访问类型:最好到最差system>const>eq_ref>ref>range>index>ALL;当出现ALL时就表现为全表扫描,例如百万级别数据库使用select * from table;
- key:用到的索引
- Extra:
-
filesort:文件排序,没有建立索引或者索引失效
-
using temporary:主要是用了group by:会建立临时表,使用group by 要尽量使用索引来。
-
using index:使用了覆盖索引,效率可以。有Using where表明被用来了执行索引键的查找。
- 例如:explain select col2 from t1 where col1=‘ab’,col2是索引,col1也是索引,然后会有Using index; Using where
- explain select col1 , col2 from t1; 就只有Using index;
-
Using where 表明使用了where过滤。
-
- ref:显示已经被使用了索引列,使用索引列查询的值(类似复杂度这么一说)
备注:建立索引 create index idx_article_ccv on article(category_id,comments,views)
2、MYSQL索引在什么情况下会失效
在staffs表上建立了name age pos 复合索引;
-
最佳左前缀:
- select * from table where name=‘july’ and age=15;如果索引了多列(name,age,pos),不能跳过索引中的列(中间列)。否则失效;
- select * from table where name=15 and pos=1;这时候也用到了索引,但是只是用到了name,pos没有用到;
-
不要在索引列是操作(计算,函数,自动或者手动类型转换);
- explain select * from staffs where left(name,4)=‘july’;此时用到了函数,索引失效
-
不能使用索引中范围条件右边的列
- select * from staffs where name=‘july’ and age=25 and pos=‘manager’;ref:const,const,const;type:ref; 这是最好的查询
- select * from staffs where name=‘july’ and age>25 and pos=‘manager’;ref:null;type:range;这时候因为age之后不能使用,导致type变成range;
-
使用覆盖索引达到最优查询
-
使用!= 或者 <>的时候索引失效
- select * from staffs where name!=‘july’;导致全表扫描
- select * from staffs where name <> ‘july’;
-
is null is not null 也无法使用索引;
- select * from staffs where name is null; 无法使用索引
-
like以通配符开头‘%ab…’,mysql会导致全表扫描;
- select * from staffs where name like ‘%july%’;导致全表扫描
- select * from staffs where name like ‘%july’; 全表扫描
- select * from staffs where name like ‘july%’;type:range
- 对于非得使用’%abc%'的,使用覆盖索引优化,例如:select age,name from staffs where name like ‘%july%’;这时候使用了覆盖索引;
-
字符串不加单引号索引失效:select * from staffs where name=200;没加单引号,索引失效
-
使用or索引失效; select * from staffs where name = ‘july’ or name=‘z3’;
3、MYSQL的存储引擎:底层实现、对比、适用场景
主要有两种存储引擎:MyISAM和InnoDB
- InnoDB支持事务,MyISAM不支持事务;
- InnoDB支持外键,MyISAM不支持外键;
- InnoDB不支持FULLTEXT类型的索引(全文搜索的索引)。
- InnoDB不保存表的具体行数,每次要获取行数要搜素整张表来计算,MyISAM保存表的行数,直接就可以取出来;
- 对于AUTO_INCREMENT的字段,InnoDB中必须包含只有该字段的索引,在MyISAM可以喝其他的字段建立联合索引;
- InnoDB支持行锁,读写可以并行,有时候行锁会升级为表锁(update table set a=1 where user like ‘%hdc%’);MyISAM只有表锁,读锁和写锁是互斥的,也就是说读写是串行的;表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock):nnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,注意间隙锁的影响
适用场景:MyISAM:以读为主,数据一致性要求不是很高;
InnoDB:数据更新频繁的场景,数据一致性要求比较高;
4、 B 树, B+树在数据库存储中的作用、区别;
- B树叶子节点和非叶子节点都保存数据,B+树只有叶子节点保存数据
- B+树一个磁盘叶可以存放更多的节点信息,因为树更矮,千万级别的数据只需要3-4层,也就是只需要I/O操作三次左右;
- B+树叶子节点有指针节点连接起来,对范围查找更快,而B树需要不停的中序遍历;
5、 MYSQL的分库分表,分库分表后如何保证分布式id唯一;
- 数据库自增id:单独开一个表:每次来一个插入就自增id然后再到对应的库去修改id;优点:简单;缺点要单开一个服务,高并发有问题;
- UUID:优点:本地生成,脱离数据库;缺点:太长,导致B+树频繁修改树结构,性能下降;
- snowflake算法:1bit不用,41bit毫秒数,10bit工作id,12bit序列号;
6、MYSQL什么时候发生死锁?
死锁是一种两个或者两个以上的线程,在争夺资源造成互相等待的现象。MySQL中:两个或者两个以上的Session加锁的顺序不一致造成的;
7、MYSQL的 innodb 引擎为什么不用 B 树
因为B树的非叶子节点存放数据,同等条件下B+树能存放更多的节点信息,千万级的数据只需要三层树高这样子,也就是只需要I/O操作三次;而且B+树的叶子节点有指针相连,适合范围查找。
8、MYSQL的主从复制原理,如何实现
9、如果是存储日志,用什么存储引擎比较合适。
答:MyISAM适合存储,因为这个引擎插入速度很快;如果需要对日志表做分析报表,生成报表的SQL可能导致插入速度下降;由此可以利用主从复制,在备库上执行耗时的生成报表操作。主库只用于写入操作。
10、Mysql的锁有那几种,行锁的实现原理;
有行锁和表锁和页锁;原理:行锁是加在索引之上的;
11、一条sql在MySQL的执行过程
- 连接器:登录账号,连接服务器,取账号权限;在select语句情况下,如果开启查询缓存则查缓存,命中直接返回;
- 分析器:语法检查;将语句传递给预处理器,检查数据表和数据列是否存在,解析别名看是否存
- 优化器:优化sql
- 执行器:执行sql,返回结果;
#Redis
1、Redis有那些数据结构?
- String:redis的基本数据结构
- Hash:
- List:
- Set:
- ZSet:
2、redis的过期策略?
-
设置过期时间(set key value)
- 定期删除:假设你设定一个key能存活1小时,1小时后key失效了会直接被删除吗?并不是的,redis默认100ms随机抽取一些过期的key删除,为什么随机呢?因为担心检查key过多。
- 惰性删除:查找指定key是,redis检查是否过期,过期就直接删除,不返回;
-
内存淘汰策略:
- noeviction:内存不足时,写入操作直接报错;
- allkeys-lru:所有key中,移除最近最少使用的key;
- allkeys-random:所有key中,随机删除key;
- volatile-lru:移除设置了过期的最近最少使用的key;
- volatile-random:移除设置了过期的的key中随机一个key;
- volatile-ttl:移除设置了过期的key中更早过期的key。
3、redis的集群设计
- 主从模式:主节点挂掉以后,redis就没法对外提供服务。
- Sentinel模式:保证了高可用,当数据量过大时,不支持扩展,适用于缓存较小的系统。
- Cluster模式:解决了单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。使用slot(槽)的概念,通过hash算法将key分配到槽中;
4、Redis的持久化机制,应用场景
- RDB:每隔一定的时间将数据保存到一个RDB文件,通过配置文件里面修改。sava 900 1:每900秒有一个key发生变化就保存RDB;
- AOF:保存写命令的日志,简单来理解就是保存我们平时命令。默认是关闭的:修改为:appendonly yes
对比:实现方式不一样,RDB比AOF文件小,AOF安全性比RDB高,因为AOF要比RDB丢失的数据少。优先级:开启了AOF优先使用AOF恢复文件,反之;
4、Redis为什么那么快(为什么使用 redis 做消4息队列)?
- redis使用内存当缓存
- redis提供了丰富的数据结构,有string,hash,list,set,zset;
- redis使用了单线程,避免了不必要的上下文切换。
- redis用了多路复用:具体是调用底层操作系统的epoll来监控多个流事件,当有一个或者多个流I/O事件是,通知程序来轮训处理I/O流事件。在这个过程中是单线程的;
5、Redis缓存穿透,缓存雪崩,以及如何解决?
- 缓存穿透:高并发下访问redis中不存在的值,不会被命中,导致大量的访问数据库。//黑客攻击:(同一个key请求)将第一次请求返回的null缓存到redis中;不同key高频请求:布隆过滤器;二进制码;使用了hash算法,然后对二进制位保存id,通过判断二进制里面有没有;但是不能解决hash碰撞问题;(所以容错率存储id)
- 缓存击穿:高并发之下访问一个key,当key过期之后,导致大量的访问数据库。/分布式锁
- 缓存雪崩:高并发之下:大量的热门key同时失效,导致大量的请求落到数据库之上。/给每条数据设置随机有效期;
解
- 雪崩:优化缓存过期时间
- 击穿:设置缓存永不过期。法一:使用zookeeper分布式锁来解决:当去redis找得时候,没有找到,然后去抢zookeeper抢一把锁,抢到了之后然后写回到redis,其他的线程还是先查redis;法2:查询数据库,然后再缓存到redis(常用算法,而且效率高);法三:RabbitMQ消息队列;
6、Redis有序集合的底层数据结构,为什么用跳表 压缩列表比纯用跳表好?
-
ziplist:
- 元素数量少于128
- 每个元素的长度小于64字节
-
skiplist:不满足上诉条件,则使用跳表结构。
当数据小的时候,使用链表的查找速度很快。数据量大的时候使用跳表速度比较快。
7、redis中AOF重写的原理?
AOF是记录写命令来记录数据库状态的。所以会越来越大;因为需要重写,解决文件膨胀问题;创建一个新的AOF文件代替现有的AOF文件,新旧文件保存的数据库状态是一致的;
- AOF重写不需要对AOF文件进行任何的读取,写入,分析等操作,是通过读取当前服务器的数据库状态来实现的;
- 首先从数据库读取键现在的值,然后用一条命令去记录键值对,代替之前记录的多个命令;
- AOF不希望重写会造成服务器无法处理请求,所以将重写放到子进程里执行;
- 为了解决子进程重写期间,服务器进程处理请求造成当前数据库和重写后的AOF文件不一致。redis增加了AOF重写缓存;redis服务器主进程会在执行完命令之后,会同时将写命令追加到AOF缓冲区和AOF重写缓冲区;
- 完成重写之后,给主进程发信号,然后主进程调用信号处理函数将AOF缓冲区写入到新的AOF文件中;同时对新的AOF文件重命名替换,完成
- 当5完成之后主进程重新开始处理请求;
8、redis分布式锁的加锁和解锁详细实现?
在分布式中:如果使用synchronized,可能会对同一个商品减库存;
单机中:
- 互斥性:保证只有一个客户端可以获取到锁;
- 不会发生死锁:一个客户端持有锁崩溃了,会在一定时间释放锁,保证其他客户端能获取锁;
- 容错性:只要大部分节点正常运行,客户端就可以加锁解锁;
- 加锁和解锁必须是同一个客户端;
利用Jedis开源组件:jedis.set(lockKey,requestId,nx,expx,time);来加锁;
jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId))解锁;
场景1:
- 加锁的时候设置的超时时间由于系统压力大,程序执行时间大于释放时间,所以锁会被redis释放, 如果这时候刚好另一个线程进来又加了一把锁,则第一个线程会把第二个线程的锁给释放掉了/以上是jedis的实现;可以使用将获得锁的客户端开一个分线程来没隔多少秒检查redis当前key的值是否有锁,如果有给续命;大概是1/3;
- redission(底层使用了lua脚本:脚本代码是原子性的)实现了上式的功能:
- Rlock resissionLock=redission.getLock(lockKey);
- resissionLock.lock();
- redissionLock.unlock();
场景2:对上述存在如下1的问题:
- 如果Master-Slave之下:一个线程给Master加锁成功,并对对应的key执行了业务逻辑,还没来得及同步到slave中,这时候master节点挂了,然后其他的线程抢到了新的redis的锁;这时候是没有key值的。
- 想让性能提升10倍: 解决思路:例如对某个商品库存的key,分为10个段,然后分别就可以对不同的key加锁。性能提升10倍;类似CurrentHashMap;如果是集群的话,再把划分的key分到不同的集群上,性能又会提升;
- 解决问题1:可以使用zookeeper,来解决数据一致性;相对来说zookeeper稳定性高,redis性能高;可以说是各有千秋;
zookeeper:分布式锁原理:cp(cap:c:一致性 a:可用性;:p:分区容错性) redis:ap
- zookeeper是leader-follower模式,而且是树形结构:它也是像redis一样设置key-value对,但是它给leader加锁的时候并不会直接返回给线程,而是当zk把key同步到半数以上的节点时才会返回,程序才能继续执行;如果主节点挂了,zk会保证只有key的节点会被选举成功;cp的zk牺牲掉了可用性,也就是选举的过程对外部是不可用的;
- 加锁原理:创建临时节点(有序号的):然后每个节点都都监听前面一个节点(注册事件,),可以使用CountDownLanch(),让前一个节点发生变化时,下一个节点就会尝试获得锁(调用回调函数);
ngnix
当用户数量多的时候,一般不止一台tomcat,前面可能会先挂一台ngnix反向代理服务器(负载均衡),通过一定的算法分发给某一台tomcat;
9、分布式锁和锁区别,什么时候用,怎么考虑的
- 锁是基于jvm的,当时单机模式的时候,使用基本的锁就可以解决线程的问题;
- 当部署了多态服务器,比如多台tomcat的时候,这时候多个服务器之间基于jvm的锁就无效了;比如对共享资源的访问,有可能对同一个资源进行了操作;这时候就考虑用到了分布式锁,mysql的锁,redis分布式锁,zookeeper分布式锁;
数据库
1、 ACID特性()
2、 SQL优化
3、 聚族索引和非聚族索引;
- 聚族索引,存放了数据库行号叫做聚族索引,确定了表中数据的物理地址;
- 非聚族索引,存储主键值;
4、非聚族索引查询的过程?
- 如果使用了覆盖索引,那么查询的就能得到数据;
- 如果不是覆盖索引,那么使用索引查到主键行号,然后再通过主键号找到对应的数据;也叫作回表;
5、varchar怎么建立索引?
答:指定索引的长度,没必要对全字段建立索引;
6、Tomcat是一个Servlet容器
-
Host是虚拟主机:可以配置不同的虚拟主机,然后将不同的应用放在里面;
-
Context继承了Container 也就是容器,它代表一个应用;通过配置容器的路径,就能访问我们
-
Engine:管理我们的虚拟主机主机(Host)
-
Engine > Host >Context > Wrapper > Servlet/默认是单例的,也就是每一个请求都会访问某一个Servlet实例;
-
容器部署的架构:
- Engine:List host;
- Host:List context;
- Context: List list;
- Wrapper:List servlets;//来一个Request,就是传给我们的servlet.doGet()方法;
-
Tomcat中Request对象怎么生成的?从哪里来的?
- Tomcat里面有一个Connector组件,首先组件从socket(建立tcp连接)获取操作系统的数据,然后根据http协议解析数据得到(Request)(如果是https,需要先ssl握手,加密);
- 因为涉及读取数据,所以涉及到了BIO,NIO;通过配置不同的类名来实现IO模型切换;
7、索引的缺点
- 占用物理存储空间
- 当插入或者删除或者修改的时候,需要维护B+树;
8、设计一个数据库表实现树的结构
- 基于节点之间的继承关系来描述(Node_id,name,Parent_id);
- 基于左右至编码的Schema设计;(node_id,name,left,right);
9、SQL慢查询的常见优化步骤是什么?
-
开启sql慢查询:修改my.ini;
- long_query_time=2: 定义多少秒为慢查询
- slow_query_log=on;
- slow_query_log_file="";放在哪个路径之下;
-
分析日志:使用explain SQL语句;然后分析type类型:ALL<range<ref<eq_ref<const<system;
-
优化
- 先看一下有没有需要建立索引
- 已经建立索引的情况下是否有索引失效
- 优化数据库结构(表是不是太大了)
- 分析关联查询
10、 varchar 和 char 的区别
- char(10): 值为123,则存储为:123+7个空格:由此,char是长度不可变的类型
- varchar(10): 值为:123 则存储为:123;由此,varchar是长度可变的;
- 两者超出长度都会自动截取前部分;
11、 说下乐观锁、悲观锁,并写出MYSQL的实现;
-
乐观锁:通过增加一个字段version来实现的,更新的时候比较一下是不是对应的版本号
- sql:update status set name=‘liar’,version=(version+1) where id=1 and version=version;
-
悲观锁:select for update;索引失效可能会锁住整张表;
12、 数据库中密码是怎么存放的? 还有其他的加密方式吗?
一般是MD5加密,然后再数据库中建立一个字段用来存放;
13、怎么保证焕春和数据库双写一致?
- 查询的时候,先查缓存,再查数据库
- 更新的时候,先更新数据库,在删除缓存;