计算机网络编程知识笔记大全
2022-10-31 10:37:39 0 举报
AI智能生成
计算机网络编程知识笔记大全
作者其他创作
大纲/内容
计算机组成原理
硬件设备组成
cpu
内存
硬盘
主板
键盘,鼠标
显示器
冯诺依曼体系结构
运算器
控制器
存储器
输入设备
输出设备
图灵机
计组知识地图
性能究竟是什么
响应时间
吞吐率
CPU 时钟<br>
time命令
real time
user time
sys time
程序的 CPU 执行时间 = 指令数×CPI×Clock Cycle Time
时钟周期时间,就是计算机主频,这个取决于计算机硬件。
每条指令的平均时钟周期数 CPI,就是一条指令到底需要多少 CPU Cycle。在后面讲解 CPU 结构的时候,我们会看到,现代的 CPU 通过流水线技术(Pipeline),让一条指令需要的 CPU Cycle 尽可能地少。因此,对于 CPI 的优化,也是计算机组成和体系结构中的重要一环。
指令数,代表执行我们的程序到底需要多少条指令、用哪些指令。这个很多时候就把挑战交给了编译器。同样的代码,编译成计算机指令时候,就有各种不同的表示方式。
如何提升性能
功耗:CPU 的“人体极限”
功耗 ~= 1/2 ×负载电容×电压的平方×开关频率×晶体管数量
增加晶体管数量
降低电压
并行优化,理解阿姆达尔定律
第一,需要进行的计算,本身可以分解成几个可以并行的任务。好比上面的乘法和加法计算,几个人可以同时进行,不会影响最后的结果。
第二,需要能够分解好问题,并确保几个人的结果能够汇总到一起。
第三,在“汇总”这个阶段,是没有办法并行进行的,还是得顺序执行,一步一步来
阿姆达尔定律
优化后的执行时间 = 受优化影响的执行时间 / 加速倍数 + 不受影响的执行时间
几个原则性的性能提升方法
1.加速大概率事件
2.通过流水线提高性能
3.通过预测提高性能
计算机网络
网络协议体系结构分层
OSI七层
应用层
超文本传输协议: HTTP
文件传输协议: FTP<br>
简单邮件传输协议: SMTP
域名系统: DNS
安全外壳协议: SSH<br>
动态主机配置协议: DHCP
远程登录协议: TELNET
表示层
会话层
传输层
传输控制协议: TCP
用户数据报文协议: UDP<br>
网络层
网际协议: IP
地址转换协议: ARP
反向地址转换协议: RARP
数据链路层
物理层
中继器
集线器
网线
HUB
TCP/IP五层模型
TCP/IP四层模型
ARP 协议的工作原理
完成ip地址和mac地址的映射
IP
IP 地址分类<br>
A 类地址:以 0 开头,第一个字节范围:0~127
B 类地址:以 10 开头,第一个字节范围:128~191<br>
C 类地址:以 110 开头,第一个字节范围:192~223<br>
D 类地址:以 1110 开头,第一个字节范围为 224~239, 广播地址
E 类地址:以 1111 开头,保留地址
localhost与127.0.0.1
TCP
TCP 的主要特点
面向连接
点对点
可靠交付<br>
全双工通信<br>
面向字节流<br>
TCP 对应的应用层协议<br>
HTTP
FTP
TELNET
SMTP
POP3
三次握手的过程
为什么两次握手不可以呢?
为什么不需要四次握手?<br>
Server 端收到 Client 端的 SYN 后,为什么还要传回 SYN?
传了 SYN,为什么还要传 ACK?<br>
四次挥手的过程
为什么 TIME-WAIT 状态必须等待 2MSL 的时间呢?
为什么第二次跟第三次不能合并, 第二次和第三次之间的等待是什么?
保活计时器的作用?<br>
TCP 协议是如何保证可靠传输的?
数据包校验
对失序的数据包重排序
丢弃重复的数据
应答机制
超时重发
流量控制
谈谈你对停止等待协议的理解?<br>
谈谈你对 ARQ 协议的理解<br>
自动重传请求 ARQ 协议<br>
连续 ARQ 协议<br>
谈谈你对滑动窗口的了解?<br>
谈下你对流量控制的理解?<br>
谈下你对 TCP 拥塞控制的理解?使用了哪些算法?<br>
慢开始算法
拥塞避免算法
快重传与快恢复算法
什么是粘包?<br>
TCP 黏包是怎么产生的?<br>
发送方产生粘包
接收方产生粘包<br>
怎么解决拆包和粘包?<br>
UDP
UDP 的主要特点
无连接的<br>
不保证可靠交付<br>
面向报文的
没有拥塞控制<br>
UDP 支持一对一、一对多、多对一和多对多的交互通信<br>
UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短
UDP对应的应用层协议
DNS<br>
TFTP
TCP 和 UDP 的区别<br>
HTTP
你对 HTTP 状态码有了解吗?<br>
1XX 信息<br>
100 Continue :表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应。<br>
2XX 成功<br>
3XX 重定向<br>
4XX 客户端错误<br>
5XX 服务器错误<br>
HTTP 状态码 301 和 302 代表的是什么?有什么区别?<br>
forward 和 redirect 的区别?<br>
HTTP 方法有哪些?
1. GET:获取资源,当前网络中绝大部分使用的都是 GET;<br>
2. HEAD:获取报文首部,和 GET 方法类似,但是不返回报文实体主体部分;
3. POST:传输实体主体<br>
4. PUT:上传文件,由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法。<br>
5. PATCH:对资源进行部分修改。PUT 也可以用于修改资源,但是只能完全替代原始资源,PATCH 允许部分修改。<br>
6. OPTIONS:查询指定的 URL 支持的方法;<br>
7. CONNECT:要求在与代理服务器通信时建立隧道。使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。<br>
8. TRACE:追踪路径。服务器会将通信路径返回给客户端。发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。通常不会使用 TRACE,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪)。<br>
说下 GET 和 POST 的区别?<br>
本质区别:GET 只是一次 HTTP请求,POST 先发请求头再发请求体,实际上是两次请求。<br>
从功能上讲,GET 一般用来从服务器上获取资源,POST 一般用来更新服务器上的资源;<br>
从 REST 服务角度上说,GET 是幂等的,即读取同一个资源,总是得到相同的数据,而 POST 不是幂等的,因为每次请求对资源的改变并不是相同的;进一步地,GET 不会改变服务器上的资源,而 POST 会对服务器资源进行改变;<br>
从请求参数形式上看,GET 请求的数据会附在 URL 之后,而 POST 请求会把提交的数据则放置在是 HTTP 请求报文的 请求体 中;<br>
就安全性而言,POST 的安全性要比 GET 的安全性高,因为 GET 请求提交的数据将明文出现在 URL 上,而且 POST 请求参数则被包装到请求体中,相对更安全;<br>
从请求的大小看,GET 请求的长度受限于浏览器或服务器对 URL 长度的限制,允许发送的数据量比较小,而 POST 请求则是没有大小限制的。
在浏览器中输入 URL 地址到显示主页的过程
1. DNS 解析
DNSz查找过程:浏览器缓存 => 路由器缓存 => DNS缓存<br>
2. TCP 连接
3. 发送 HTTP 请求<br>
4.服务器处理请求并返回 HTTP 报文<br>
5. 浏览器解析渲染页面<br>
6. 连接结束
DNS 的解析过程?
1. 主机向本地域名服务器的查询一般都是采用递归查询<br>
2. 本地域名服务器向根域名服务器的查询的迭代查询<br>
谈谈你对域名缓存的了解?<br>
谈下你对 HTTP 长连接和短连接的理解
谈下 HTTP 1.0 和 1.1、1.2 的主要变化?<br>
HTTP1.1 的主要变化<br>
支持长连接
支持只发送header不发送body
支持host字段
HTTP2.0 的主要变化<br>
支持多路复用
支持服务端推送
压缩请求头
适用于https场景
HTTPS 的工作过程?<br>
1. 客户端发送自己支持的加密规则给服务器,代表告诉服务器要进行连接了
2. 服务器从中选出一套加密算法和 hash 算法以及自己的身份信息(地址等)以证书的形式发送给浏览器,证书中包含服务器信息,加密公钥,证书的颁发机构;
3. 客户端收到网站的证书之后处理<br>
4. 服务器接收到客户端传送来的信息处理
5. 如果计算法 hash 值一致,握手成功
HTTP 和 HTTPS 的区别<br>
1. 开销:HTTPS 协议需要到 CA 申请证书,一般免费证书很少,需要交费;<br>
2. 资源消耗:HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 ssl 加密传输协议,需要消耗更多的 CPU 和内存资源;<br>
3. 端口不同:HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443;
4. 安全性:HTTP 的连接很简单,是无状态的;HTTPS 协议是由 TSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
HTTPS 的优缺点
优点
1. 使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;<br>
2. HTTPS 协议是由 SSL + HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性;
3. HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
缺点
1. HTTPS 协议握手阶段比较费时,会使页面的加载时间延长近 50%,增加 10% 到 20% 的耗电;<br>
2. HTTPS 连接缓存不如 HTTP 高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
3. SSL 证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用;
4. SSL 证书通常需要绑定 IP,不能在同一 IP 上绑定多个域名,IPv4 资源不可能支撑这个消耗;
5. HTTPS 协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL 证书的信用链体系并不安全,特别是在某些国家可以控制 CA 根证书的情况下,中间人攻击一样可行。
什么是数字签名?
什么是数字证书?
什么是对称加密和非对称加密?<br>
Java
基础篇<br>
面向对象
什么是面向对象<br>
泛型<br>
注解
Node.js
基础<br>
Node.js简介
基本架构
undefined与null的区别
作用域
什么是作用域?
作用域是一组规则,它决定了在哪里和如何查找一个变量(标识符)。这种查询也许是为了向这个变量赋值,这时变量是一个LHS引用,或者是为取得它的值,这时变量是一个RHS引用。
编译器理论
分词/词法分析<br>
解析--抽象语法树
代码生成
词法作用域
词法作用域意味着作用域是由编写时函数被声明的位置的决策定义的。编译器的词法分析阶段实质上可以知道所有的标识符是在哪里和如何声明的,并如此在执行期间预测它们将如何被查询。
在JavaScript中有两种机制可以“欺骗”词法作用域:eval(..) 和 with 。前者可以通过对一个拥有一个或多个声明的“代码”字符串进行求值,来(在运行时)修改现存的词法作用域。后者实质上是通过将一个对象引用看作一个“作用域”,并将这个对象的属性看作作用域中的标识符,(同样,也是在运行时)创建一个全新的词法作用域。
这些机制的缺点是,它压制了引擎在作用域查询上进行编译期优化的能力,因为引擎不得不悲观地假定这样的优化是不合法的。这两种特性的结果就是代码将会运行的更慢。不要使用它们。
函数与块作用域
在JavaScript中函数是最常见的作用域单位。在另一个函数内部声明的变量和函数,实质上对任何外围“作用域”都是“隐藏的”,这是优秀软件的一个有意的设计原则。<br>
但是函数绝不是唯一的作用域单位。块儿作用域指的是这样一种想法:变量和函数可以属于任意代码块儿(一般来说,就是任意的 { .. } ),而不是仅属于外围的函数。<br>
从ES3开始,try/catch 结构在 catch 子句上拥有块儿作用域。<br>
在ES6中,引入了 let 关键字( var 关键字的表兄弟)允许在任意代码块中声明变量。if (..) { let a = 2; }将会声明变量a,而它实质上劫持了 if 的 { .. } 块儿的作用域,并将自己附着在这里。<br>
虽然有些人对此深信不疑,但是块儿作用域不应当被认为是 var 函数作用域的一个彻头彻尾的替代品。两种机能是共存的,而且开发者们可以并且应当同时使用函数作用域和块儿作用域技术 —— 在它们各自可以产生更好,更易读/易维护代码的地方。
提升
在一个作用域内的所有声明,不论它们出现在何处,都会在代码本身被执行前 首先 被处理。你可以将它可视化为声明(变量与函数)被“移动”到它们各自的作用域顶部,这就是我们所说的“提升”。
声明本身会被提升,但不是赋值,即便是函数表达式的赋值,也不会被提升。<br>
函数的提升是优先于变量的提升的,所以在进行重名赋值的时候需要注意。 <br>
作用域闭包
闭包就是函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时。
模块要求两个关键性质:<br>
一个被调用的外部包装函数,来创建外围作用域。<br>
这个包装函数的返回值必须包含至少一个内部函数的引用,这个函数才拥有包装函数内部作用域的闭包。
引用传递
JavaScript中基本数据类型和引用数据类型的区别<br>
基本数据类型因为值的大小固定,所以直接保存在栈内存中。而引用数据类型因为值的大小不固定,所以保存在堆内存中,而堆内存是无法直接进行访问的,进而在栈内存当中又保存了指向堆内存中位置的指针。 <br>
复制时,基本数据类型是将原始值的副本赋值给新值,从而两个值之间并不会有任何影响,而引用数据类型则是将栈内存中保存的指向堆内存的指针赋值给新值,从而会互相影响。 <br>
深拷贝
最简单暴力的方法是: JSON.parse(JSON.stringify(obj)). 但是这样不能拷贝函数,并且会丢失原型链。<br>
较为完善的方法就是实现一个 extend 方法,递归调用 extend 方法。
== 和 === 区别是什么?
=== 比较不同数据类型时,直接返回false。比较基本数据类型时比较的是数据类型以及值,在比较引用数据类型时是比较的是否指向同一块内存区域。<br>
== 在比较相同数据类型的值的时候与 === 相同,在比较不同数据类型时,会先对两边的数据类型进行转换再比较。
JS 中没有按地址(引用)传递,只有按值传递
引用类型的值实际上是对其引用对象的一个指针。
这里严格的说,在和JAVA类似的语言中,已经没有了指针。在C里面,指针就是一个具有固定长度的类型(在大多数的C编译器里是2个字节),但在JAVA类似的语言里,引用也有自己的属性和方法,只是你不能直接去访问和控制它,所以它从某种意义上也是一种对象,这种机制也很大程度的避免了内存泄露,术语称之为内存结构化访问机制。
内存释放
新生代<br>
内存区域小,垃圾回收频繁,大多数变量刚被声明的时候都先进入新生代区域。当新生代区域内存满的时候会进行一次清理。<br>
采用Scavenge算法进行回收,主要思想是将内存区分为 From 空间和 To 空间。变量一来时都先进入 From 空间,当开始清理的时候对 From 空间进行宽搜,将那些能够从ROOT节点搜索到的,并且还在新生代区域的变量放入 To 空间中,然后交换 From 和 To 空间。
默认情况下,64位环境下的V8引擎的新生代内存大小32MB,32位则减半<br>
晋升<br>
在新生代区域进行回收的时候,查看这个变量是否已经经历过一次垃圾回收,如果已经经历过一次了就将它放入老生代区域。
对象从 From 空间复制到 To 空间时,如果To 空间已经被使用了超过(新生代)25%,那么这个对象直接被复制到老生代。
老生代<br>
内存区域大,垃圾回收频率较低,保存的对象大多数是生存周期很长的甚至是常驻内存的对象。 <br>
采用Mark-Sweep(标记清除)与 Mark-Compact(标记整理)结合的算法进行回收,主要思想是进行宽搜,搜索过程当中对对象进行染色,最后如果一个对象没有被染色那么就是垃圾(这里其实和Scavenge寻找垃圾的思路是一致的,就是看一个对象能不能从ROOT节点搜索到)。然后进行对象的清除,当空间不足以分配从新生代晋升过来的对象时,才使用标记整理(其实就是内存页面的整理)。 <br>
默认64位,老生代内存大小为1400MB, 32位为700MB
内存泄漏
指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况
内存泄漏的几种情况
1.全局变量<br>
2.闭包
3.事件监听<br>
例如对同一个事件重复监听,忘记移除(removeListener),将造成内存泄漏
4.其他原因<br>
大缓存
非常占用 CPU 的代码<br>
定位内存泄漏
重现内存泄漏情况
对于只要正常使用就可以重现的内存泄漏,这是很简单的情况只要在测试环境模拟就可以排查了。<br>
对于偶然的内存泄漏,一般会与特殊的输入有关系。想稳定重现这种输入是很耗时的过程。如果不能通过代码的日志定位到这个特殊的输入,那么推荐去生产环境打印内存快照了。需要注意的是,打印内存快照是很耗 CPU 的操作,可能会对线上业务造成影响。
打印内存快照
对比内存快照找出泄漏位置
如何避免内存泄漏<br>
ESLint 检测代码检查非期望的全局变量。<br>
使用闭包的时候,得知道闭包了什么对象,还有引用闭包的对象何时清除闭包。最好可以避免写出复杂的闭包,因为复杂的闭包引起的内存泄漏,如果没有打印内存快照的话,是很难看出来的
绑定事件的时候,一定得在恰当的时候清除事件。在编写一个类的时候,推荐使用 init 函数对类的事件监听进行绑定和资源申请,然后 destroy 函数对事件和占用资源进行释放。
ES6 新特性
let 与 var 的区别
let 不会有作用域提升现象,所以使用 let 会有TDZ错误。<br>
let 一般与 {} 块联合使用,即在块中使用 let 声明的变量只在块中有效,在外面不能进行访问。<br>
let 与 for 联合使用的时候,因为 let 声明的变量只在块中有效,所以每一次循环当中都会声明一个新的循环变量。(这里还需要注意,for 循环当中,循环语句部分是一个父作用域,而循环体内部是一个单独的子作用域)<br>
let 不允许重复声明。<br>
function 与 => 的区别<br>
=>函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。<br>
=>不可以当做构造函数,也就是说,不可以使用 new 命令,否则会抛出错误。
=>不可以使用 arguments 对象,该对象在函数体内不存在。
=>不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。<br>
const 定义的 Array 中间元素能否被修改? 如果可以, 那 const 修饰对象有什么意义?
const 定义的 Array 中间元素能被修改,const 定义的变量只是持有 Array 的地址,这个变量只是本身不能修改,而对于存在于堆内存中的 Array 本身是可以修改的。<br>
对于 const 声明,只是它的赋值操作被冻结了,而值不会因为 const 而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。
结合 {} 来谈 set 与 map
Set: 感觉这个应该结合 [] 来谈,这个与数组的区别就是里面不存在重复的元素。结合 ... 可以直接转为数组,并且可以很方便的实现 并集、交集、差集。(这里的问题是 NaN 被判为同一种元素,但是 === 判NaN是不同的元素)
WeakSet: 对象成员版的 Set,里面的成员只能是对象。并且这里是对成员是弱引用,所以不具有 size 属性,也不具有循环操作。
Map: 这个与 {} 的区别是键值可以不只是字符串了,但是这里判断两个键一不一样的时候,对于引用数据来说是看他们是否指向同一块内存。
WeakMap: 对象键值版的 Map,里面的成员的键只能是对象,这边同样是弱引用。特征与 WeakSet 相似。
私有化的问题与 symbol 、 class
常规的私有化方法是使用闭包,只对外开放非私有化的部分。
symbol 是用来处理属性名的冲突。但是一个 symbol 属性作为键名时是不能被 Object.keys() 、 Object.getOwnPropertyNames() 获取,所以就造成了一种非私有的内部方法效果。symbol 是不能达到闭包那么好的效果的,因为通过 Symbol.for() 是可以获取同一个 Symbol 值的,获得以后一样是能够访问值。
在 class 中实现私有方法的办法是将方法声明在类外,然后在类中使用 .call() 进行引用。虽然通过这个类对象是不能访问这个方法,但是这个方法其实还是暴露在其他更大的作用域当中的,或者就是使用 symbol 作为方法名,这里的优缺点在 Symbol 中已经分析了。
目前,有一个提案,为class加了私有属性。方法是在属性名之前,使用#表示。
一种做法是在命名上加以区别, 例如以_开头
模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。<br>模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
常见问题 <br>
如果 a.js require 了 b.js, 那么在 b 中定义全局变量 t = 111 能否在 a 中直接打印出来?<br>
a.js 和 b.js 两个文件互相 require 是否会死循环? 双方是否能导出变量? 如何从设计上避免这种问题?<br>
AMD, CMD, CommonJS 三者的区别
node 中 require 的实现原理
热更新 <br>
上下文 <br>
既然可以通过新的上下文来避免污染,那么为什么 node.js不给每一个.js文件以独立的上下文来避免作用域被污染
包管理 <br>
npm yarn<br>
事件/异步
Promise
Events
异步
JS异步是怎么实现的
我们都知道JS是单线程的,那单线程是怎么实现异步的呢?
渲染进程
GUI线程<br>
JS引擎线程<br>
定时器线程 <br>
事件触发线程
异步HTTP请求线程
Event Loop
浏览器的Event Loop<br>
Node.js的Event Loop
定时器不准
宏任务<br>
微任务
总结
1. JS所谓的“单线程”只是指主线程只有一个,并不是整个运行环境都是单线程
2. JS的异步靠底层的多线程实现 <br>
3. 不同的异步API对应不同的实现线程 <br>
4. 异步线程与主线程通讯靠的是Event Loop <br>
5. 异步线程完成任务后将其放入任务队列 <br>
6. 主线程不断轮询任务队列,拿出任务执行 <br>
7. 任务队列有宏任务队列和微任务队列的区别 <br>
8. 微任务队列的优先级更高,所有微任务处理完后才会处理宏任务 <br>
9. Promise是微任务 <br>
10. Node.js的Event Loop跟浏览器的Event Loop不一样,他是分阶段的 <br>
11. setImmediate和setTimeout(fn, 0)哪个回调先执行,需要看他们本身在哪个阶段注册的,如果在定时器回调或者I/O回调里面,setImmediate肯定先执行。如果在最外层或者setImmediate回调里面,哪个先执行取决于当时机器状况。<br>
12. process.nextTick不在Event Loop的任何阶段,他是一个特殊API,他会立即执行,然后才会继续执行Event Loop <br>
数据库
redis
功能文档
redis基础
redis命令参考
5个基本数据类型
string
list
hash
set
sortedSet
数据结构
HyperLogLog
Geo
Pub/Sub
Redis Module<br>
BloomFilter(布隆过滤器)<br>
RedisSearch<br>
业界常用 elasticsearch 和 lucene 等方案
Redis-ML<br>
机器学习模型
如果有大量的key需要设置同一时间过期,一般需要注意什么?<br>
那你使用过Redis分布式锁么,它是什么回事?
如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?
对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
scan命令
使用过Redis做异步队列么,你是怎么用的?<br>
rpush
lpop
如果对方追问可不可以不用sleep呢?
blpop
如果对方接着追问能不能生产一次消费多次呢?
pub/sub
如果对方继续追问 pub/su b有什么缺点?
MQ
如果对方究极TM追问Redis如何实现延时队列?
sortedSet
redis数据持久化
Redis是怎么持久化的?服务主从数据怎么交互的?
RDB
优点
缺点
AOF
优点
缺点
RDB 和 AOF ,我应该用哪一个?
对方追问那如果突然机器掉电会怎样?
对方追问RDB的原理是什么?
Pipeline有什么好处,为什么要用pipeline?
Redis的同步机制了解么?
主从同步<br>
从从同步
是否使用过Redis集群,集群的高可用怎么保证,集群的原理是什么?
Redis Sentinal<br>
Redis Cluster
事务
MULTI<br>
EXEC
事务中的错误
事务在执行 EXEC 之前,入队的命令可能会出错
命令可能在 EXEC 调用之后失败
为什么 Redis 不支持回滚(roll back)
失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中
因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速
在通常情况下, 回滚并不能解决编程错误带来的问题
使用 check-and-set 操作实现乐观锁
WATCH命令
Redis 脚本和事务
redis缓存
雪崩
应对方法
穿透
缓存穿透我会在接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接拦截等。
布隆过滤器(Bloom Filter)
击穿
设置热点数据永远不过期。或者加上互斥锁就能搞定了
Redis哨兵、持久化、主从、手撕LRU
为啥Redis那么快
完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。它的,数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);<br>
数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
使用多路I/O复用模型,非阻塞IO;
使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
那他是单线程的,我们现在服务器都是多核的,那不是很浪费?
既然提到了单机会有瓶颈,那你们是怎么解决这个瓶颈的?
持久化
Redis还有其他保证集群高可用的方式么?
哨兵集群sentinel<br>
哨兵组件的主要功能
能说一下主从之间的数据怎么同步的么?
数据传输的时候断网了或者服务器挂了怎么办啊?
那说了这么多你能说一下他的内存淘汰机制么
定期删除
惰性删除<br>
内存淘汰机制<br>
最近最少使用LRU
最不常使用LFU
FIFO
双写一致, 并发竞争, 线程模型
你有没有考虑过,如果你多个系统同时操作(并发)Redis带来的数据问题?
分布式锁
你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
串行化
队列
你了解最经典的KV、DB读写模式么?
为什么是删除缓存,而不是更新缓存?
懒加载思想
Redis 和 Memcached 有啥区别,为啥选择用Redis作为你们的缓存中间件?<br>
Redis 的线程模型了解么?<br>
常见面试题<br>
秒杀系统设计
问题
高并发
超卖
恶意请求
连接暴露<br>
数据库
设计<br>
服务单一职责
秒杀连接加盐<br>
redis集群
nginx负载均衡<br>
前端资源静态化
按钮控制
限流,降级,熔断
库存预热
削峰填谷MQ
MySQL
MySQL的基本架构
连接器<br>
查询缓存
分析器
词法分析
语法分析
优化器
索引
类型
HASH<br>
可以快速的精确查询,但是不支持范围查询
B+TREE
矮胖, 查询速度快,范围查找比b树快
平衡二叉树
高瘦, 查询效率低
b树
矮胖
那么,一个B+树的节点中到底存多少个元素最合适你有了解过么?
Mysql的基本存储结构是 页
回表
覆盖索引
最左匹配原则
创建好的索引原则
什么时候【要】创建索引
什么时候【不要】创建索引
总结
子主题
数据库常见面试题<br>
什么是存储过程?有哪些优缺点?
优点
缺点
三个范式是什么
第一范式:字段是最小的单元不可再分割
第二范式:满足第一范式,要有主键且表中的字段必须完全依赖于全部主键而非部分主键
第三范式:满足第二范式,非主键外的所有字段必须互不依赖(消除冗余)
什么是视图?以及视图的使用场景有哪些?
drop、delete与truncate分别在什么场景之下使用?
drop
truncate<br>
delete
场景
什么是事务?
ACID — 数据库事务正确执行的四个基本要素<br>
原子性(Atomicity)<br>
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
事务隔离级别
脏读<br>
不可重复读
幻读(虚读)
数据库的乐观锁和悲观锁是什么?
悲观锁
乐观锁
超键、候选键、主键、外键分别是什么?
超键
在关系中能唯一标识元组的属性集称为关系模式的超键
候选键
是最小超键,即没有冗余元素的超键
主键
数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合(唯一,非空)
外键
在一个表中存在的另一个表的主键称此表的外键
SQL 约束有哪几种?
NOT NULL(非空): 用于控制字段的内容一定不能为空(NULL)。
UNIQUE(唯一): 控件字段内容不能重复,一个表允许有多个 Unique 约束。
PRIMARY KEY(主键): 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。
FOREIGN KEY(外键): 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
CHECK(检查): 用于控制字段的值范围。
数据库运行于哪种状态下可以防止数据的丢失?
在archivelog mode(归档模式)只要其归档日志文件不丢失,就可以有效地防止数据丢失。<br>
Mysql存储引擎
innodb<br>
Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
MyIASM
不提供事务的支持,也不支持行级锁和外键
MEMORY
所有的数据都在内存中,数据的处理速度快,但是安全性不高
mysql有关权限的表都有哪几个<br>
数据表损坏的修复方式有哪些?
使用 myisamchk 来修复
repair table
OPTIMIZE TABLE
MySQL中InnoDB引擎的行锁是通过加在什么上完成
行锁依赖于索引,如果没加索引则使用表锁
数据库优化的思路
SQL优化
①选择最有效率的表名顺序
②WHERE子句中的连接顺序
③SELECT子句中避免使用*号
④用TRUNCATE替代DELETE
⑤多使用内部函数提高SQL效率
⑥使用表或列的别名
⑦多使用commit
⑧善用索引
⑨SQL写大写
⑩避免在索引列上使用NOT
①①避免在索引列上使用计算
①②用 >= 替代 >
①③用IN替代OR
①④总是使用索引的第一个列
数据库结构优化<br>
范式优化<br>
反范式优化
拆分表
垂直拆分
水平拆分
服务器硬件优化
MongoDB
应用场景
MQ
为啥用消息队列?<br>
应用场景
异步
削峰
解耦
缺点
系统复杂性<br>
重复消费
重试机制
接口幂等
强校验
支付等
弱校验
顺序消费<br>
消息丢失
分布式事务
事务的 ACID 特性(原子性、一致性、隔离性、持久性)
2pc(两段式提交)
3pc(三段式提交)
TCC(Try、Confirm、Cancel)
半消息/最终一致性(RocketMQ)
数据一致性
可用性
技术选型
kafka
rocketMQ
优点
缺点
activeMQ<br>
rabbitMQ
面试题
java系列总结最全面的面试题
字节跳动三面四小时的灵魂拷问
阿里一面java向
京东百度java向
微服务
2020年Java多线程与并发系列22道高频面试题
简历
Redis面试全攻略
面经
微服务
docker
dockerfile
大前端
express
KOA
简介
四个对象
aplication
context
request
response
中间件
koa-router
koa-static<br>
参考资料
阮一峰
执行流程图
深入koa源码(一):架构设计
egg
设计原则
约定优于配置
一个插件只做一件事
特性
提供基于 Egg 定制上层框架的能力
高度可扩展的插件机制
内置多进程管理
基于 Koa 开发,性能优异
框架稳定,测试覆盖率高
渐进式开发
框架内置基础对象<br>
Application
事件
server
error
request
response
Context
Request
Response
Controller
Service
Helper
Config
Logger
运行环境<br>
指定运行环境<br>
通过 config/env 文件指定
通过 EGG_SERVER_ENV 环境变量指定运行环境
应用内获取运行环境
框架提供了变量 app.config.env 来表示应用当前的运行环境。<br><br>
与 NODE_ENV 的区别
自定义环境<br>
与 Koa 的区别<br>
koa:app.env
egg: app.config.env
Config 配置<br>
常见配置管理方案
使用平台管理配置,应用构建时将当前环境的配置放入包内,启动时指定该配置。但应用就无法一次构建多次部署,而且本地开发环境想使用配置会变的很麻烦。
使用平台管理配置,在启动时将当前环境的配置通过环境变量传入,这是比较优雅的方式,但框架对运维的要求会比较高,需要部署平台支持,同时开发环境也有相同痛点。
使用代码管理配置,在代码中添加多个环境的配置,在启动时传入当前环境的参数即可。但无法全局配置,必须修改代码。<br>
多环境配置<br>
配置写法<br>
配置加载顺序<br>
合并规则<br>
配置结果<br>
中间件(Middleware)<br>
编写中间件<br>
配置
使用中间件<br>
在应用中使用中间件<br>
在框架和插件中使用中间件<br>
router 中使用中间件<br>
框架默认中间件<br>
通用配置<br>
enable:控制中间件是否开启
match:设置只有符合某些规则的请求才会经过这个中间件。
ignore:设置符合某些规则的请求不经过这个中间件。
vue
0 条评论
下一页