【腾讯】实习基地专项,问的很简单|0330
- 自我介绍
- 做了什么项目,怎么实现的
- 项目有哪些难点,注意点
- 为什么你的项目中redis和mysql一起使用,说说理由
- 你的菜品有设置库存吗,高并发情况下多个用户同时获取少量菜品,你如何确保数据不会出错 -- 可以设置乐观锁
- udp和tcp有什么区别
- tcp如何保证可靠的
- www.qq.com这个网页的访问过程
- tcp三次握手过程讲一下
- http和https协议有什么区别
- tcp属于那一层,http属于哪一层
- http协议所在层还有哪些协议,你说一下
- c++了解吗,说说值传递,引用传递,指针传递的区别 -- 不了解c++,回答不全,
- 代码题,一个纯数字字符串,如果有相邻数字和为10,将其移除,最后返回字符串长度 例 364752 => 2
- 代码题,升序链表,删除重复值
- 哪里人,是否对工作地有要求
反问
- 我的面试表现如何,哪里需要改进 -- 基础很扎实,但是实际应用方面偏弱
- 如果有二面,二面大概要多久 -- 大概一周会进行二面
PS:面试官很和蔼 面完半小时官网显示过一面,第二天早上约二面
来源:s__t
面经专栏直通车: https://www.nowcoder.com/creation/manager/columnDetail/0xKkDM
1. 为什么项目中redis和mysql一起使用,说说理由?
参考回答:
在项目中同时使用Redis和MySQL,主要是基于它们各自的优势和特性,以满足不同的数据存储和访问需求。
- 数据类型的差异:
- MySQL:是关系型数据库,适合存储结构化数据,如用户信息、订单详情等。它提供了强大的数据持久化、事务处理、复杂查询(如连接、子查询等)以及数据完整性保证(如ACID属性)。
- Redis:是内存中的数据结构存储系统,它可以用作数据库、缓存和消息代理。Redis支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,非常适合存储非结构化数据和进行高速数据操作。
- 性能考虑:
- MySQL:数据存储在硬盘上,读写操作受到I/O限制,虽然可以通过索引、查询优化等手段提高性能,但在处理大量并发读写请求时,性能可能成为瓶颈。
- Redis:数据存储在内存中,读写速度非常快,非常适合作为缓存层来减轻MySQL的压力。通过缓存热点数据和计算结果,可以显著提高系统的响应速度和吞吐量。
- 数据一致性与持久化:
- MySQL:提供了强一致性保证,通过事务和ACID属性确保数据的完整性和一致性。同时,MySQL也提供了数据持久化功能,确保在发生故障时数据不会丢失。
- Redis:虽然也提供了持久化功能(如RDB和AOF),但其主要目的是在内存数据丢失后能够恢复数据,而不是提供强一致性保证。Redis更适合作为临时数据存储或缓存使用。
- 功能扩展与灵活性:
- MySQL:作为成熟的关系型数据库,提供了丰富的功能和强大的查询语言(SQL),支持复杂的业务逻辑和数据处理需求。
- Redis:提供了发布/订阅、事务、Lua脚本等高级功能,可以方便地实现消息队列、分布式锁、计数器、实时分析等应用场景。
- 成本考虑:
- 在某些场景下,使用Redis作为缓存层可以减少对MySQL的访问次数,从而降低数据库服务器的负载和硬件成本。同时,Redis的高性能也可以帮助提高系统的整体性能和用户体验。
综上所述,项目中同时使用Redis和MySQL可以充分利用它们各自的优势,满足不同的数据存储和访问需求,提高系统的性能、可扩展性和灵活性。
学习指引:mysql+redis 使用场景和优点
2. 你的菜品有设置库存吗,高并发情况下多个用户同时获取少量菜品,你如何确保数据不会出错 ?
参考回答:
当多个用户同时尝试获取或购买同一菜品时,必须采取措施来防止数据出错,如超卖或库存不一致等问题。
- 使用数据库事务:
- 当更新库存时,使用数据库事务来确保操作的原子性。这意味着要么所有操作都成功,要么所有操作都失败并回滚。
- 通过事务,你可以避免在多个操作之间出现数据不一致的情况。
- 乐观锁或悲观锁:
- 乐观锁:在数据更新时检查是否有其他操作修改了数据。如果有,则当前操作失败或重试。这通常通过版本号、时间戳或特定的字段来实现。
- 悲观锁:在数据被修改期间锁定数据,防止其他操作访问。这可以确保数据在事务处理过程中不会被其他事务修改。
- 分布式锁:
- 在分布式系统中,你可能需要使用分布式锁来确保跨多个服务器或实例的数据一致性。例如,Redis的RedLock算法或基于Zookeeper的锁。
- 队列化处理:
- 使用消息队列(如RabbitMQ、Kafka等)来处理库存更新请求。这样,所有的请求都会按照它们到达的顺序进行处理,从而避免了并发冲突。
- 库存预留:
- 当用户下单但尚未支付时,可以预留库存一段时间。这需要使用定时任务或延迟队列来确保在预定时间内未支付的订单会释放库存。
学习指引:高并发场景下,如何设计订单库存架构,一共9个关键性问题
3. udp和tcp有什么区别?
参考回答:
- 连接方式**:
- UDP:无连接协议,发送数据前不需要建立连接。它简单地将数据报发送到网络,不保证数据能否到达目的地。
- TCP:面向连接的协议,在发送数据之前,必须在发送端和接收端之间建立可靠的连接。
- 可靠性:
- UDP:提供不可靠的服务,数据报可能在传输过程中丢失、重复或乱序。它不提供数据重传机制。
- TCP:提供可靠的数据传输服务,通过确认、重传和流量控制机制确保数据的正确、有序传输。
- 数据传输方式:
- UDP:基于数据报文的传输方式,每个数据报独立封装,不保留数据之间的顺序关系。
- TCP:基于字节流的传输方式,将数据视为连续的字节流,不保留数据的报文边界。
- 传输效率:
- UDP:由于无需建立连接和进行确认,UDP的传输效率通常比TCP高,尤其适用于实时性要求较高的场景(如VoIP、视频流等)。
- TCP:虽然传输效率相对较低,但提供了可靠的数据传输服务,适用于需要保证数据完整性和顺序性的场景(如文件传输、数据库操作等)。
- 资源消耗:
- UDP:资源消耗较少,因为它不需要维护连接状态和进行复杂的流量控制。
- TCP:资源消耗相对较多,需要维护连接状态、进行流量控制和数据重传等操作。
- 头部开销:
- UDP:UDP报文的头部开销较小,只包含基本的源端口、目的端口、长度和校验和等信息。
- TCP:TCP报文的头部开销相对较大,包含了更多的控制信息和状态信息。
- 应用场景:
- UDP:适用于对实时性要求较高、可以容忍一定数据丢失的场景,如DNS查询、实时音视频传输等。
- TCP:适用于需要保证数据可靠性和顺序性的场景,如HTTP请求、FTP文件传输、SMTP邮件传输等。
学习指引:一文搞懂TCP与UDP的区别
4. tcp如何保证可靠的?
参考回答:
TCP(传输控制协议)保证可靠传输主要通过以下几个关键机制:
- 确认应答机制:TCP协议中,接收方在成功接收到数据后,会向发送方发送一个确认应答(ACK)报文。这个机制确保了发送方能够知道哪些数据已经被成功接收。如果发送方没有收到确认应答,它会重传数据,直到数据被成功接收并确认。
- 超时重传机制:在网络传输中,数据包可能会丢失或延迟。为了解决这个问题,TCP引入了超时重传机制。发送方在发送数据后会等待接收方的确认应答,如果等待超时仍未收到确认,发送方会重传数据。这个机制确保了数据的可靠传输。
- 连接管理:TCP通过三次握手建立连接,并通过四次挥手断开连接。这种严格的连接管理确保了通信双方的状态一致,避免了在数据传输过程中出现混乱。
- 滑动窗口机制:TCP使用滑动窗口来控制数据的流量。发送方根据接收方的窗口大小来调整自己的发送速率,确保接收方能够及时处理接收到的数据。这个机制避免了因发送速率过快而导致的数据丢失或乱序问题。
- 拥塞控制:当网络发生拥塞时,TCP会降低发送速率,以减少网络中的数据包数量。这个机制通过避免过多的数据包同时传输来防止网络拥塞的发生,从而保证了数据的可靠传输。
TCP通过确认应答机制、超时重传机制、连接管理、滑动窗口机制和拥塞控制等关键机制来确保数据的可靠传输。这些机制共同作用,使得TCP成为了一种非常可靠的网络传输协议。
学习指引:TCP的可靠性传输是如何保证的
5. www.qq.com这个网页的访问过程?
参考回答:
- 输入网址: 用户在浏览器的地址栏中输入www.qq.com这个网址,这是访问过程的开始。
- 解析URL: 浏览器首先解析输入的URL,将域名(www.qq.com)和需要请求的资源(在这里是首页)分离开来。这样浏览器就知道了需要向哪个服务器发送请求,以及请求的具体内容是什么。
- DNS域名解析: 接下来,浏览器需要通过DNS协议将域名解析为对应的IP地址。这个过程可能涉及多个步骤,包括查询本地的hosts文件、DNS缓存、以及向DNS服务器发送查询请求。最终,浏览器会获得www.qq.com对应的IP地址。
- 建立TCP连接: 在获得IP地址后,浏览器会尝试与目标服务器建立TCP连接。这个过程包括TCP的三次握手,确保双方都具有可靠的接收和发送能力。由于现代网页通常使用HTTPS协议进行加密传输,因此在TCP连接建立后,还会进行SSL握手以协商加密使用的对称密钥。
- 发送HTTP请求: TCP连接建立成功后,浏览器会向服务器发送HTTP请求。这个请求包含了用户想要访问的资源的信息(如首页的HTML文件),以及浏览器的相关信息(如浏览器类型、版本等)。
- 服务器处理请求: 服务器接收到HTTP请求后,会进行相应的处理。这可能包括从数据库中检索信息、执行服务器端脚本、生成动态内容等。对于www.qq.com这样的门户网站,服务器可能需要处理大量的并发请求,并确保快速、准确地响应每一个请求。
- 返回响应: 服务器处理完请求后,会生成一个HTTP响应。这个响应包含了用户请求的资源(如HTML文件、图片、CSS样式表等),以及一些额外的信息(如状态码、响应头等)。然后,服务器会将这个响应发送回浏览器。
- 浏览器渲染页面: 浏览器接收到服务器的响应后,会开始解析和渲染页面。这个过程包括解析HTML文件、加载和应用CSS样式表、执行JavaScript脚本等。最终,用户会在浏览器的窗口中看到www.qq.com的首页内容。
- 断开TCP连接: 当浏览器完成页面的渲染,并且确定不再需要从服务器接收数据时,它会发起TCP的四次挥手过程来断开与服务器的连接。这样可以释放网络资源,为其他请求提供空间。
学习指引:在浏览器中输入www.qq.com后执行的全部过程
6. tcp三次握手过程讲一下?
参考回答:
TCP的三次握手过程是建立TCP连接的重要步骤,它确保了通信双方能够建立一个可靠的数据传输通道:
- 第一次握手:客户端向服务器发送一个SYN报文段(SYN=1,seq=x),其中SYN表示同步序列编号,用于初始化序列号。此时,客户端进入SYN_SEND状态,等待服务器的确认。
- 第二次握手:服务器收到客户端的SYN报文段后,必须确认客户的SYN(即发送一个ACK报文段,ack=x+1),同时自己也发送一个SYN报文段(SYN=1,seq=y),即SYN+ACK报文段。这个报文段既用来确认客户端的初始序列号,又用来同步自己的序列号给客户端。此时,服务器进入SYN_RECV状态。
- 第三次握手:客户端收到服务器的SYN+ACK报文段后,会向服务器发送一个ACK报文段(ack=y+1),表示已经收到了服务器的SYN报文段并确认了其初始序列号。这个报文段发送完毕后,客户端和服务器都进入ESTABLISHED状态,表示TCP连接已经成功建立。
通过这三次握手过程,客户端和服务器之间建立了一个可靠的连接,可以开始进行数据传输。在这个过程中,双方都会随机选择一个初始序列号,并且每次发送数据后都会更新序列号,以确保数据的顺序性和可靠性。同时,如果在握手过程中出现任何问题(如超时、序列号不匹配等),则连接建立会失败,双方会重新尝试建立连接或报告错误。
学习指引:一文读懂TCP的三次握手(详细图解)
7. http和https协议有什么区别?
参考回答:
HTTP和HTTPS协议之间的主要区别体现在安全性、连接方式和使用的端口上。
- 安全性:HTTP协议是超文本传输协议,信息在传输过程中是明文形式,如果攻击者截取了浏览器和服务器之间的传输报文,就可以直接读懂其中的信息,因此安全性较低。而HTTPS协议是在HTTP上建立的SSL加密传输协议,并对传输数据进行加密。HTTPS将对称加密与非对称加密结合起来,充分利用两者之长。在交换密钥环节,HTTPS使用非对称加密方式,之后的报文交换则使用对称加密方式。具体做法是:发送密文的一方,首先用非对称加密算法,生成一个对称加密算法的密钥(此过程称为握手),然后把这个密钥用对方的公钥加密,发送给对方;对方收到后,用自己的私钥解密得到这个密钥,这样双方达成了密钥上的一致。之后,双方就使用这个密钥进行对称加密传输,完成对交换信息的加密传输。所以,HTTPS协议的安全性比HTTP协议的安全性高。
- 连接方式:HTTP协议是基于请求响应模式的,是一个无状态的协议。而HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
- 端口不同:HTTP协议和HTTPS协议使用的默认端口也不一样。HTTP协议使用的端口是80,而HTTPS协议使用的端口是443。
HTTPS协议是HTTP协议的升级版本,是在HTTP协议的基础上增加了SSL加密传输层,并对传输数据进行加密。HTTPS协议将对称加密与非对称加密结合起来,充分利用两者之长。因此,HTTPS协议的安全性比HTTP协议高。在网络通信中,如果传输的信息对安全性要求较高,建议使用HTTPS协议。
8. tcp属于那一层,http属于哪一层?
参考回答:
在计算机网络体系结构中,TCP(传输控制协议)和HTTP(超文本传输协议)分别属于不同的层次。
- TCP属于传输层:
- TCP是OSI(开放系统互连)七层模型中的第四层,也就是传输层。它提供面向连接的、可靠的、基于字节流的传输服务。TCP负责将数据从发送端传输到接收端,并确保数据的顺序性和可靠性。
- HTTP属于应用层:
- HTTP是OSI七层模型中的第七层,也就是应用层。它是在TCP/IP协议族中使用的一个应用层协议,用于在网络中传输超文本(如HTML文档)和其他类型的内容。HTTP定义了客户端(如Web浏览器)与服务器(如Web服务器)之间通信的规则和标准。
当在Web浏览器中输入一个网址并按下回车键时,HTTP协议会生成一个请求消息,这个消息随后会被传递到TCP层。TCP层会将这个请求消息封装成一个或多个TCP数据包,并确保这些数据包能够可靠地传输到目标服务器。服务器收到数据包后,会逐层解封装,最终到达应用层处理HTTP请求,并返回相应的响应。
学习指引:OSI七层模型、TCP/IP四层模型
9. http协议所在层还有哪些协议,你说一下?
参考回答:
HTTP协议属于应用层,在应用层中,除了HTTP协议之外,以下是一些常见的应用层协议:
- FTP(文件传输协议):用于在网络中传输文件,支持文件的上传和下载。
- SMTP(简单邮件传输协议):用于发送电子邮件。当你在电子邮件客户端编写并发送一封电子邮件时,SMTP协议负责将邮件传递到对方的邮件服务器。
- POP3(邮局协议第三版)和IMAP(Internet邮件访问协议):这两个协议通常用于从邮件服务器上接收电子邮件。POP3允许用户下载邮件到本地计算机进行离线阅读,而IMAP则支持更复杂的邮件操作,如创建文件夹、标记邮件等。
- Telnet(远程终端协议):允许一个用户通过网络登录到另一台计算机上进行远程操作,就像直接在那台计算机上操作一样。
- DNS(域名系统):用于将域名(如www.example.com)解析为对应的IP地址,以便计算机能够找到并连接到相应的网络服务器。
- SNMP(简单网络管理协议):用于网络管理系统,允许管理员查询和修改网络设备(如路由器、交换机)的配置信息。
- SSH(安全外壳协议):提供安全的远程登录和其他安全网络服务。SSH协议可以有效防止远程管理过程中的信息泄露问题。
- HTTPS:是HTTP的安全版本,通过使用SSL/TLS协议对通信内容进行加密和身份验证,确保数据传输的安全性和完整性。
学习指引:一文弄懂所有应用层的协议
10. c++了解吗,说说值传递,引用传递,指针传递的区别?
参考回答:
在C++中,函数参数传递主要有三种方式:值传递、引用传递和指针传递。它们各有特点和用途,下面分别进行解释:
- 值传递(Pass by Value):
- 在值传递中,函数接收的是参数值的一个副本,而不是参数本身。因此,在函数内部对参数的修改不会影响到原始变量。
- 值传递适用于那些不需要修改原始数据,只需要使用其值的场景。
- 由于传递的是副本,如果数据结构较大,可能会产生一定的性能开销(复制成本)。
- 引用传递(Pass by Reference):
- 在引用传递中,函数通过引用直接访问原始变量。对引用的任何修改都会直接反映在原始变量上。
- 引用传递通常用于需要修改原始数据,或者避免数据复制开销的场景。
- 引用必须在声明时就被初始化,并且一旦初始化后就不能改变引用的关系(即不能重新指向其他变量)。
- 使用引用传递时需要注意,因为函数内部可以修改原始数据,所以必须确保这种修改是安全的、符合预期的。
- 指针传递(Pass by Pointer):
- 指针传递中,函数接收的是指向原始变量的指针。通过指针,函数可以间接访问和修改原始变量。
- 指针传递也适用于需要修改原始数据或避免数据复制的场景。
- 与引用不同,指针可以在任何时候被重新赋值以指向不同的变量。
- 使用指针传递时需要特别小心,因为指针操作(如解引用)可能导致未定义行为,比如空指针解引用、野指针等。
- 指针还提供了更多的灵活性,比如可以传递空指针作为特殊标志,或者通过指针的算术运算来访问数组元素等。
总结来说:
- 值传递是安全的,因为它不会修改原始数据,但可能产生性能开销。
- 引用传递和指针传递都可以用来修改原始数据,但使用时需要更加小心以确保数据的完整性和安全性。
- 引用传递在语法上更简洁,且一旦初始化后就不能改变引用的关系;而指针传递提供了更多的灵活性和控制力,但也需要更多的注意来避免潜在的问题。
学习指引:c++ 引用和指针传参的区别以及优缺点
11. 代码题,一个纯数字字符串,如果有相邻数字和为10,将其移除,最后返回字符串长度?
参考回答:
可以通过栈(Stack)的数据结构来解决。遍历字符串中的每个数字,对于每个数字,检查它和栈顶的数字之和是否为10。如果是,就将栈顶的数字弹出;如果不是,就将这个数字压入栈中。最后,栈中的元素个数就是要找的字符串的长度。
以下是一个Python的实现:
def remove_pairs(s): stack = [] for char in s: if stack and int(char) + int(stack[-1]) == 10: stack.pop() else: stack.append(char) return len(stack) # 测试 s = "1234567890" print(remove_pairs(s)) # 输出:2,因为可以移除"19"、"28"、"37"、"46"、"5"这些相邻和为10的数字对,剩下"0"和"8"
这个算法的时间复杂度是O(n),其中n是字符串的长度。
12. 代码题,升序链表,删除重复值?
参考回答:
首先,定义一个链表节点类:
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
接下来,实现一个函数来删除升序链表中的重复元素:
def delete_duplicates(head): if not head: return None current = head while current and current.next: if current.val == current.next.val: current.next = current.next.next else: current = current.next return head
这个函数通过遍历链表并比较当前节点和下一个节点的值来工作。如果两个节点的值相同,它就将当前节点的
next
指针指向下一个节点的下一个节点,从而跳过重复值。如果值不同,它就移动到下一个节点。下面是一个完整的示例,包括创建链表、调用删除函数和打印结果:
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def delete_duplicates(head): if not head: return None current = head while current and current.next: if current.val == current.next.val: current.next = current.next.next else: current = current.next return head def print_list(head): current = head while current: print(current.val, end=" -> ") current = current.next print("None") # 表示链表结束 # 创建一个升序链表,包含重复值 head = ListNode(1, ListNode(1, ListNode(2, ListNode(3, ListNode(3))))) print("原始链表:") print_list(head) # 输出: 1 -> 1 -> 2 -> 3 -> 3 -> None # 删除重复值 head = delete_duplicates(head) print("删除重复值后的链表:") print_list(head) # 输出: 1 -> 2 -> 3 -> None
面经专栏直通车: https://www.nowcoder.com/creation/manager/columnDetail/0xKkDM
收录各个网友分享的各个公司的面经,并给出答案。