25 届暑期实习已经开展 1 个月了,很多同学反馈,腾讯面试约的很多,即使挂了,还会被其他部门捞起来继续面,看下腾讯的实习 hc 还是蛮多的。
今天分享一位同学腾讯 wxg(微信事业群)的暑期实习校招面经,同学虽然学的是Java,但是 wxg 的面试官都是C++/GO 技术栈的,对 Java 不太熟悉,所以面试没怎么问Java内容,重要拷打计算机础去了,也很看重算法,一般都会出 1-2 个算法题,也见过直接出了 3 个算法题的微信面经。
所以,每个公司的面试风格都会有所区别,像腾讯和字节都偏向计算机基础问的多一些,而阿里、美团、京东等其他以Java技术栈为主的公司,就会主要问Java相关的内容。
这次面经考察的内容,我帮大家罗列一下。
数据库:acid、隔离性、锁、乐观锁、sql 注入
网络
HTTPS了解吗?讲讲 TSL 流程
传统的 TLS 握手基本都是使用 RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书文件其实就是服务端的公钥,会在 TLS 握手阶段传递给客户端,而服务端的私钥则一直留在服务端,一定要确保私钥不能被窃取。
在 RSA 密钥协商算法中,客户端会生成随机密钥,并使用服务端的公钥加密后再传给服务端。根据非对称加密算法,公钥加密的消息仅能通过私钥解密,这样服务端解密后,双方就得到了相同的密钥,再用它加密应用消息。
我用 Wireshark 工具抓了用 RSA 密钥交换的 TLS 握手过程,你可以从下面看到,一共经历了四次握手:
TLS 第一次握手
首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:(1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。(2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。(3)客户端支持的密码套件列表,如 RSA 加密算法。
TLS 第二次握手
服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:(1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。(2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。(3)确认的密码套件列表,如 RSA 加密算法。(4)服务器的数字证书。
TLS 第三次握手
客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。
如果证书没有问题,客户端会
从数字证书中取出服务器的公钥
,然后使用它加密报文,向服务器发送如下信息:(1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。(2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。
服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」
。
TLS 第四次握手
服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。
然后,向客户端发送最后的信息:(1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。
CA 签发流程是什么?
image.png
服务方S
向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证
(不交私钥)
CA
通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等
如信息审核通过,
CA会向申请者签发认证文件-证书
证书包含以下信息:
申请者公钥
、申请者的组织信息和个人信息、签发机构CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用CA的私钥对信息摘要进行加密,密文即签名
浏览器缓存内CA 证书哪里来的?
浏览器缓存中的CA证书通常来自于浏览器预装的根证书颁发机构(Root Certificate Authority),这些根证书是浏览器或操作系统内置的信任的CA机构颁发的证书。
当用户访问一个使用SSL/TLS加密的网站时,浏览器会检查网站提供的数字证书是否由根证书中的CA颁发,从而验证网站的身份和安全性。如果数字证书的颁发机构是根证书中的CA之一,浏览器会信任该证书,建立安全连接。
最后通信的时候,是怎么加密的?是用三个随机数加密吗?
客户端和服务器手里有了三个随机数:
Client Random、Server Random 和 Pre-Master
。用这三个作为原始材料,就可以生成用于加密会 话的主密钥,叫“
Master Secret
”。而黑客因为拿不到“Pre-Master”,所以也就得不到主密钥。
为了保证真正的“完全随机”“不可预测”,把三个不可靠的随机数混合起来,那么“随机”的程度就非常高了,足够让黑客难以猜测。
Master Secret 计算方式贴一下 RFC 文档里的公式:
master_secret = PRF(pre_master_secret, "master secret" , ClientHello.random + ServerHello.random )
这里的“PRF”就是伪随机数函数,它基于密码套件里的最后一个参数,比如这次的 SHA384,通过摘要算法来再一次强化“Master Secret”的随机性。
主密钥有 48 字节,但它也不是最终用于通信的会话密钥,还会再用 PRF 扩展出更多的密钥,比如客户端发送用的会话密钥(client_write_key)、服务器发送用的会话密钥(server_write_key)等等,避免只用一个密钥带来的安全隐患。
系统
讲讲中断的流程
中断是计算机系统中一种机制,用于在处理器执行指令时暂停当前任务,并转而执行其他任务或处理特定事件。
以下是中断的基本流程:
发生中断
:当外部设备或者软件程序需要处理器的注意或者响应时,会发出中断信号。处理器在接收到中断信号后,会停止当前执行的指令,保存当前执行现场,并跳转到中断处理程序执行。
中断响应
:处理器接收到中断信号后,会根据中断向量表找到对应的中断处理程序的入口地址。处理器会保存当前执行现场(如程序计数器、寄存器状态等),以便在中断处理完成后能够恢复执行。
中断处理
:处理器跳转到中断处理程序的入口地址开始执行中断处理程序。中断处理程序会根据中断类型进行相应的处理,可能涉及到保存现场、处理中断事件、执行特定任务等。
中断的类型有哪些?
中断按事件来源分类,可以分为外部中断和内部中断。中断事件来自于CPU外部的被称为外部中断,来自于CPU内部的则为内部中断。
进一步细分,外部中断还可分为可屏蔽中断(maskable interrupt)和不可屏蔽中断(non-maskable interrupt)两种,而内部中断按事件是否正常来划分可分为软中断和异常两种。
外部中断
的中断事件来源于CPU外部,必然是某个硬件产生的,所以外部中断又被称为硬件中断(hardware interrupt)。计算机的外部设备,如网卡、声卡、显卡等都能产生中断。外部设备的中断信号是通过两根信号线通知CPU的,一根是INTR,另一根是NMI。CPU从INTR收到的中断信号都是不影响系统运行的,CPU可以选择屏蔽(通过设置中断屏蔽寄存器中的IF位),而从NMI中收到的中断信号则是影响系统运行的严重错误,不可屏蔽,因为屏蔽的意义不大,系统已经无法运行。
内部中断
来自于处理器内部,其中软中断是由软件主动发起的中断,常被用于系统调用(system call);而异常则是指令执行期间CPU内部产生的错误引起的。异常也和不可屏蔽中断一样不受eflags寄存器的IF位影响,区别在于不可屏蔽中断发生的事件会导致处理器无法运行(如断电、电源故障等),而异常则是影响系统正常运行的中断(如除0、越界访问等)。
中断的作用是什么?
中断使得计算机系统具备应对对处理突发事件的能力,提高了CPU的工作效率。
如果没有中断系统,CPU就只能按照原来的程序编写的先后顺序,对各个外设进行查询和处理,即轮询工作方式,轮询方法貌似公平,但实际工作效率却很低,却不能及时响应紧急事件。
堆和栈的作用和区别是什么?
堆是用于动态分配内存的区域,需要手动管理内存;栈用于存储函数调用和局部变量,由编译器自动管理。
堆中的内存分配通常由程序员通过调用类似 malloc()、new等函数来实现,但需要手动释放,如果没有正确释放堆中分配的内存,可能会导致内存泄漏。;栈中的内存分配和释放自动化,遵循“后进先出”的原则。
栈空间的数据线程中是独立的,堆空间的数据在线程中是共享的,读写操作的时候,需要加锁,保证并发安全。
数据库
事务四个特性是什么?
实现事务必须要遵守 4 个特性,分别如下:
原子性(Atomicity)
:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。
一致性(Consistency)
:是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
隔离性(Isolation)
:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
持久性(Durability)
:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离性怎么实现的?
隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
mysql 有哪些锁?
全局锁
:通过flush tables with read lock 语句会将整个数据库就处于只读状态了,这时其他线程执行以下操作,增删改或者表结构修改都会阻塞。全局锁主要应用于做
全库逻辑备份
,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。
表锁:通过lock tables 语句可以对表加表锁,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。
元数据锁:当我们对数据库表进行操作时,会自动给这个表加上 MDL,对一张表进行 CRUD 操作时,加的是
MDL 读锁
;对一张表做结构变更操作的时候,加的是
MDL 写锁
;MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。
意向锁:当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。
意向锁的目的是为了快速判断表里是否有记录被加锁
。
行级锁
:InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。
记录锁,锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的,满足读写互斥,写写互斥
间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。
Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。
一致性怎么实现的?
持久性是通过 redo log (重做日志)来保证的;
原子性是通过 undo log(回滚日志) 来保证的;
隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
用mysql怎么实现乐观锁?
乐观锁是一种并发控制机制,主要用于管理数据库中记录的并发修改。它假设多个事务在大多数时间不会同时修改同一条记录,因此在实际提交更改之前不加锁。乐观锁通常通过记录版本号或时间戳来实现。
在表中添加一个
version
字段,每次更新记录时,将这个版本号加一。更新操作时,检查版本号是否与数据库中的版本号一致,如果一致,执行更新并将版本号加一;如果不一致,表示记录已经被其他事务更新,此次更新失败。