计算机网络
计算机网络
TCP/IP网络模型/ OSI模型
OSI模型, 是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,将计算机网络通信划分为七个不同的层级,每个层级都负责特定的功能。每个层级都构建在其下方的层级之上,并为上方的层级提供服务。七层从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。虽然OSI模型在理论上更全面,但在实际网络通信中,TCP/IP模型更为实用。TCP/IP模型分为四个层级,每个层级负责特定的网络功能。
1应用层:该层与OSI模型的应用层和表示层以及会话层类似,提供直接与用户应用程序交互的接口。它为网络上的各种应用程序提供服务,如电子邮件(SMTP)、网页浏览(HTTP)、文件传输(FTP)等。
2传输层:该层对应OSI模型的传输层。它负责端到端的数据传输,提供可靠的、无连接的数据传输服务。主要的传输层协议有TCP和UDP。TCP提供可靠的数据传输,确保数据的正确性和完整性;而UDP则是无连接的,适用于不要求可靠性的传输,如实时音频和视频流。
3网际层:该层对应OSI模型的网络层。主要协议是IP,它负责数据包的路由和转发,选择最佳路径将数据从源主机传输到目标主机。IP协议使用IP地址来标识主机和网络,并进行逻辑地址寻址。
4网络接口层:该层对应OSI模型的数据链路层和物理层。它负责物理传输媒介的传输,例如以太网、Wi-Fi等,并提供错误检测和纠正的功能。此外,网络接口层还包含硬件地址(MAC地址)的管理。
从输入URL到页面展示发生了什么
1输入网址,解析URL信息,准备发送HTTP请求
2检查浏览器缓存里是否有缓存该资源,如果有直接返回;如果没有进入下一步网络请求。
3DNS域名解析:网络请求前,进行DNS解析,以获取请求域名的IP地址。DNS解析时会按本地浏览器缓存->本地Host文件->路由器缓存->DNS服务器->根DNS服务器的顺序查询域名对应IP,直到找到为止。
4TCP三次握手建立连接:浏览器与服务器IP建立TCP连接。
5客户端发送HTTP请求:连接建立后,浏览器端会构建请求行、请求头等信息,并把和该域名相关的Cookie等数据附加到请求头中,向服务器构建请求信息。如果是HTTPS的话,还涉及到HTTPS的加解密流程。
6服务器处理请求并返回HTTP资源:服务器接收到请求信息,根据请求生成响应数据。
7TCP四次挥手断开连接:浏览器与服务器IP断开TCP连接。
8浏览器解析响应并渲染页面:
●浏览器解析响应头。若响应头状态码为301、302,会重定向到新地址;若响应数据类型是字节流类型,一般会将请求提交给下载管理器;若是HTML类型,会进入下一部渲染流程。
●浏览器解析HTML文件,创建DOM树,解析CSS进行样式计算,然后将CSS和DOM合并,构建渲染树;最后布局和绘制渲染树,完成页面展示。
HTTP请求报文和响应报文是怎样的,有哪些常见的字段?
HTTP报文分为请求报文和响应报文。
(1) 请求报文 请求报文主要由请求行、请求头、空行、请求体构成。 请求行包括如下字段:
●方法(Method):指定要执行的操作,如 GET、POST、PUT、DELETE 等。
●资源路径(Resource Path):请求的资源的URI(统一资源标识符)。
●HTTP版本(HTTP Version):使用的HTTP协议版本,如 HTTP/1.1 或 HTTP/2.0。
请求头的字段较多,常使用的包含以下几个:
●Host:请求的服务器的域名。
●Accept:客户端能够处理的媒体类型。
●Accept-Encoding:客户端能够解码的内容编码。
●Authorization:用于认证的凭证信息,比如token数据。
●Content-Length:请求体的长度。
●Content-Type:请求体的媒体类型。
●Cookie:存储在客户端的cookie数据。
●If-None-Match:资源的ETag值,用于缓存控制。
●Connection:管理连接的选项,如 keep-alive。
空行是请求头部和请求主体之间的空行,用于分隔请求头部和请求主体。而请求体通常用于 POST 和 PUT 请求,包含发送给服务器的数据。
(2) 响应报文
HTTP响应报文是服务器向客户端返回的数据格式,用于传达服务器对客户端请求的处理结果以及相关的数据。一个标准的HTTP响应报文通常包含状态行、响应头、空行、响应体。
状态行包含HTTP版本、状态码和状态消息。例如:HTTP/1.1 200 OK
响应头部也是以键值对的形式提供的额外信息,类似于请求头部,用于告知客户端有关响应的详细信息。一些常见的响应头部字段包括:
●Content-Type:指定响应主体的媒体类型。
●Content-Length:指定响应主体的长度(字节数)。
●Server:指定服务器的信息。
●Expires: 响应的过期时间,之后内容被认为是过时的。
●ETag: 响应体的实体标签,用于缓存和条件请求。
●Last-Modified: 资源最后被修改的日期和时间。
●Location:在重定向时指定新的资源位置。
●Set-Cookie:在响应中设置Cookie。
●Access-Control-Allow-Origin: 跨源资源共享(CORS)策略,指示哪些域可以访问资源。
空行(Empty Line)在响应头和响应体之间,表示响应头的结束。而响应体是服务端实际传输的数据,可以是文本、HTML页面、图片、视频等,也可能为空。
HTTP有哪些请求方式?GET请求和POST请求的区别
HTTP请求方式:
1GET:请求指定的资源。
2POST:向指定资源提交数据进行处理请求(例如表单提交)。
3PUT:更新指定资源。
4DELETE:删除指定资源。
5HEAD:获取报文首部,不返回报文主体。
6OPTIONS:查询服务器支持的请求方法。
7PATCH:对资源进行部分更新。
GET请求和POST请求的区别:
1用途:GET请求通常用于获取数据,POST请求用于提交数据。
2数据传输:GET请求将参数附加在URL之后,POST请求将数据放在请求体中。
3安全性:GET请求由于参数暴露在URL中,安全性较低;POST请求参数不会暴露在URL中,相对更安全。
4数据大小:GET请求受到URL长度限制,数据量有限;POST请求理论上没有大小限制。
5幂等性:GET请求是幂等的,即多次执行相同的GET请求,资源的状态不会改变;POST请求不是幂等的,因为每次提交都可能改变资源状态。
6缓存:GET请求可以被缓存,POST请求默认不会被缓存。
HTTP请求中常见的状态码
1XX:提示信息,协议处理的中间状态
200:(成功)服务器已成功处理了请求.通常,这表示服务器提供了请求的网页.
201(已创建)请求成功并且服务器创建了新的资源.
(已接受)服务器已接受请求,但尚未处理.
202
2XX:请求成功
(非授权信息)服务器已成功处理了请求,但返回的信息可能来自另一来源.
203
服务器成功处理了请求,但没有返回任何内容.
(无内容)
204
服务器成功处理了部分GET请求,服务器返回的BODY数据是资
(部分内容)
206
源的一部分
(永久重定向)请求的网页已永久移动到新位置.
301
HTTP状态码
(临时重定向),说明请求的资源还在,但暂时需要用另一个URL来访问.
302
3XX:请求重定向
(未修改)自从上次请求后,请求的网页未修改过.服务器返回此响应时,不
304
会返回网页内容,重定向到已存在的缓存文件.
(未授权)请求要求身份验证.对于需要登录的网页,服务器可能返回此响
401
应.
4XX:请求错误
(禁止)服务器拒绝请求.
403
(未找到)服务器找不到请求的网页.
404
500
(服务器内部错误)服务器遇到错误,无法完成请求.
(尚未实施)服务器不具备完成请求的功能.
501
(错误网关)服务器作为网关或代理,从上游服务器收到无效响应.
502
5XX:服务器错误
(服务不可用)服务器目前无法使用(由于超载或停机维护).通常,这只是
503
暂时状态.
(网关超时)
服务器作为网关或代理,但是没有及时从上游服务器收到请求.
504
HTTP请求中常用的状态码包括以下几个:
200:表示客户端请求成功
201:创建了新资源。
204 :无内容,服务器成功处理请求,但未返回任何内容。
301:永久重定向
302: 临时重定向
304:请求的内容没有修改过,所以服务器返回此响应时,不会返回网页内容,而是使用缓存
401:请求需要身份验证
403:请求的对应资源禁止被访问
404:服务器无法找到对应资源
500:服务器内部错误
503: 服务不可用
什么是强缓存和协商缓存
强缓存和协商缓存是HTTP缓存机制的两种类型,它们用于减少服务器的负担和提高网页加载速度。
1强缓存:客户端在没有向服务器发送请求的情况下,直接从本地缓存中获取资源。强缓存通过HTTP响应头中的Cache-Control字段实现,如max-age,告诉浏览器在指定时间内可以直接使用缓存数据,无需再次请求。
2协商缓存:当强缓存失效时,浏览器会发送请求到服务器,通过ETag或Last-Modified等HTTP响应头与服务器进行验证,以确定资源是否被修改。如果资源未修改,服务器返回304 Not Modified状态码,告知浏览器使用本地缓存;如果资源已修改,则返回新的资源,浏览器更新本地缓存。这种方式需要与服务器通信,但可以确保用户总是获取最新的内容。
强缓存和协商缓存是HTTP缓存机制的两种类型,它们用于减少服务器的负担和提高网页加载速度。
1强缓存:客户端在没有向服务器发送请求的情况下,直接从本地缓存中获取资源。
●Expires强缓存:设置一个强缓存时间,此时间范围内,从内存中读取缓存并返回。但是因为Expires判断强缓存过期的机制是获取本地时间戳,与之前拿到的资源文件中的Expires字段的时间做比较来判断是否需要对服务器发起请求。这里有一个巨大的漏洞:“如果我本地时间不准咋办?”所以目前已经被废弃了。
●Cache-Control强缓存:目前使用的强缓存是通过HTTP响应头中的Cache-Control字段实现,通过max-age来告诉浏览器在指定时间内可以直接使用缓存数据,无需再次请求。
1协商缓存:当强缓存失效时,浏览器会发送请求到服务器,通过ETag或Last-Modified等HTTP响应头与服务器进行验证,以确定资源是否被修改。如果资源未修改,服务器返回304 Not Modified状态码,告知浏览器使用本地缓存;如果资源已修改,则返回新的资源,浏览器更新本地缓存。这种方式需要与服务器通信,但可以确保用户总是获取最新的内容。
●基于Last-Modified的协商缓存
○Last-Modified 是资源的最后修改时间,服务器在响应头部中返回。
○当客户端读取到Last-modified的时候,会在下次的请求标头中携带一个字段:If-Modified-Since,而这个请求头中的If-Modified-Since就是服务器第一次修改时候给他的时间。
○服务器比较请求中的 If-Modified-Since 值与当前资源的 Last-Modified 值,如果比对的结果是没有变化,表示资源未发生变化,返回状态码 304 Not Modified。如果比对的结果说资源已经更新了,就会给浏览器正常返回资源,返回200状态。
但是这样的协商缓存有两个缺点:
○因为是更改文件修改时间来判断的,所以在文件内容本身不修改的情况下,依然有可能更新文件修改时间(比如修改文件名再改回来),这样,就有可能文件内容明明没有修改,但是缓存依然失效了。
○当文件在极短时间内完成修改的时候(比如几百毫秒)。因为文件修改时间记录的最小单位是秒,所以,如果文件在几百毫秒内完成修改的话,文件修改时间不会改变,这样,即使文件内容修改了,依然不会返回新的文件。
●基于ETag的协商缓存:将原先协商缓存的比较时间戳的形式修改成了比较文件指纹(根据文件内容计算出的唯一哈希值)。
○ETag 是服务器为资源生成的唯一标识符(文件指纹),可以是根据文件内容计算出的哈希值,服务端将其和资源一起放回给客户端。
○客户端在请求头部的 If-None-Match 字段中携带上次响应的 ETag 值。
○服务器比较请求中的 If-None-Match 值与当前资源的 ETag 值,如果匹配,表示资源未发生变化,返回状态码 304 Not Modified。如果两个文件指纹不吻合,则说明文件被更改,那么将新的文件指纹重新存储到响应头的ETag中并返回给客户端
HTTP1.0和HTTP1.1的区别
1持久连接:HTTP/1.1 默认支持持久连接,允许在一个TCP连接上发送多个HTTP请求和响应,减少了连接建立和关闭的开销。而HTTP/1.0 默认为短连接,每次请求都需要建立一个TCP连接,并通过Connection: keep-alive头来实现持久连接。
2管道化:HTTP/1.1 支持管道化,允许客户端在第一个请求的响应到达之前发送多个请求,这可以减少等待时间,提高效率。HTTP/1.0不支持管道化。
3缓存控制:HTTP1.0主要使用If-Modified-Since/Expires来做为缓存判断的标准,而HTTP1.1则引入了更多的缓存控制策略例如Etag / If-None-Match等更多可供选择的缓存头来控制缓存策略。
4错误处理:HTTP/1.1 增加了一些新的HTTP状态码,如100 Continue,用于增强错误处理和请求的中间响应。
5Host 头:HTTP/1.1 引入了Host头,允许客户端指定请求的主机名,这使得在同一台服务器上托管多个域名成为可能。HTTP/1.0没有这个头字段。
6带宽优化 :HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能, 而HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content)
HTTP2.0与HTTP1.1的区别?
1二进制协议:HTTP/2.0 采用二进制格式传输数据,而非HTTP/1.1 的文本格式,使得解析更高效,减少了解析时间。
2多路复用:HTTP/2.0 支持多路复用,允许在单个TCP连接上并行交错发送多个请求和响应,解决了HTTP/1.1 中的队头阻塞问题。
3头部压缩:HTTP/2.0 引入了HPACK 压缩算法,对请求和响应的头部信息进行压缩,减少了冗余头部信息的传输,提高了传输效率。
4服务器推送:HTTP/2.0 允许服务器主动推送资源给客户端,而不需要客户端明确请求,这可以减少页面加载时间。
5优先级和依赖:HTTP/2.0 允许客户端为请求设置优先级,并表达请求之间的依赖关系,资源加载更加有序。
HTTP3.0有了解过吗?
HTTP/3是HTTP协议的最新版本,它基于QUIC协议,具有以下特点:
1无队头阻塞: QUIC 使用UDP协议来传输数据。一个连接上的多个stream之间没有依赖, 如果一个stream丢了一个UDP包,不会影响后面的stream,不存在 队头阻塞问题。
2零 RTT 连接建立:首次连接肯定是需要1 RTT的,0 RTT的优势是在连接的后续建立的 ,从而减少了连接延迟,加快了页面加载速度。
3连接迁移:QUIC 允许在网络切换(如从 Wi-Fi 到移动网络)时,将连接迁移到新的 IP 地址,从而减少连接的中断时间。
4优化的可靠性机制(取代早期 FEC):前向纠错(FEC)的演进,早期 QUIC(gQUIC)曾引入 FEC,通过数据包冗余减少重传,但因协议复杂度和带宽成本过高,在 IETF 标准化版本(RFC 9000)中被移除。当前方案,依赖选择性重传(SACK)、自适应拥塞控制及快速丢包检测保障可靠性,同时通过流优先级和流量控制优化资源分配。
5安全性:HTTP/3默认使用TLS加密,确保了数据传输的安全性。
HTTPS和HTTP有哪些区别
两者的主要区别在于安全性和数据加密:
1加密层:HTTPS 在HTTP 的基础上增加了SSL/TLS 协议作为加密层,确保数据传输的安全性。
2数据安全:HTTPS 通过加密,保护数据在传输过程中不被窃听或篡改,而HTTP 数据传输是明文的,容易受到攻击。
3端口:HTTPS 通常使用端口443 ,而HTTP 使用端口80。
HTTPS工作原理
HTTPS 主要基于SSL/TLS 协议,确保了数据传输的安全性和完整性, 其建立连接并传输数据的过程如下:
1密钥交换:客户端发起HTTPS请求后,服务器会发送其公钥证书给客户端。
2证书验证:客户端会验证服务器的证书是否由受信任的证书颁发机构(CA )签发,并检查证书的有效性。
3加密通信:一旦证书验证通过,客户端会生成一个随机的对称加密密钥,并使用服务器的公钥加密这个密钥,然后发送给服务器。
4建立安全连接:服务器使用自己的私钥解密得到对称加密密钥,此时客户端和服务器都有了相同的密钥,可以进行加密和解密操作。
5数据传输:使用对称加密密钥对所有传输的数据进行加密,确保数据在传输过程中的安全性。
6完整性校验:SSL/TLS协议还包括消息完整性校验机制,如消息认证码,确保数据在传输过程中未被篡改。
7结束连接:数据传输完成后,通信双方会进行会话密钥的销毁,以确保不会留下安全隐患。
TCP和UDP的区别
1TCP是面向连接的协议,需要在数据传输前建立连接;UDP是无连接的,不需要建立连接。
2TCP提供可靠的数据传输,保证数据包的顺序和完整性;UDP不保证数据包的顺序或完整性。
3TCP具有拥塞控制机制,可以根据网络状况调整数据传输速率;UDP没有拥塞控制,发送速率通常固定。
4TCP通过滑动窗口机制进行流量控制,避免接收方处理不过来;UDP没有流量控制。
5TCP能够检测并重传丢失或损坏的数据包;UDP不提供错误恢复机制。
6TCP有复杂的报文头部,包含序列号、确认号等信息;UDP的报文头部相对简单。
7由于TCP的连接建立、数据校验和重传机制,其性能开销通常比UDP大;UDP由于简单,性能开销小。
8适用场景:TCP适用于需要可靠传输的应用,如网页浏览、文件传输等;UDP适用于对实时性要求高的应用,如语音通话、视频会议等。
TCP连接如何确保可靠性
TCP通过序列号、确认应答、超时重传、数据校验、流量控制、拥塞控制等机制,确保了数据传输的可靠性和效率。
1序列号:每个TCP段都有一个序列号,确保数据包的顺序正确。
2确认应答:接收方发送ACK确认收到的数据,如果发送方在一定时间内没有收到确认,会重新发送数据。
3超时重传:发送方设置一个定时器,如果在定时器超时之前没有收到确认,发送方会重传数据。
4数据校验:TCP使用校验和来检测数据在传输过程中是否出现错误,如果检测到错误,接收方会丢弃该数据包,并等待重传。
5流量控制:TCP通过滑动窗口机制进行流量控制,确保接收方能够处理发送方的数据量。
6拥塞控制:TCP通过算法如慢启动、拥塞避免、快重传和快恢复等,来控制数据的发送速率,防止网络拥塞。
TCP 拥塞控制机制
TCP拥塞控制可以在网络出现拥塞时动态地调整数据传输的速率,以防止网络过载。TCP拥塞控制的主要机制包括以下几个方面:
1慢启动(Slow Start): 初始阶段,TCP发送方会以较小的发送窗口开始传输数据。随着每次成功收到确认的数据,发送方逐渐增加发送窗口的大小,实现指数级的增长,这称为慢启动。这有助于在网络刚开始传输时谨慎地逐步增加速率,以避免引发拥塞。
2拥塞避免(Congestion Avoidance): 一旦达到一定的阈值(通常是慢启动阈值),TCP发送方就会进入拥塞避免阶段。在拥塞避免阶段,发送方以线性增加的方式增加发送窗口的大小,而不再是指数级的增长。这有助于控制发送速率,以避免引起网络拥塞。
3快速重传(Fast Retransmit): 如果发送方连续收到相同的确认,它会认为发生了数据包的丢失,并会快速重传未确认的数据包,而不必等待超时。这有助于更快地恢复由于拥塞引起的数据包丢失。
4快速恢复(Fast Recovery): 在发生快速重传后,TCP进入快速恢复阶段。在这个阶段,发送方不会回到慢启动阶段,而是将慢启动阈值设置为当前窗口的一半,并将拥塞窗口大小设置为慢启动阈值加上已确认但未被快速重传的数据块的数量。这有助于更快地从拥塞中恢复。
TCP 流量控制机制
流量控制就是让发送方发送速率不要过快,让接收方来得及接收。利用滑动窗口机制就可以实施流量控制,主要方法就是动态调整发送方和接收方之间数据传输速率。
●滑动窗口大小: 在TCP通信中,每个TCP报文段都包含一个窗口字段,该字段指示发送方可以发送多少字节的数据而不等待确认。这个窗口大小是动态调整的。
●接收方窗口大小: 接收方通过TCP报文中的窗口字段告诉发送方自己当前的可接收窗口大小。这是接收方缓冲区中还有多少可用空间。
●流量控制的目标: 流量控制的目标是确保发送方不要发送超过接收方缓冲区容量的数据。如果接收方的缓冲区快满了,它会减小窗口大小,通知发送方暂停发送,以防止溢出。
●动态调整: 发送方会根据接收方的窗口大小动态调整发送数据的速率。如果接收方的窗口大小增加,发送方可以加速发送数据。如果窗口大小减小,发送方将减缓发送数据的速率。
●确认机制: 接收方会定期发送确认(ACK)报文,告知发送方已成功接收数据。这也与流量控制密切相关,因为接收方可以通过ACK报文中的窗口字段来通知发送方它的当前窗口大小。
UDP怎么实现可靠传输
UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。关键在于两点,从应用层角度考虑:
(1)提供超时重传,能避免数据报丢失。
(2)提供确认序列号,可以对数据报进行确认和排序。
本端:首先在UDP数据报定义一个首部,首部包含确认序列号和时间戳,时间戳是用来计算RTT(数据报传输的往返时间),计算出合适的RTO(重传的超时时间)。然后以等-停的方式发送数据报,即收到对端的确认之后才发送下一个的数据报。当时间超时,本端重传数据报,同时RTO扩大为原来的两倍,重新开始计时。
对端:接受到一个数据报之后取下该数据报首部的时间戳和确认序列号,并添加本端的确认数据报首部之后发送给对段。根据此序列号对已收到的数据报进行排序并丢弃重复的数据报。
三次握手的过程,为什么是三次
(1) 三次握手的过程
1第一次握手:客户端向服务器发送一个SYN (同步序列编号)报文,请求建立连接,客户端进入SYN_SENT 状态。
2第二次握手:服务器收到SYN 报文后,如果同意建立连接,则会发送一个SYN-ACK (同步确认)报文作为响应,同时进入SYN_RCVD 状态。
3第三次握手:客户端收到服务器的SYN-ACK 报文后,会发送一个ACK (确认)报文作为最终响应,之后客户端和服务器都进入ESTABLISHED 状态,连接建立成功。
(2)为什么需要三次握手
通过三次握手,客户端和服务器都能够确认对方的接收和发送能力。第一次握手确认了客户端到服务器的通道是开放的;第二次握手确认了服务器到客户端的通道是开放的;第三次握手则确认了客户端接收到服务器的确认,从而确保了双方的通道都是可用的。
而如果仅使用两次握手,服务器可能无法确定客户端的接收能力是否正常,比如客户端可能已经关闭了连接,但之前发送的连接请求报文在网络上延迟到达了服务器,服务器就会主动去建立一个连接,但是客户端接收不到,导致资源的浪费。而四次握手可以优化为三次。
四次挥手的过程,为什么是四次
(1)四次挥手的过程
1第一次挥手:客户端发送一个FIN报文给服务端,表示自己要断开数据传送,报文中会指定一个序列号 (seq=x)。然后,客户端进入FIN-WAIT-1状态。
2第二次挥手:服务端收到FIN报文后,回复ACK报文给客户端,且把客户端的序列号值+1,作为ACK+1报文的序列号(seq=x+1)。然后,服务端进入CLOSE-WAIT``(seq=x+1)状态,客户端进入FIN-WAIT-2状态。
3第三次挥手:服务端也要断开连接时,发送FIN报文给客户端,且指定一个序列号(seq=y+1),随后服务端进入LAST-ACK状态。
4第四次挥手:客户端收到FIN报文后,发出ACK报文进行应答,并把服务端的序列号值+1作为ACK报文序列号(seq=y+2)。此时客户端进入TIME-WAIT状态。服务端在收到客户端的ACK报文后进入CLOSE 状态。如果客户端等待2MSL没有收到回复,才关闭连接。
(2)为什么需要四次挥手
TCP是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。 当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后才会完全关闭TCP 连接。因此两次握手可以释放一端到另一端的TCP连接,完全释放连接一共需要四次握手。
只有通过四次挥手,才可以确保双方都能接收到对方的最后一个数据段的确认,主动关闭方在发送完最后一个ACK后进入TIME-WAIT 状态,这是为了确保被动关闭方接收到最终的ACK ,如果被动关闭方没有接收到,它可以重发FIN 报文,主动关闭方可以再次发送ACK 。
而如果使用三次挥手,被动关闭方可能在发送最后一个数据段后立即关闭连接,而主动关闭方可能还没有接收到这个数据段的确认。
HTTP的Keep-Alive是什么?TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?
1HTTP 的 Keep-Alive,是由应用层实现的,称为 HTTP 长连接
每次请求都要经历这样的过程:建立 TCP连接 -> HTTP请求资源 -> 响应资源 -> 释放连接,这就是HTTP短连接,但是这样每次建立连接都只能请求一次资源,所以HTTP的 Keep-Alive实现了使用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,避免了连接建立和释放的开销,就就是 HTTP 长连接。通过设置HTTP头Connection: keep-alive来实现。
1TCP 的 Keepalive,是由TCP层(内核态)实现的,称为 TCP保活机制,是一种用于在 TCP连接上检测空闲连接状态的机制
当TCP连接建立后,如果一段时间内没有任何数据传输,TCP Keepalive会发送探测包来检查连接是否仍然有效。
DNS查询过程
DNS 用来将主机名和域名转换为IP地址, 其查询过程一般通过以下步骤:
1本地DNS缓存检查:首先查询本地DNS缓存,如果缓存中有对应的IP地址,则直接返回结果。
2如果本地缓存中没有,则会向本地的DNS服务器(通常由你的互联网服务提供商(ISP)提供, 比如中国移动)发送一个DNS查询请求。
3如果本地DNS解析器有该域名的ip地址,就会直接返回,如果没有缓存该域名的解析记录,它会向根DNS服务器发出查询请求。根DNS服务器并不负责解析域名,但它能告诉本地DNS解析器应该向哪个顶级域(.com/.net/.org)的DNS服务器继续查询。
4本地DNS解析器接着向指定的顶级域名DNS服务器发出查询请求。顶级域DNS服务器也不负责具体的域名解析,但它能告诉本地DNS解析器应该前往哪个权威DNS服务器查询下一步的信息。
5本地DNS解析器最后向权威DNS服务器发送查询请求。 权威DNS服务器是负责存储特定域名和IP地址映射的服务器。当权威DNS服务器收到查询请求时,它会查找”example.com”域名对应的IP地址,并将结果返回给本地DNS解析器。
6本地DNS解析器将收到的IP地址返回给浏览器,并且还会将域名解析结果缓存在本地,以便下次访问时更快地响应。
7浏览器发起连接: 本地DNS解析器已经将IP地址返回给您的计算机,您的浏览器可以使用该IP地址与目标服务器建立连接,开始获取网页内容。
CDN是什么
CDN是一种分布式网络服务,通过将内容存储在分布式的服务器上,使用户可以从距离较近的服务器获取所需的内容,从而加速互联网上的内容传输。
●就近访问:CDN 在全球范围内部署了多个服务器节点,用户的请求会被路由到距离最近的 CDN 节点,提供快速的内容访问。
●内容缓存:CDN 节点会缓存静态资源,如图片、样式表、脚本等。当用户请求访问这些资源时,CDN 会首先检查是否已经缓存了该资源。如果有缓存,CDN 节点会直接返回缓存的资源,如果没有缓存所需资源,它会从源服务器(原始服务器)回源获取资源,并将资源缓存到节点中,以便以后的请求。通过缓存内容,减少了对原始服务器的请求,减轻了源站的负载。
●可用性:即使某些节点出现问题,用户请求可以被重定向到其他健康的节点。
Cookie和Session是什么?有什么区别?
(1) Cookie和Session是什么?
Cookie和 Session都用于管理用户的状态和身份, Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
1Cookie
●通常,服务器会将一个或多个Cookie 发送到用户浏览器,然后浏览器将这些 Cookie 存储在本地。
●服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。
1Session
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。Session 主要用于维护用户登录状态、存储用户的临时数据和上下文信息等。服务器为每个用户分配一个唯一的Session ID,通常存储在Cookie中。
(2) Cookie和Session的区别?
●存储位置:Cookie 数据存储在用户的浏览器中,而 Session 数据存储在服务器上。
●数据容量:Cookie 存储容量较小,一般为几 KB。Session 存储容量较大,通常没有固定限制,取决于服务器的配置和资源。
●安全性:由于 Cookie 存储在用户浏览器中,因此可以被用户读取和篡改。相比之下,Session 数据存储在服务器上,更难被用户访问和修改。
●生命周期:Cookie可以设置过期时间,Session 依赖于会话的持续时间或用户活动。
●传输方式:Cookie 在每次 HTTP 请求中都会被自动发送到服务器,而 Session ID 通常通过Cookie 或 URL 参数传递。
操作系统
进程和线程的区别
进程是资源分配和调度的基本单位。
线程是程序执行的最小单位,线程是进程的子任务,是进程内的执行单元。 一个进程至少有一个线程,一个进程可以运行多个线程,这些线程共享同一块内存。
资源开销:
●进程:由于每个进程都有独立的内存空间,创建和销毁进程的开销较大。进程间切换需要保存和恢复整个进程的状态,因此上下文切换的开销较高。
●线程:线程共享相同的内存空间,创建和销毁线程的开销较小。线程间切换只需要保存和恢复少量的线程上下文,因此上下文切换的开销较小。
通信与同步:
●进程:由于进程间相互隔离,进程之间的通信需要使用一些特殊机制,如管道、消息队列、共享内存等。
●线程:由于线程共享相同的内存空间,它们之间可以直接访问共享数据,线程间通信更加方便。
安全性:
●进程:由于进程间相互隔离,一个进程的崩溃不会直接影响其他进程的稳定性。
●线程:由于线程共享相同的内存空间,一个线程的错误可能会影响整个进程的稳定性。
并行和并发有什么区别
●并行是在同一时刻执行多个任务。
●并发是在相同的时间段内执行多个任务,任务可能交替执行,通过调度实现。
并行是指在同一时刻执行多个任务,这些任务可以同时进行,每个任务都在不同的处理单元(如多个CPU核心)上执行。在并行系统中,多个处理单元可以同时处理独立的子任务,从而加速整体任务的完成。
并发是指在相同的时间段内执行多个任务,这些任务可能不是同时发生的,而是交替执行,通过时间片轮转或者事件驱动的方式。并发通常与任务之间的交替执行和任务调度有关。
解释一下用户态和核心态
1用户态和内核态的区别
用户态和内核态是操作系统为了保护系统资源和实现权限控制而设计的两种不同的CPU运行级别,可以控制进程或程序对计算机硬件资源的访问权限和操作范围。
●用户态:在用户态下,进程或程序只能访问受限的资源和执行受限的指令集,不能直接访问操作系统的核心部分,也不能直接访问硬件资源。
●核心态:核心态是操作系统的特权级别,允许进程或程序执行特权指令和访问操作系统的核心部分。在核心态下,进程可以直接访问硬件资源,执行系统调用,管理内存、文件系统等操作。
1在什么场景下,会发生内核态和用户态的切换
●系统调用:当用户程序需要请求操作系统提供的服务时,会通过系统调用进入内核态。
●异常:当程序执行过程中出现错误或异常情况时,CPU会自动切换到内核态,以便操作系统能够处理这些异常。
●中断:外部设备(如键盘、鼠标、磁盘等)产生的中断信号会使CPU从用户态切换到内核态。操作系统会处理这些中断,执行相应的中断处理程序,然后再将CPU切换回用户态。
进程调度算法你了解多少
●先来先服务:按照请求的顺序进行调度。 这种调度方式简单,但是能导致较长作业阻塞较短作业。
●最短作业优先:非抢占式的调度算法,按估计运行时间最短的顺序进行调度。 但是如果一直有短作业到来,那么长作业永远得不到调度,造成长作业“饥饿”现象。
●最短剩余时间优先:基于最短作业优先改进,按剩余运行时间的顺序进行调度。当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
●优先级调度:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
●时间片轮转:为每个进程分配一个时间片,进程轮流执行,时间片用完后切换到下一个进程。
●多级队列:时间片轮转调度算法和优先级调度算法的结合。 将进程分为不同的优先级队列,每个队列有自己的调度算法。
进程间有哪些通信方式
1管道:是一种半双工的通信方式,数据只能单向流动而且只能在具有父子进程关系的进程间使用。
2命名管道: 类似管道,也是半双工的通信方式,但是它允许在不相关的进程间通信。
3消息队列:允许进程发送和接收消息,而消息队列是消息的链表,可以设置消息优先级。
4信号:用于发送通知到进程,告知其发生了某种事件或条件。
5信号量:是一个计数器,可以用来控制多个进程对共享资源的访问,常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此主要作为进程间以及同一进程内不同线程之间的同步手段。
6共享内存:就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的进程通信方式,
7Socket套接字:是支持TCP/IP 的网络通信的基本操作单元,主要用于在客户端和服务器之间通过网络进行通信。
8互斥锁:一种信号量,用于保护共享数据结构,防止多个进程同时访问。
9条件变量:与互斥锁配合使用,用于进程间的同步,等待某些条件成立。
解释一下进程同步和互斥,以及如何实现进程同步和互斥
进程同步是指多个并发执行的进程之间协调和管理它们的执行顺序,以确保它们按照一定的顺序或时间间隔执行。
互斥指的是在某一时刻只允许一个进程访问某个共享资源。当一个进程正在使用共享资源时,其他进程不能同时访问该资源。
解决进程同步和互斥的问题有很多种方法,其中一种常见的方法是使用信号量和 PV 操作。信号量是一种特殊的变量,它表示系统中某种资源的数量或者状态。PV 操作是一种对信号量进行增加或者减少的操作,它们可以用来控制进程之间的同步或者互斥。
●P操作:相当于“检查”信号量,如果资源可用,就减少计数,然后使用资源。
●V操作:相当于“归还”资源,增加信号量的计数,并可能唤醒等待的进程。
除此之外,下面的方法也可以解决进程同步和互斥问题:
●临界区:将可能引发互斥问题的代码段称为临界区,里面包含了需要互斥访问的资源。进入这个区域前需要先获取锁,退出临界区后释放该锁。这确保同一时间只有一个进程可以进入临界区。
●互斥锁(Mutex):互斥锁是一种同步机制,用于实现互斥。每个共享资源都关联一个互斥锁,进程在访问该资源前需要先获取互斥锁,使用完后释放锁。只有获得锁的进程才能访问共享资源。
●条件变量:条件变量用于在进程之间传递信息,以便它们在特定条件下等待或唤醒。通常与互斥锁一起使用,以确保等待和唤醒的操作在正确的时机执行。
什么是死锁,如何预防死锁?
死锁是系统中两个或多个进程在执行过程中,因争夺资源而造成的一种僵局。当每个进程都持有一定的资源并等待其他进程释放它们所需的资源时,如果这些资源都被其他进程占有且不释放,就导致了死锁。
死锁只有同时满足以下四个条件才会发生:
●互斥条件:一个进程占用了某个资源时,其他进程无法同时占用该资源。
●请求保持条件:一个线程因为请求资源而阻塞的时候,不会释放自己的资源。
●不可剥夺条件:资源不能被强制性地从一个进程中剥夺,只能由持有者自愿释放。
●循环等待条件:多个进程之间形成一个循环等待资源的链,每个进程都在等待下一个进程所占有的资源。
避免死锁:通过破坏死锁的四个必要条件之一来预防死锁。比如破坏循环等待条件,让所有进程按照相同的顺序请求资源。检测死锁:通过检测系统中的资源分配情况来判断是否存在死锁。例如,可以使用资源分配图或银行家算法进行检测。解除死锁:一旦检测到死锁存在,可以采取一些措施来解除死锁。例如,可以通过抢占资源、终止某些进程或进行资源回收等方式来解除死锁。
讲一讲你理解的虚拟内存
虚拟内存是指在每一个进程创建加载的过程中,会分配一个连续虚拟地址空间,它不是真实存在的,而是通过映射与实际物理地址空间对应,这样就可以使每个进程看起来都有自己独立的连续地址空间,并允许程序访问比物理内存RAM更大的地址空间, 每个程序都可以认为它拥有足够的内存来运行。
需要虚拟内存的原因:
●内存扩展: 虚拟内存使得每个程序都可以使用比实际可用内存更多的内存,从而允许运行更大的程序或处理更多的数据。
●内存隔离:虚拟内存还提供了进程之间的内存隔离。每个进程都有自己的虚拟地址空间,因此一个进程无法直接访问另一个进程的内存。
●物理内存管理:虚拟内存允许操作系统动态地将数据和程序的部分加载到物理内存中,以满足当前正在运行的进程的需求。当物理内存不足时,操作系统可以将不常用的数据或程序暂时移到硬盘上,从而释放内存,以便其他进程使用。
●页面交换:当物理内存不足时,操作系统可以将一部分数据从物理内存写入到硬盘的虚拟内存中,这个过程被称为页面交换。当需要时,数据可以再次从虚拟内存中加载到物理内存中。这样可以保证系统可以继续运行,尽管物理内存有限。
●内存映射文件:虚拟内存还可以用于将文件映射到内存中,这使得文件的读取和写入可以像访问内存一样高效。
你知道的线程同步的方式有哪些?
线程同步机制是指在多线程编程中,为了保证线程之间的互不干扰,而采用的一种机制。常见的线程同步机制有以下几种:
1互斥锁:互斥锁是最常见的线程同步机制。它允许只有一个线程同时访问被保护的临界区(共享资源)
2条件变量:条件变量用于线程间通信,允许一个线程等待某个条件满足,而其他线程可以发出信号通知等待线程。通常与互斥锁一起使用。
3读写锁: 读写锁允许多个线程同时读取共享资源,但只允许一个线程写入资源。
4信号量:用于控制多个线程对共享资源进行访问的工具。
介绍一下几种典型的锁
●互斥锁:互斥锁是一种最常见的锁类型,用于实现互斥访问共享资源。在任何时刻,只有一个线程可以持有互斥锁,其他线程必须等待直到锁被释放。这确保了同一时间只有一个线程能够访问被保护的资源。
●自旋锁:自旋锁是一种基于忙等待的锁,即线程在尝试获取锁时会不断轮询,直到锁被释放。
其他的锁都是基于这两个锁的
●读写锁:允许多个线程同时读共享资源,只允许一个线程进行写操作。分为读(共享)和写(排他)两种状态。
●悲观锁:认为多线程同时修改共享资源的概率比较高,所以访问共享资源时候要上锁
●乐观锁:先不管,修改了共享资源再说,如果出现同时修改的情况,再放弃本次操作。
有哪些页面置换算法
常见页面置换算法有最佳置换算法(OPT)、先进先出(FIFO)、最近最久未使用算法(LRU)、时钟算法(Clock) 等。
1最近最久未使用算法LRU :LRU算法基于页面的使用历史,通过选择最长时间未被使用的页面进行置换。
2先进先出FIFO算法:也就是最先进入内存的页面最先被置换出去。
3最不经常使用LFU :淘汰访问次数最少的页面,考虑页面的访问频率。
4时钟算法CLOCK:Clock算法的核心思想是通过使用一个指针(称为时钟指针)在环形链表上遍历,检查页面是否被访问过, 当需要进行页面置换时,Clock算法从时钟指针的位置开始遍历环形链表。 如果当前页面的访问位为0,表示该页面最久未被访问,可以选择进行置换。将访问位设置为1,继续遍历下一个页面。 如果当前页面的访问位为1,表示该页面最近被访问过,它仍然处于活跃状态。将访问位设置为0,并继续遍历下一个页面如果遍历过程中找到一个访问位为0的页面,那么选择该页面进行置换。
5最佳置换算法: 该算法根据未来的页面访问情况,选择最长时间内不会被访问到的页面进行置换。那么就有一个问题了,未来要访问什么页面,操作系统怎么知道的呢?操作系统当然不会知道,所以这种算法只是一种理想情况下的置换算法,通常是无法实现的。
select、poll、epoll的区别
I/O多路复用通常通过select、poll、epoll等系统调用来实现。
●select: select是一个最古老的I/O多路复用机制,它可以监视多个文件描述符的可读、可写和错误状态。然而,但是它的效率可能随着监视的文件描述符数量的增加而降低。
●poll: poll是select的一种改进,它使用轮询方式来检查多个文件描述符的状态,避免了select中文件描述符数量有限的问题。但对于大量的文件描述符,poll的性能也可能变得不足够高效。
●epoll: epoll是Linux特有的I/O多路复用机制,相较于select和poll,它在处理大量文件描述符时更加高效。epoll使用事件通知的方式,只有在文件描述符就绪时才会通知应用程序,而不需要应用程序轮询。
I/O多路复用允许在一个线程中处理多个I/O操作,避免了创建多个线程或进程的开销,允许在一个线程中处理多个I/O操作,避免了创建多个线程或进程的开销。
数据库
一条SQL查询语句是如何执行的?
1连接器:连接器负责跟客户端建立连接、获取权限、维持和管理连接。
2查询缓存: MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以key-value 对的形式,被直接缓存在内存中。
3分析器:你输入的是由多个字符串和空格组成的一条SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。
4优化器:优化器是在表里面有多个索引的时候,决定使用哪个索引; 或者在一个语句有多表关联(join )的时候,决定各个表的连接顺序。
5执行器: MySQL通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
数据库的事务隔离级别有哪些?
1读未提交(Read Uncommitted):
○允许一个事务读取另一个事务尚未提交的数据修改。
○最低的隔离级别,存在脏读、不可重复读和幻读的问题。
2读已提交(Read Committed):
○一个事务只能读取已经提交的数据。其他事务的修改在该事务提交之后才可见。
○解决了脏读问题,但仍可能出现不可重复读和幻读。
3可重复读(Repeatable Read):
○事务执行期间,多次读取同一数据会得到相同的结果,即在事务开始和结束之间,其他事务对数据的修改不可见。
○解决了不可重复读问题,但仍可能出现幻读。
4序列化(Serializable):
○最高的隔离级别,确保事务之间的并发执行效果与串行执行的效果相同,即不会出现脏读、不可重复读和幻读。
事务的四大特性有哪些?
事务的四大特性通常被称为 ACID 特性
1原子性:确保事务的所有操作要么全部执行成功,要么全部失败回滚,不存在部分成功的情况。
2一致性:事务在执行前后,数据库从一个一致性状态转变到另一个一致性状态。
3隔离性:多个事务并发执行时,每个事务都应该被隔离开来,一个事务的执行不应该影响其他事务的执行。
4持久性:一旦事务被提交,它对数据库的改变就是永久性的,即使在系统故障或崩溃后也能够保持。
MySQL的执行引擎有哪些?
MySQL的执行引擎主要负责查询的执行和数据的存储, 其执行引擎主要有MyISAM、InnoDB、Memery 等。
●InnoDB引擎提供了对事务ACID的支持,还提供了行级锁和外键的约束,是目前MySQL的默认存储引擎,适用于需要事务和高并发的应用。
●MyISAM引擎是早期的默认存储引擎,支持全文索引,但是不支持事务,也不支持行级锁和外键约束,适用于快速读取且数据量不大的场景。
●Memery就是将数据放在内存中,访问速度快,但数据在数据库服务器重启后会丢失。
MySQL为什么使用B+树来作索引
B+树是一个B树的变种,提供了高效的数据检索、插入、删除和范围查询性能。
●单点查询:B 树进行单个索引查询时,最快可以在 O(1) 的时间代价内就查到。从平均时间代价来看,会比 B+ 树稍快一些。但是 B 树的查询波动会比较大,因为每个节点既存索引又存记录,所以有时候访问到了非叶子节点就可以找到索引,而有时需要访问到叶子节点才能找到索引。B+树的非叶子节点不存放实际的记录数据,仅存放索引,所以数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。
●插入和删除效率:B+ 树有大量的冗余节点,删除一个节点的时候,可以直接从叶子节点中删除,甚至可以不动非叶子节点,删除非常快。B+ 树的插入也是一样,有冗余节点,插入可能存在节点的分裂(如果节点饱和),但是最多只涉及树的一条路径。B 树没有冗余节点,删除节点的时候非常复杂,可能涉及复杂的树的变形。
●范围查询:B+ 树所有叶子节点间有一个链表进行连接,而 B 树没有将所有叶子节点用链表串联起来的结构,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。存在大量范围检索的场景,适合使用 B+树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如nosql的MongoDB。
说一下索引失效的场景?
索引失效意味着查询操作不能有效利用索引进行数据检索,从而导致性能下降,下面一些场景会发生索引失效。
1使用OR条件:当使用OR连接多个条件,并且每个条件用到不同的索引列时,索引可能不会被使用。
2使用非等值查询:当使用!=或<>操作符时,索引可能不会被使用,特别是当非等值条件在WHERE子句的开始部分时。
3对列进行类型转换: 如果在查询中对列进行类型转换,例如将字符列转换为数字或日期,索引可能会失效。
4使用LIKE语句:以通配符%开头的LIKE查询会导致索引失效。
5函数或表达式:在列上使用函数或表达式作为查询条件,通常会导致索引失效。
6表连接中的列类型不匹配: 如果在连接操作中涉及的两个表的列类型不匹配,索引可能会失效。例如,一个表的列是整数,另一个表的列是字符,连接时可能会导致索引失效。
undo log、redo log、binlog 有什么用?
●undo log是Innodb存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC。
●redo log是物理日志,记录了某个数据页做了什么修改,每当执行一个事务就会产生一条或者多条物理日志。
●binlog(归档日志)是Server层生成的日志,主要用于数据备份和主从复制。
什么是慢查询?原因是什么?可以怎么优化?
数据库查询的执行时间超过指定的超时时间时,就被称为慢查询。
原因:
●查询语句比较复杂:查询涉及多个表,包含复杂的连接和子查询,可能导致执行时间较长。
●查询数据量大:当查询的数据量庞大时,即使查询本身并不复杂,也可能导致较长的执行时间。
●缺少索引:如果查询的表没有合适的索引,需要遍历整张表才能找到结果,查询速度较慢。
●数据库设计不合理:数据库表设计庞大,查询时可能需要较多时间。
●并发冲突:当多个查询同时访问相同的资源时,可能发生并发冲突,导致查询变慢。
●硬件资源不足:如果MySQL服务器上同时运行了太多的查询,会导致服务器负载过高,从而导致查询变慢
优化:
1运行语句,找到慢查询的sql
2查询区分度最高的字段
3explain:显示mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引、写出更优化的查询语句
4order by limit形式的sql语句,让排序的表优先查
5考虑建立索引原则
Redis有什么优缺点?为什么用Redis查询会比较快
(1) Redis有什么优缺点?
Redis 是一个基于内存的数据库,读写速度非常快,通常被用作缓存、消息队列、分布式锁和键值存储数据库。它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等, Redis 还提供了分布式特性,可以将数据分布在多个节点上,以提高可扩展性和可用性。但是Redis 受限于物理内存的大小,不适合存储超大量数据,并且需要大量内存,相比磁盘存储成本更高。
(2)为什么Redis查询快
●基于内存操作: 传统的磁盘文件操作相比减少了IO,提高了操作的速度。
●高效的数据结构:Redis专门设计了STRING、LIST、HASH等高效的数据结构,依赖各种数据结构提升了读写的效率。
●单线程:单线程操作省去了上下文切换带来的开销和CPU的消耗,同时不存在资源竞争,避免了死锁现象的发生。
●I/O多路复用:采用I/O多路复用机制同时监听多个Socket,根据Socket上的事件来选择对应的事件处理器进行处理。
Redis的数据类型有那些?
Redis 常见的五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及 Zset(sorted set:有序集合)。
1字符串STRING:存储字符串数据,最基本的数据类型。
2哈希表HASH:存储字段和值的映射,用于存储对象。
3列表LIST:存储有序的字符串元素列表。
4集合SET:存储唯一的字符串元素,无序。
5有序集合ZSET:类似于集合,但每个元素都关联一个分数,可以按分数进行排序。
Redis版本更新,又增加了几种数据类型,
●BitMap: 存储位的数据结构,可以用于处理一些位运算操作。
●HyperLogLog:用于基数估算的数据结构,用于统计元素的唯一数量。
●GEO: 存储地理位置信息的数据结构。
●Stream:专门为消息队列设计的数据类型。
Redis是单线程的还是多线程的,为什么?
Redis在其传统的实现中是单线程的(网络请求模块使用单线程进行处理,其他模块仍用多个线程),这意味着它使用单个线程来处理所有的客户端请求。这样的设计选择有几个关键原因:
1简化模型:单线程模型简化了并发控制,避免了复杂的多线程同步问题。
2性能优化:由于大多数操作是内存中的,单线程避免了线程间切换和锁竞争的开销。
3原子性保证:单线程执行确保了操作的原子性,简化了事务和持久化的实现。
4顺序执行:单线程保证了请求的顺序执行。
但是Redis的单线程模型并不意味着它在处理客户端请求时不高效。实际上,由于其操作主要在内存中进行,Redis能够提供极高的吞吐量和低延迟的响应。
此外,Redis 6.0 引入了多线程的功能,用来处理网络I/O这部分,充分利用CPU资源,减少网络I/O阻塞带来的性能损耗。
Redis持久化机制有哪些
●AOF 日志:每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;
●RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
●混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RBD 的优点;
缓存雪崩、击穿、穿透和解决办法
1缓存雪崩是指在某个时间点,大量缓存同时失效,导致请求直接访问数据库或其他后端系统,增加了系统负载。
对于缓存雪崩,可以通过合理设置缓存的过期时间,分散缓存失效时间点,或者采用永不过期的策略,再结合定期更新缓存。
1缓存击穿是指一个缓存中不存在但是数据库中存在的数据,当有大量并发请求查询这个缓存不存在的数据时,导致请求直接访问数据库,增加数据库的负载。典型的场景是当一个缓存中的数据过期或被清理,而此时有大量请求访问这个缓存中不存在的数据,导致大量请求直接访问底层存储系统。
对于缓存击穿,可以采用互斥锁(例如分布式锁)或者在查询数据库前先检查缓存是否存在,如果不存在再允许查询数据库,并将查询结果写入缓存。
1缓存穿透是指查询一个在缓存和数据库都不存在的数据,这个数据始终无法被缓存,导致每次请求都直接访问数据库,增加数据库的负载。典型的情况是攻击者可能通过构造不存在的 key 大量访问缓存,导致对数据库的频繁查询。
对于缓存穿透,可以采用布隆过滤器等手段来过滤掉恶意请求,或者在查询数据库前先进行参数的合法性校验。
如何保证数据库和缓存的一致性
Cache Aside
●原理:先从缓存中读取数据,如果没有就再去数据库里面读数据,然后把数据放回缓存中,如果缓存中可以找到数据就直接返回数据;更新数据的时候先把数据持久化到数据库,然后再让缓存失效。
●问题:假如有两个操作一个更新一个查询,第一个操作先更新数据库,还没来及删除缓存,查询操作可能拿到的就是旧的数据;更新操作马上让缓存失效了,所以后续的查询可以保证数据的一致性;还有的问题就是有一个是读操作没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,也会造成脏数据。
●可行性:出现上述问题的概率其实非常低,需要同时达成读缓存时缓存失效并且有并发写的操作。数据库读写要比缓存慢得多,所以读操作在写操作之前进入数据库,并且在写操作之后更新,概率比较低。
Read/Write Through
●原理:Read/Write Through原理是把更新数据库(Repository)的操作由缓存代理,应用认为后端是一个单一的存储,而存储自己维护自己的缓存。
●Read Through:就是在查询操作中更新缓存,也就是说,当缓存失效的时候,Cache Aside策略是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对调用方是透明的。
●Write Through:当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由缓存自己更新数据库(这是一个同步操作)。
Write Behind
●原理:在更新数据的时候,只更新缓存,不更新数据库,而缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作非常快,带来的问题是,数据不是强一致性的,而且可能会丢。
●第二步失效问题:这种可能性极小,缓存删除只是标记一下无效的软删除,可以看作不耗时间。如果会出问题,一般程序在写数据库那里就没有完成:故意在写完数据库后,休眠很长时间再来删除缓存。