字节后端
什么叫进程?什么叫线程?他俩有什么区别和联系?
进程是操作系统进行资源分配和调度的基本单位,是一个程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。
线程是进程的一个执行流,是CPU调度和分派的基本单位,它比进程更小,被包含在进程之中,是进程中实际运行工作的单位。
区别:
地址空间和其他资源:进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响。而线程是进程的一部分,一个线程崩溃可能直接造成整个进程的崩溃。
资源分配:进程是资源分配的单元,线程是CPU调度的单元。
相互关系:没有进程就没有线程,一个进程至少有一个线程,称为主线程,而多线程可以并发执行。
联系:
线程的切换更快,资源开销小,但是线程依赖于进程,因为线程是由进程来提供可执行环境和必需资源的。一个程序至少有一个进程,一个进程至少有一个线程。
介绍一下MySQL的索引有哪些?底层数据结构是什么?哪些场景下索引会失效?
MySQL的索引主要有以下几种:
- B-Tree索引:也就是我们常说的索引,用于等值和范围查询,左侧前缀查找;
- 哈希索引:只用于等值查询,不能用于排序和部分查找;
- 空间数据索引:主要用于空间数据查询,比如地理数据查找;
- 全文索引:用于全文搜索。
底层数据结构:
- B-Tree索引:采用B+树数据结构;
- 哈希索引:采用哈希表;
- 空间数据索引:采用R-Tree;
- 全文索引:采用倒排索引。
索引会失效的场景包括:
- 使用!=或<>操作符;
- 对字段进行运算或函数操作;
- 使用LIKE '%XXX’这样以通配符开头的模糊查询;
- 数据类型不一致,比如用字符串类型的字段去匹配数字类型的索引;
- 在WHERE子句中使用OR,除非OR条件中的每个列都进行了索引。
- 对于NULL的查询通常不会使用索引。
你有在服务器上布置过程序吗?怎么部署的?将C++代码布置到服务器上的时候,他的代码在服务器上是怎么运行起来的?
部署程序到服务器一般需经过以下几个步骤:
- 编写代码:首先在本地环境上编写和测试好您的C++代码。
- 编译代码:使用C++编译器(如g++)将你的代码编译成可执行文件。
- 移动文件:通过FTP工具(如FileZilla)、或scp命令,将编译后的可执行文件上传到服务器对应位置。
- 运行程序:在服务器上通过命令行,运行上一步中移动到服务器的可执行文件。
C++代码在服务器上的运行原理:
- CPU 将可执行文件加载到内存,然后执行其中的机器码,C++代码在编译阶段已经被翻译为机器码。
- 可执行文件的执行,实际上是操作系统为此程序启动一个进程,该进程才是真正执行机器码的实体。
- 操作系统负责管理和调度进程,确保每一个进程都有执行的资源和时间,从而使得你的C++程序得以运行。
了解过集群的概念吗?
集群是一种技术,通过这种技术,可以将多台计算机联结起来,使它们可以一起作业,以提供比单个计算机更高的处理速度、可靠性和可扩展性。
主要特点有:
- 高可靠性:任何一个节点出现故障,不会影响到整个集群系统的工作。当某个节点出现故障后,其它节点可以接管故障节点的工作。
- 高性能:采用多节点并行处理技术,性能可以通过简单地增加节点数目而线性或者接近线性增加。
- 高可扩展性:可以根据需要方便地添加新的节点。
集群的主要类型包括负载均衡集群、高可用集群、计算集群等。
介绍一下虚拟内存
虚拟内存是计算机管理内存的一种技术,它允许操作系统将硬盘空间用作临时的内存使用。这种技术使得计算机能够运行比实际物理内存更多的程序,并通过内存分页来提高程序的运行效率。
其主要特点包括:
- 内存扩展:虚拟内存扩展了计算机的可用内存空间,使得系统能运行更多程序。
- 内存隔离:确保每个程序在自己的地址空间运行,互不干扰。
- 数据保护:保护数据不被未经授权的程序访问。
- 交换:将不频繁使用的数据暂时存放到硬盘上,以释放物理内存。
工作原理上,虚拟内存将硬盘的一部分空间作为扩展内存(称为交换空间或页文件),并通过页面置换算法,将正在使用和不常使用的数据在物理内存和硬盘之间交换,以高效地利用有限的物理内存资源。
介绍一下https
HTTPS是HTTP的安全版。它是一种用于安全通信的网络协议,通过在HTTP下加入SSL/TLS协议,为网站身份认证提供了一种保障,同时确保数据传输的隐私和完整性。简而言之,HTTPS通过以下机制增加网络安全:
- 加密:数据在传输过程中被加密,即使被截获,数据也无法被读取。
- 身份验证:确保访问者与网站服务器之间的数据交换是安全的,防止“中间人攻击”。
- 数据完整性:确保数据在传输过程中未被篡改。
介绍一下TCP和UDP的区别
TCP(传输控制协议)和UDP(用户数据报协议)是两种主要的网络传输协议,主要区别在于它们数据传输的可靠性和速度:
- 可靠性:TCP是一种面向连接的协议,提供数据包的有序传送和错误检查,保证数据的完整性,但速度相对较慢。相反,UDP是一种无连接的协议,不提供有序传送和错误检查,因此传送速度更快,但可能丢失数据包。
- 连接性:TCP需要建立连接后才能进行数据传输,而UDP不需要预先建立连接。
- 数据包顺序:TCP保证数据包的顺序,而UDP不保证。
- 速度:由于TCP需要确认机制,相比于UDP,TCP的传输速度较慢。
- 使用场景:TCP常用于需要可靠传输的应用,如Web页面传输,电子邮件传输等。而UDP则常用在实时应用(如语音和视频通话,直播)和简单查询服务(如DNS)。
- 头部大小:TCP头部最小为20字节,UDP头部固定为8字节,因此UDP整体上较为轻量。
代码题:
1、搜索旋转排序数组(leetcode 33)
在旋转排序数组中搜索给定目标值的问题,可以使用二分查找方法高效解决。核心思想是分析目标值与中间值的关系,确定下一步查找的区间。下面是解题的步骤:
-
初始化:设置左指针
left
为0,右指针right
为nums.length - 1
。 -
二分查找:
-
计算中间位置
mid = (left + right) / 2
。 -
如果
nums[mid]
等于目标值target
,直接返回mid
。 -
分析
nums[left]
至
nums[mid]
是否是递增:
-
如果是递增,判断
target
是否在
nums[left]
和
nums[mid]
之间:
- 如果是,调整
right
至mid - 1
。 - 否则,调整
left
至mid + 1
。
- 如果是,调整
-
如果不是递增,判断
target
是否在
nums[mid]
和
nums[right]
之间:
- 如果是,调整
left
至mid + 1
。 - 否则,调整
right
至mid - 1
。
- 如果是,调整
-
-
-
返回结果:如果没找到返回
-1
。
这种方法能在O(log n)的时间复杂度内找到目标值的位置。
2、排序链表(leetcode 148)
可以通过归并排序算法来高效解决,时间复杂度为O(nlogn),空间复杂度为O(1)。排序链表的归并排序实现步骤如下:
- 寻找中点:使用快慢指针找到链表的中点,快指针速度是慢指针的两倍,当快指针到达链表尾部时,慢指针正好在链表中点。
- 分割链表:将链表从中点分割为两个子链表。
- 递归排序:对两个子链表递归地进行归并排序。
- 合并链表:将两个排序后的子链表合并为一个有序链表。
腾讯实习 云架构平台
c++中struct和class的区别
区别在于默认的访问权限和继承权限:
- 默认访问权限:
struct
成员默认是public
的,class
成员默认是private
的。 - 默认继承权限:
struct
继承默认是public
的,class
继承默认是private
的。
虚函数内部的实现
虚函数在C++内部是通过虚函数表和虚函数指针来实现的:
- 虚函数表:每个包含虚函数的类(或派生类)都有一个相应的虚函数表,这个表中储存着该类的虚函数的地址。
- 虚函数指针:每个类的对象都会有一个指向虚函数表的指针,当调用虚函数时,编译器会通过这个指针找到虚函数表,从表中获取相应虚函数的地址,然后调用。
纯虚函数
纯虚函数是一种在基类中声明但不实现的虚函数,其语法为:virtual ReturnType FunctionName(Parameters...) = 0;
。纯虚函数的存在使得基类成为抽象类,不能直接实例化,要求任何派生自该基类的子类必须实现这个纯虚函数,从而实现多态。
如何避免指针被双重删除
避免指针双重删除的常见方法:
- 置空:在删除指针后,立即将其设置为NULL。这样,即使对其进行第二次删除操作(delete NULL是安全的),也不会引发问题。
- 智能指针:使用C++智能指针(如unique_ptr或shared_ptr)。这些智能指针在离开作用域时会自动释放内存,从而避免了双重删除。
- 避免复制:避免将裸指针复制给多个指针变量,以防止错误地删除同一段内存。
\n与endl的区别
\n
只负责换行,不会刷新缓冲区,因此输出速度较快。endl
除了换行外,还会强制刷新缓冲区,确保输出立即显示,但相对较慢。
TCP完成服务监听的步骤
socket()
:创建一个新的套接字。bind()
:将套接字绑定到一个本地地址和端口上。listen()
:使得套接字进入被动监听状态。accept()
:等待客户端的连接请求,接受连接并创建一个新的套接字用于通信。
长连接和短链接的区别
- 长连接:连接建立后,客户端和服务器之间的连接会保持活跃,可以进行多次数据交换,直到一方主动关闭连接。
- 短连接:每次通信后,一旦数据交换完成,连接即被关闭,下次通信时需要重新建立连接。
长连接的优缺点
长连接的优点:
- 减少了频繁建立和关闭连接的开销。
- 提高数据传输效率,减少延迟。
- 适合实时性较高的应用场景。
长连接的缺点:
- 占用服务器资源较多,可能影响服务器并发处理能力。
- 若不加管理,可能导致资源泄露。
- 需要心跳维护,增加了一定的复杂度。
TCP拥塞控制的实现方式
- 慢启动:以指数方式增加拥塞窗口大小,直到达到阈值。
- 拥塞避免:增加拥塞窗口大小的速率放慢,转为线性增长。
- 快速重传:接收方连续收到三个重复确认时,发送方立即重传丢失的包,而不是等待超时。
- 快速恢复:在快速重传后,将拥塞阈值设为当前窗口大小的一半,从而快速恢复传输速率。
滑动窗口最大可以是多少
窗口大小字段:在TCP头部中,窗口大小字段是一个16位的数,所以它的最大值理论上是2的16次方减1(65535字节)。
为什么在timewait之后还要等两个msl
- 确保最后一个确认报文能够到达对方。如果这个确认报文丢失,对方将重新发送最后一个FIN包,此时等待两个MSL可以确保有足够的时间接收并响应这个重传的FIN包。
- 防止“老”连接的报文段出现在后续新的连接中。等待两个MSL确保了所有当前连接的报文段都从网络中消失,避免影响新的连接。
连接期间拔掉网线会出现什么情况
- 数据传输中断:正在进行的数据传输会因为丢失网络连接而中断。
- 超时重传:TCP具有超时重传机制,如果在预定的时间内没有收到确认应答,发送方会尝试重传数据包。
- 连接超时关闭:如果重传尝试持续失败,并超过了特定的超时阈值,TCP连接将被认为已经断开,并且会关闭该连接。
如果没有开keep-alive会是什么情况
- 静默中断:连接看似还是建立的状态,因为无法立即检测到断线。
- 无自动检测:因为没有定期的探测包来验证连接状态,所以TCP连接不会主动发现对方已经断线。
- 应用层超时:通常依赖于应用层实现的超时机制来检测连接健康状况,并做出响应处理。
DNS解析的步骤
- 客户端请求:浏览器或其他客户端向本地DNS服务器发起域名解析请求。
- 本地DNS服务器查询:本地DNS服务器首先查看自己的缓存,如果没有相应记录,则向根DNS服务器发起请求。
- 根DNS服务器响应:根DNS服务器不解析域名,而是返回负责该顶级域名(如.com、.net)的顶级域名服务器的地址。
- 顶级域名服务器查询:本地DNS服务器再向顶级域名服务器查询,顶级域名服务器返回负责该域名的权威DNS服务器的地址。
- 权威DNS服务器响应:本地DNS服务器最后向权威DNS服务器查询,权威DNS服务器返回域名对应的IP地址。
- 客户端获取IP地址:本地DNS服务器将解析的结果返回给客户端,客户端得到IP地址后,就可以直接访问该地址的服务器了。
http与https的区别
- 安全性:HTTPS比HTTP更安全,因为HTTPS在传输数据时加密,而HTTP传输的数据是未加密的。
- 端口:HTTP的默认端口是80,HTTPS的默认端口是443。
- 性能:由于加密解密过程,HTTPS在性能上稍微慢于HTTP。
- 证书:HTTPS需要使用SSL/TLS证书来建立安全连接,而HTTP不需要。
https建立连接的步骤
- 客户端发起请求:浏览器(客户端)向服务器发起HTTPS请求,请求建立SSL连接。
- 服务器响应:服务器返回带有公钥的SSL证书给客户端。
- 创建对话密钥:浏览器生成一个随机对话密钥,然后用服务器的公钥加密这个密钥,并发送给服务器。
- 对话密钥解密:服务器用其私钥解密上一步浏览器发送的内容,获取到浏览器生成的对话密钥。
- 加密通信:服务器和浏览器之后的通信都会基于这个对话密钥来进行加密,以保护数据的安全性。
I/O多路复用的原理
I/O多路复用指的是使用单一的I/O线程来处理多个I/O读写操作。其核心原理如下:
- 注册文件描述符:程序向操作系统注册一系列的文件描述符(可以是套接字的描述符,也可以是其他I/O操作的描述符)及其对应的事件(如读或写)。
- 阻塞等待:I/O线程阻塞等待事件发生。事件可能是文件描述符就绪(可读或可写),也可能是定时器超时。
- 处理就绪事件:一旦有事件发生,I/O线程被唤醒并依次处理所有就绪事件。对于每个就绪事件,I/O线程执行操作(如读或写),然后返回等待下一个事件。
进程间调度的方法
- 先来先服务(FCFS):按照进程到达的顺序进行调度。这种方法简单,但可能会导致长进程阻塞短进程。
- 短进程优先(SJF):优先调度估计运行时间最短的进程。这种方法可以最小化平均等待时间,但需要对进程运行时间进行预测。
- 优先级调度:每个进程根据其重要性和类型分配一个优先级,优先级高的进程优先执行。
- 时间片轮转:所有进程轮流使用CPU,每个进程执行一个固定长度的时间片,然后将CPU让给下一个进程。
- 多级反馈队列:根据进程的行为和需求,将其放入不同优先级的队列中,然后按照某种策略(如时间片轮转或优先级)在每个队列中调度。
当一个进程正在读写文件时,文件管理员把文件删掉了会出现什么情况
在大多数现代操作系统中,如果一个进程正在读写文件而同时该文件被删除(通常是通过文件管理员或命令行等操作),则文件的目录条目会被移除,但是文件的实际数据不会立即从磁盘上删除。进程对文件的读写操作可以继续进行,直到所有对该文件的引用都被关闭。只有当最后一个引用(比如打开的文件描述符)被关闭后,操作系统才会释放文件所占用的空间。
多线程中锁的类型
- **互斥锁:最基本的锁类型,同一时间只允许一个线程持有锁。
- **递归锁:允许同一个线程多次获得同一个锁,通常用于递归函数中。
- **读写锁:使多个读线程同时访问共享资源,但写线程访问时独占资源。
- 自旋锁:通过循环等待来尝试获取锁,适用于锁定时间短的情况。
- **条件变量:不是锁本身,但通常与锁配合使用,用来阻塞一个线程直至某个条件为真。
- **信号量:允许多个线程访问一定数量的资源实例,常用于限制对资源的并发访问数。
互斥锁与自旋锁的区别
- **互斥锁:当一个线程试图获取已经被其他线程获取的互斥锁时,该线程会被阻塞并进入睡眠状态,直到锁被释放。因此,互斥锁在发生阻塞时不会消耗CPU时间,适合用于保护长时间操作的临界区资源。
- **自旋锁:当一个线程试图获取已被其他线程获取的自旋锁时,该线程会进入忙等待状态,不断地检查锁是否被释放,而不进入睡眠。这会持续消耗CPU时间,因此自旋锁适用于保护短时间操作的临界区资源,以避免由于上下文切换带来的额外开销。
MySQL数据库中有哪几种常见的索引
- **主键索引:唯一标识表中的每一行,不允许有重复值。
- 唯一索引: 确保数据的唯一性,不允许重复的索引值。
- 普通索引:加快数据检索速度的基本索引。
- 全文索引:对文本内容进行索引,用于全文搜索。
- **组合索引:在多个列上创建的索引,用于多条件查询优化。
数据库的事务特性
- **原子性:事务是最小的执行单元,不可再分,要么全部执行,要么全部不执行。
- **一致性:事务执行前后,数据库从一个一致性状态转换到另一个一致性状态。
- 隔离性:事务的执行不应互相干扰,多个并发事务的执行应相互隔离。
- **持久性:一旦事务提交,则其所做的更改就会被永久保存到数据库中,即使系统崩溃也不会丢失。
乐观锁和悲观锁
- **悲观锁:假设冲突很可能发生,在数据处理过程中通过锁机制阻止其他事务访问该数据。
- 乐观锁:假设冲突很少发生,不会立即锁定数据,而是在提交更新前检查数据在读取后是否被更改过。常通过版本号或时间戳实现。
delete,truncate,drop的区别
- DELETE:从表中删除一行或多行数据,可以搭配WHERE子句进行条件删除,操作可回滚。
- TRUNCATE:删除表中所有行,但保留表结构以便之后使用,操作速度快,但不可回滚。
- DROP:删除整个表,包括数据和表结构,操作不可回滚。
如果有自增字段用哪种方法删除
如果表中包含自增字段并且希望删除所有数据同时重置自增计数器,应使用TRUNCATE
命令,因为它会重置自增计数器到初始值。使用DELETE
命令将不会重置自增计数器。
关系型数据库与kv型数据库的区别
- 关系型数据库:数据以表格的形式储存,数据间有丰富的关系,如一对一、一对多、多对多等。支持复杂的事务和查询操作,并且有良好的ACID特性。
- KV型数据库:即键值对数据库,其中每个键和值都是一个数据项,相互间没有关联。读写性能高,易用于分布式系统,但不支持复杂查询。
redis的数据结构
- **字符串:最常见类型,可以包括字符串、整数或浮点数。
- 列表:有序集合,可以实现堆栈、队列等。
- 集合:无序且唯一的元素集合,可以快速完成交集、并集等操作。
- 哈希:键值对集合,适用于存储对象。
- 有序集合:不仅是集合,还有每个元素关联的分数,可以按分数排序输出。
redis的持久化机制
- RDB:在指定的时间间隔内生成数据集的时间点快照。
- AOF:记录服务器接收到的每个写操作命令,服务器启动时会重新执行这些命令来恢复数据。
算法题: LRU
算法题: 和为k的子数组
收集整理了一份2024年最新C++开发学习资料,既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C++开发知识点,真正体系化!
包含大厂面经、学习笔记、实战项目、大纲路线、讲解视频 领取地址:
https://docs.qq.com/doc/DR2N4d25LRG1leU9Q
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。