剑指Java
计算机网络
网络基础知识
OSI开放式互联参考模型
TCP/IP
OSI七层模型 | TCP/IP概念层模型 | 功能 | TCP/IP协议族 |
---|---|---|---|
应用层 | 应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | FTP,HTTP,SMTP,DNS,Telnet,TFTP |
表示层 | 应用层 | 数据格式化,代码转换,数握加密 | 没有协议 |
会话层 | 应用层 | 解除或建立与别的接点的联系 | 没有协议 |
传输层 | 传输层 | 提供端对端的接口 | TCP,UDP |
网络层 | 网络层 | 为数据包选择踏由 | IP,ICIP,RIP, OSPF, BCP, ICIP |
数据链路层 | 链路层 | 传输有地址的帧以及错误检测功能 | SLIP, CSLIP, PPP, ARP, RARP,ITU |
物理层 | 链路层 | 以二进制数据形式在物理媒体上传输数据 | 1902110,IEEE802,IEEE802.2 |
OSI注重通信协议必要功能是什么,TCP/IP更强调计算机上实现协议应该要开发哪种程序
TCP三次握手
传输控制协议TCP简介
- 面向连接的、可靠的、基于字节流的传输层通信协议
- 将应用层的数据流分割成报文段并发送给目标节点的TCP层
- 数据包都有序号,对方收到则发送ACK确认,未收到则重传
- 使用校验和来检验数据在传输过程中是否有误
TCP报文头
TCP Flags
- URG : 紧急指针标志
- ACK : 确认序号标志
- PSH : push标志
- RST :重置连接标志
- SYN :同步序号,用于建立连接过程
- FIN : finish标志,用于释放连接
三次握手
“握手”是为了建立连接, TCP3次握手的流程图如下
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
为什么需要三次握手才能建立起连接
答:为了初始化Sequence Number的初始值
首次握手的隐患—-SYN超时
问题起因分析
- Server收到Client的SYN , 回复SYN-ACK的时候未收到ACK确认
- Server不断重试直至超时, Linux默认等待63秒才断开连接
针对SYN Flood的防护措施
- SYN队列满后,通过tcp_ syncookies参数回发SYN Cookie
- 若为正常连接则Client会回发SYN Cookie ,直接建立连接
建立连接后, Client出现故障怎么办
保活机制
- 向对方发送保活探测报文,如果未收到响应则继续发送
- 尝试次数达到保活探测数仍未收到响应则中断连接
TCP的四次挥手
“挥手”是为了终止连接, TCP四次挥手的流程图如下:
TCP采用四次挥手来释放连接
第一次挥手: Client发送一个FIN,用来关闭Client到Server的数据传送,Client 进入FIN_WAIT-1(终止等待1)状态;
第二次挥手: Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1 (与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态;
第三次挥手: Server发送一个FIN,用来关闭Server到Client的数据传送,Server 进入LAST_ACK状态;
第四次挥手: Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么会有TIME_WAIT状态
原因:
- 确保有足够的时间让对方收到ACK包
- 避免新旧连接混淆
为什么需要四次握手才能断开连接
答:因为全双工,发送方和接收方都需要FIN报文和ACK报文
服务器出现大量CLOSE_WAIT状态的原因
对方关闭socket连接,我方忙于读或写,没有及时关闭连接
- 检查代码,特别是释放资源的代码
- 检查配置,特别是处理请求的线程配置
UDP
UDP简介
UDP报文结构
UDP的特点
- 面向非连接
- 不维护连接状态,支持同时向多个客户端传输相同的消息
- 数据包报头只有8个字节,额外开销较小
- 吞吐量只受限于数据生成速率、传输速率以及机器性能
- 尽最大努力交付,不保证可靠交付,不需要维持复杂的链接状态表
- 面向报文,不对应用程序提交的报文信息进行拆分或者合并
TCP和UDP的区别
TCP | UDP |
---|---|
面向连接 | 无连接 |
可靠性 | 不可靠 |
有序性 | 无序 |
速度慢 | 速度快 |
重量级 | 轻量级 |
TCP的滑动窗口
概述
滑动窗口通俗来讲就是一种流量控制技术。
它本质上是描述接收方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据,如果发送方收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0的数据报的到来
RTT和RTO
RTT:发送一个数据包到收到对应的ACK ,所花费的时间
RTO:重传时间间隔
TCP使用滑动窗口做流量控制与乱序重排
- 保证TCP的可靠性
- 保证TCP的流控特性
窗口数据的计算过程
AdvertisedWindow = MaxRcvBuffer - (LastByteRcvd - LastByteRead)
EffectiveWindow = AdvertisedWindow - (LastByteSent - LastByteAcked)
TCP会话的发送方
HTTP
HTTP简介
超文本传输协议HTTP主要特点
- 支持客户/服务器模式
- 简单快速
- 灵活
- 无连接
- 无状态
HTTP请求结构
HTTP响应结构
请求/响应的步骤
- 客户端连接到Web服务器
- 发送HTTP请求
- 服务器接受请求并返回HTTP响应
- 释放连接TCP连接
- 客户端浏览器解析HTML内容
HTTP相关问题
在浏览器地址栏键入URL ,按下回车之后经历的流程
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束
HTTP状态码
五种可能的取值
- 1xx :指示信息—表示请求已接收,继续处理
- 2xx :成功—表示请求已被成功接收、理解、接受
- 3xx :重定向—要完成请求必须进行更进一步的操作
- 4xx :客户端错误—请求有语法错误或请求无法实现
- 5xx :服务器端错误—服务器未能实现合法的请求
常见状态码
- 200 OK: 正常返回信息
- 400 Bad Request: 客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized: 请求未经授权,这个状态代码必须和WWW-Authenticate报头域- -起使用
- 403 Forbidden: 服务器收到请求,但是拒绝提供服务
- 404 Not Found: 请求资源不存在,eg,输入了错误的URL
- 500 Internal Server Error: 服务器发生不可预期的错误
- 503 Server Unavailable: 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
GET请求和POST请求的区别
从三个层面来解答
- Http报文层面: GET将请求信息放在URL , POST放在报文体中
- 数据库层面: GET符合幂等性和安全性, POST不符合
- 其他层面: GET可以被缓存、被存储,而POST不行
Cookie和Session的区别
Cookie简介
- 是由服务器发给客户端的特殊信息,以文本的形式存放在客户端
- 客户端再次请求的时候,会把Cookie回发
- 服务器接收到后,会解析Cookie生成与客户端相对应的内容
Session简介
- 服务器端的机制,在服务器上保存的信息
- 解析客户端请求并操作session id,按需保存状态信息
Session的实现方式
- 使用Cookie来实现
- 使用URL回写来实现
区别
- Cookie数据存放在客户的浏览器上, Session数据放在服务器上
- Session相对于Cookie更安全
- 若考虑减轻服务器负担,应当使用Cookie
HTTP和HTTPS的区别
SSL(Security Sockets Layer,安全套接层)
- 为网络通信提供安全及数据完整性的一种安全协议
- 是操作系统对外的API , SSL3.0后更名为TLS
- 采用身份验证和数据加密保证网络通信的安全和数据的完整性
加密方式
- 对称加密: 加密和解密都使用同一个密钥
- 非对称加密: 加密使用的密钥和解密使用的密钥是不相同的
- 哈希算法: 将任意长度的信息转换为固定长度的值, 算法不可逆
- 数字签名: 证明某个消息或者文件是某人发出/认同的
HTTP数据传输流程
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以证书的形式回发浏览器
- 浏览器验证证书合法性,并结合证书公钥加密信息发送给服务器
- 服务器使用私钥解密信息,验证哈希,加密响应消息回发浏览器
- 浏览器解密响应消息,并对消息进行验真,之后进行加密交互数据
区别
- HTTPS需要到CA申请证书, HTTP不需要
- HTTPS密文传输, HTTP明文传输
- 连接方式不同, HTTPS默认使用443端口, HTTP使用80端口
- HTTPS=HTTP+加密+认证+完整性保护,较HTTP安全
HTTPS真的很安全吗
浏览器默认填充http:// ,请求需要进行跳转,有被劫持的风险
可以使用HSTS ( HTTP Strict Transport Security )优化
Socket
Socket是对TCP/IP协议的抽象,是操作系统对外开放的接口
Socket通信流程
数据库
数据库架构
如何设计一个关系型数据库
索引模块
为什么要使用索引
什么样的信息能成为索引
索引的数据结构
密集索引和稀疏索引的区别
为什么要使用索引
避免全表扫描,快速查询数据,提升检索效率
什么样的信息能成为索引
主键、唯一键以及普通键等一切能让数据具备区分性的字段
索引的数据结构
- 生成索引,建立二叉查找树进行二分查找
- 生成索引,建立B-Tree结构进行查找
- 生成索引,建立B+-Tree结构进行查找
- 生成索引,建立Hash结构进行查找
二叉查找树上阵
B-Tree
定义
- 根节点至少包括两个孩子
- 树中每个节点最多含有m个孩子( m>=2 )
- 除根节点和叶节点外,其他每个节点至少有ceil(m/2)个孩子
- 所有叶子节点都位于同一层
假设每个非终端结点中包含有n个关键字信息,其中
- Ki (i1…n)为关键字,且关键字按顺序升序排序K[i-1]< K[i]
- 关键字的个数n必须满足: [ceil(m/ 2)-1]<=n<= m-1
- 非叶子结点的指针 : P[1], P[2], …. P[M] ;其中P[1]指向关键字小于K[1]的子树, P[M]
指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树
B+-Tree
B+树是B树的变体,其定义基本与B树相同,除了:
- 非叶子节点的子树指针与关键字个数相同
- 非叶子节点的子树指针P[i] ,指向关键字值[K[i],K[i+1])的子树
- 非叶子节点仅用来索引,数据都保存在叶子节点中
- 所有叶子节点均有一个链指针指向下一个叶子结点
B+ Tree更适合用来做存储索引
- B+树的磁盘读写代价更低
- B+树的查询效率更加稳定
- B+树更有利于对数据库的扫描
Hash索引
缺点
- 仅仅能满足 “=” , “IN”, 不能使用范围查询
- 无法被用来避免数据的排序操作
- 不能利用部分索引键查询
- 不能避免表扫描
- 遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高
BitMap索引(MySQL不支持)
密集索引和稀疏索引的区别
- 密集索引文件中的每个搜索码值都对应一个索引值
- 稀疏索引文件只为索引码的某些值建立索引项
InnoDB
- 若一个主键被定义,该主键则作为密集索引
- 若没有主键被定义,该表的第一个唯一非空索引则作为密集索引
- 若不满足以上条件, innodb内部会生成一个隐藏主键(密集索引)
- 非主键索引存储相关键位和其对应的主键值,包含两次查找
额外问题
如何定位并优化慢查询Sql
联合索引的最左匹配原则的成因
索引是建立得越多越好吗
如何定位并优化慢查询Sql
- 根据慢日志定位慢查询sql
- 使用explain等工具分析sql
- 修改sql或者尽量让sql走索引
开启MySQL慢查询
方式一: 修改配置文件 在 my.ini 增加几行: 主要是慢查询的定义时间(超过2秒就是慢查询),以及慢查询log日志记录( slow_query_log)
1 | [mysq11d] |
方式二:通过MySQL数据库开启慢查询:
1 | mysql>set global slow_query_1og = ON |
explain
显示mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句
explain select name from person info large order by name desc;
建立索引
alter table person _info _large add index idx_name(name);
联合索引的最左匹配原则的成因
最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、 <、between、like)就停止匹配,比如a = 3 and b = 4 and c> 5 and d = 6如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索弓|则都可以用到,a,b,d的顺序可以任意调整。
=和in可以乱序,比如a = 1 and b = 2 and c= 3建立(a,b,c)索引可以任意顺序, mysql的查询
优化器会帮你优化成索引可以识别的形式
索引是建立得越多越好吗
- 数据量小的表不需要建立索引,建立会增加额外的索引开销
- 数据变更需要维护索引,因此更多的索引意味着更多的维护成本
- 更多的索引意味着也需要更多的空间
锁模块
MyISAM与InnoDB关于锁方面的区别是什么
数据库事务的四大特性
事务隔离级别以及各级别下的并发访问问题
InnoDB可重复读隔离级别~下如何避免幻读
RC、RR级别下的InnoDB的非阻塞读如何实现
MyISAM与InnoDB关于锁方面的区别
- MyISAM默认用的是表级锁,不支持行级锁
- InnoDB默认用的是行级锁,也支持表级锁
MyISAM
默认情况下 MyISAM的select加的是读锁(共享锁),update,insert,delete增加的是写锁(排它锁)
select可以加写锁: 即在select语句后加上 for update
如:
1 | select * from user for update |
由于select的锁为读锁,所以在一个select时可以别的select并不阻塞,但update,insert,delete时阻塞(给整个表加锁)
update,insert,delete的锁为写锁,在操作时别的操作阻塞(表级锁)
InnoDB
InnoDB使用的是二段锁,即加锁和解锁是分两个步骤完成的,即先对同一个事务里的一批操作分别进行加锁,然后到commit的时候,在对事务里加上的锁进行统一的解锁
InnoDB在没有用到索引时,使用表级锁.当走索引时,使用行级锁
InnoDB对select进行了改进,select的操作并没有上锁
select默认是非阻塞读(不上锁),其他默认上行级写锁
为select语句上共享锁 :
1 | select * from user lock in share mode |
数据库事务的四大特性
ACID
- 原子性
原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败。
- 一致性
官网上事务一致性的概念是:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
换一种方式理解就是:事务按照预期生效,数据的状态是预期的状态。
- 隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
- 持久性
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
事务隔离级别以及各级别下的并发访问问题
事务并发访问引|起的问题以及如何避免
- 更新丢失——mysq|所有事务隔离级别在数据库层面. 上均可避免
脏读——READ-COMMITTED事务隔离级别以上可避免
不可重复读——REPEATABLE-READ事务隔离级别以上可避免
- 幻读——SERIALIZABLE事务隔离级别可避免
MySQL查看和修改事务隔离级别的几个命令:
- 查看事务隔离级别使用select @@tx_isolation
- 开启事务隔离级别使用start transaction
- 修改当前会话事务隔离级别使用SET session TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommitted|Read committed|Repeatable read|Serializable)
- 修改全局事务隔离级别使用SET global TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommitted|Read committed|Repeatable read|Serializable)
通俗地解释脏读、不可重复读、幻读
脏读:所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
也就是说,当前事务读到的数据是别的事务想要修改成为的但是没有修改成功的数据。
不可重复读:事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
也就是说,当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义。
幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。也就是说,当前事务读第一次取到的数据比后来读取到数据条目少。
不可重复读和幻读比较:
两者有些相似,但是前者针对的是update或delete,后者针对的insert。
InnoDB可重复读隔离级别下如何避免幻读
- 表象:快照读(非阻塞读) ——伪MVCC
- 内在: next-key锁 (行锁+gap锁)
当前读
- 当前读: selet…lock in share mode , selet…for update
- 当前读: update , delete , insert
读取的是记录的最新版本,所以所以就需要通过加锁(行锁 间隙锁 表锁)的方式,使得被当前读读过的数据不能被新增修改或者删除,换句话说再来一次当前读要返回相同的数据。
快照读
- 快照读:加锁的非阻塞读, select
在RR隔离级别下:快照读有可能读到数据的历史版本,也有可能读到数据的当前版本。所以快照读无需用锁也不会发生幻读的情况。
next-key锁 (行锁+gap锁)
- 行锁
- Gap锁(间隙锁)
间隙锁锁的是索引叶子节点的next指针。
解决了mysql RR级别下是幻读的问题。
Gap锁会用在非唯一索引或者不走索引的当前读中
- 非唯一索引
- 不走索引
对主键索引或者唯一索引会用Gap锁吗
如果where条件全部命中,则不会用Gap锁,只会加记录锁
如果where条件部分命中或者全不命中,则会加Gap锁
RC、RR级别下的InnoDB的非阻塞读如何实现
数据行里的DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID字段
DB_TRX_ID表示最后一个事务的更新和插入。
DB_ROLL_PTR指向当前记录项的undo log信息。
DB_ROW_ID标识插入的新的数据行的idundo日志
read view