每天一套面试题Day10-腾讯高频

题目来自牛客

可以关注我的每日一套面试题专栏,每日一起更新打卡

1.HashMap底层原理和扩容机制

数组+链表 数组+链表/红黑树(JDK8以及之后,在 ?时会变成红黑树 当元素数目大于因子(0.75)×?的时候,会发生扩容,扩容为原来的两倍,在jdk7之前要重新计算来确定位置,由于要么位置在原位置,要么在原位置+原数组长度,所以用哈希值与上原数组长度,如果为真,那么就在原位置+原数组长度,不然的话就不动。确定好在哈希桶的位置后,再尾插进对应的位置。

默认初始容量16,负载因子0.75,当元素数量超过(容量×负载因子)发生扩容。链表长度>=8且数组长度≥64时会转为红黑树,提升查询效率。

2.ArrayList和LinkedList的区别

ArrayList底层基于动态数组,LinkedList底层基于双向链表。 因此ArrayList随机访问快,直接基址+元素大小×索引即可得到位置,LinkedList增删中间快,因为只需要遍历,而ArrayList需要移动。

3.JVM的垃圾回收算法

标记-整理(老年代,无内存碎片),标记-清除(老年代,有内存碎片),标记-复制(新生代,无内存碎片)

4.详细的说说Redis的数据类型

alt

5.Redis的持久化策略

默认RDB。快照。有丢失数据的风险,但恢复快 AOF,以命令的形式追加。数据完整性高,文件更大,恢复比较慢。 RDB + AOF 兼具两者优势。

6.Redis如何与数据库保持双写一致性

双写一致性 指的是,当我们同时使用了数据库(持久化存储)和 Redis(缓存)时,如何保证对一个数据进行更新后,两者存储的数据是相同的。

6.1.并发问题

  • 更新缓存和数据库,如果并发两个写,会因为并发导致数据库和缓存数据不一致。

  • 这里可以用旁路缓存策略,也就是说先更新数据库中的数据,再删除缓存中的数据。这个顺序为什么是这样的呢,因为存在一个读写并发,如果先删除缓存,这时候另一个线程来读的话,发现缓存没有,它去数据库读到旧数据,这时候就把旧数据缓存到缓存中,这时候去更新数据库。最终就会发现redis中的数据还是旧的数据,但是数据库更新了,不一致了。 那我们怎么改善这种问题,可以用延迟双删,我们等另一个线程读完旧的数据库的数据,并且写完缓存再删除一次不就解决了吗

  • 延迟双删,顾名思义,先删除缓存中的数据,再更新数据库中的数据,然后延迟(睡眠一会),再删除一次。→解决了先删除缓存后更新数据库的问题。

  • 当然其实先更新数据库中的数据,再删除缓存中的数据。也存在读写并发,如果我们在缓存中没有读到,就去数据库获取一个旧数据,这时候另一个线程来写数据库,然后删除缓存,我们再把原来从数据库获取到的旧数据缓存在redis中,但是这样有一个问题,就是必须等另一个线程来写数据库,然后删除缓存,都做完之后,再去写缓存,本来写redis就比写sql要快很多,所以这种概率并不高。

  • 但是删了缓存的话,命中率变低,如果要求很高,那我们可以更新缓存+数据库(更新缓存+数据库或者更新数据库+缓存,都存在写写并发问题),但是要解决数据库和缓存数据不一致,我们可以采取

  • 分布式锁,避免并发问题,写操作时加锁,确保同一数据串行更新。也就是请求执行"更新数据库 → 更新缓存"(先更新数据库再更新缓存,先保证数据权威的来源(数据库),失败处理也合理(缓存失败了,也能后面会过期))的完整操作序列。

  • 给缓存加上较短的过期时间,接受出现短暂的缓存不一致,但是缓存的数据反正会很快过期。

6.2.操作失败问题

Redis和数据库是两个独立系统,可能一个成功一个失败。 更新数据库中的数据,再删除缓存中的数据,但是删除缓存中的数据失败了,其他请求打过来不还是不一致吗。

  • 消息队列重试机制。要删除的缓存中的数据加入消息队列,消费者来操作,如果失败,会从消息队列重新读取。
  • 订阅 MySQL binlog,再操作缓存。更新数据库成功会产生一条日志,记录在 binlog 里。订阅这个日志,并且通过ACK机制确认处理这条更新log(也是通过消息队列,但是代码侵入性没有那么强)

7.HTTP/1.0、HTTP/1.1、HTTP/2.0、HTTP/3.0 的区别?

现在浏览的大部分网站,可能还在使用 HTTP/1.1,但正在快速向 HTTP/2 迁移。 HTTP/2 是当前现代网站的标配和主流,能显著提升网页加载速度。 HTTP/3 是未来。

维度 HTTP/1.1 HTTP/2 HTTP/3
传输协议 TCP TCP QUIC (over UDP)
连接模型 持久连接 + 多连接并发 单连接多路复用 单连接多路复用
数据格式 文本 二进制分帧 二进制分帧
队头阻塞 应用层存在 应用层解决,传输层存在 应用层和传输层均解决
头部压缩 HPACK QPACK
0-RTT建连 不支持 不支持 支持

从HTTP/1.1到HTTP/2,核心是改变了数据的传输格式,通过二进制分帧和多路复用解决了应用层效率问题。而从HTTP/2到HTTP/3,核心是更换了底层的传输协议,通过QUIC解决了传输层的根本性瓶颈,提供更低延迟、更可靠的Web体验。

8.从「敲下一个 URL」到「页面出现在屏幕」整条链路全景

  • DNS 主机到本地域名服务器递归查询,本地域名服务器,为了完成对客户端的递归查询承诺,向根、顶级、权限域名服务器发起查询,并接收来自它们的迭代查询响应,最终拿到域名对应的IP。
  • ARP协议,由目的IP得到目的MAC(路由器的MAC)
  • TCP三次握手建立连接
  • 应用层:生成 HTTP 请求 传输层:TCP 分段,添加端口号 网络层:IP 封装,添加 IP 地址 数据链路层:添加 MAC 地址,形成帧 物理层:转换为比特流传输
  • 由IP协议指路到达服务器
  • 服务器再一层层拆开,拆到应用层,解析,响应经过HTTP应用层,TCP传输层,IP网络层,网络接口层等封装,返回客户端
  • 浏览器解析渲染
  • TCP四次挥手断开连接 (连接管理:根据 HTTP 版本和头信息决定是否保持连接或关闭,现代HTTP/1.1默认长连接,可能不会立即断开)

9.HTTP vs. HTTPS 有什么区别?

小林 alt

10.HTTPS 的「秘钥交换 + 证书校验」全流程

HTTPS 的 TLS 握手流程,其核心目标就是两个:第一,通过证书校验来验证服务器的身份,防止中间人攻击;第二,通过密钥交换算法,安全地协商出一个只有双方知道的对称会话密钥,用于后续的高效加密通信

第一步:建立连接与协商基础

    1. TCP 连接建立: 首先,客户端(比如浏览器)会和服务器通过 TCP 三次握手,建立一个可靠的网络连接。这是所有通信的基础。”
    1. ClientHello & ServerHello: “接着,客户端会发送一个 ClientHello 消息,里面主要包括:一个客户端生成的随机数(Client Random)、以及客户端支持的密码套件列表(比如 RSA 或 ECDHE)。 服务器回应一个 ServerHello 消息,从中选出双方都支持的最强密码套件,并也生成一个服务器随机数(Server Random)发给客户端。”

(至此,双方有了两个随机数,并确定了加密算法组合。)

第二步:核心环节一 —— 证书校验

“接下来就是身份验证的关键环节。服务器会将自己的 数字证书 发送给客户端。 客户端收到后,会进行严格的证书校验:

  • 验证证书链:我会检查证书是否由可信的颁发机构签发。浏览器和操作系统里预置了受信任的根CA证书。会用根CA的公钥去验证中间CA的签名,再用中间CA的公钥去验证服务器证书的签名,只要有一环验证失败,就认为身份不可信。
  • 验证内容:还会检查证书的有效期是否过期,以及证书上绑定的域名是否与正在访问的网站一致。 只有所有这些校验都通过,才会信任这个服务器,并使用证书里携带的服务器公钥进行后续操作。 如果失败,浏览器就会给用户显示警告。”

第三步:核心环节二 —— 密钥交换

“身份确认后,双方就要安全地协商出后续通信用的对称密钥了。以两种常见的密钥交换方式为例:

  • 如果是 RSA 算法: “客户端会生成第三个随机数,叫做 预备主密钥。然后,用刚才证书里拿到的服务器公钥加密这个预备主密钥,通过 ClientKeyExchange 消息发送给服务器。只有拥有对应私钥的服务器才能解密它。这样,双方就都拥有了客户端随机数、服务器随机数和预备主密钥。”

  • 如果是现在更推荐的 ECDHE 算法: “服务器会在证书发送后,发送一个 ServerKeyExchange 消息,包含它的椭圆曲线参数和公钥。客户端也生成自己的参数和公钥,通过 ClientKeyExchange 发送回去。然后,双方利用迪菲-赫尔曼密钥交换协议的原理,各自在本地计算,最终得到一个相同的共享密钥,这个共享密钥就作为预备主密钥。这种方式的好处是提供了前向保密,即使服务器私钥未来泄露,过去的通信也无法被解密。”

“无论哪种方式,现在客户端和服务器都拥有了三个共同的随机要素:Client Random, Server Random, 和 Premaster Secret。它们会通过一个伪随机函数,共同计算出最终的 主密钥会话对称密钥。”

第四步:收尾与安全通道建立

为了确认握手过程没有被篡改,并且密钥已经协商成功: 客户端和服务器会互相发送一个 Finished 消息。这个消息是用刚刚生成的会话密钥加密的,并且包含了之前所有握手消息的摘要。 对方收到后,会尝试解密并验证摘要。如果验证成功,就说明整个握手过程是安全且一致的。在这之前,双方会先发送 ChangeCipherSpec 消息,通知对方:‘从现在起,我们之后所有的通信都要用刚才商量好的密钥来加密了’。

至此,TLS 握手全部完成。一个安全的加密通道就建立起来了,之后所有的 HTTP 请求和响应都会在这个加密通道里进行。

**证书体系解决了‘你是谁’的身份问题,非对称加密的密钥交换解决了‘如何安全地传小纸条’的问题,最后再由高效的对称加密来负责‘之后的大量秘密通信’。

#面试真题#
每日一套面试真题 文章被收录于专栏

记录刷过的面试真题

全部评论

相关推荐

10-30 15:07
河南大学 Java
1.自我介绍2.展开介绍项目,项目类型(学习项目),分工是什么样的?介绍自己负责的部分3.为什么考虑用RocketMQ?(支持事务消息,保证最终一致性),怎么保证最终一致性?(事务消息的原理+MQ的重投机制)4.Redis用的什么数据结构?Redis的常见的数据结构以及底层实现。(主要讲了SDS,ziplist,listpack,skiplist)5.分布式事务的选型怎么考虑的?为什么要手写TCC?(标准的TCC在Confirm失败的时候会直接cancel,我的实现会对Confirm重试)6.看起来整个的考虑还是比较完整的,有上线吗?(并没有,这里嘴抽了提了限流没做)7.如果要做的话会考虑怎么做限流?(给自己挖坑了)8.第二个项目是啥?(练手项目)你有基于他的视频做一些优化吗?(没有)一面的时候做过题了吗?9.除了Java还接触过其他吗(大一学过C)10.你的商品的表结构是怎么设计的?会有卖家吗,还是说有固定的SKU?(卖家是平台)11.基本上差不多,多大模型有了解吗?(用过LangChain4J)可以详细介绍一下吗,他这个框架是怎么设计的比如分为哪几个模块儿?(这个真不会,感觉就是掉API啊)12.你现在对技术方向上有什么片好吗?想往哪个方向发展?()13.反问:1.二面通过还有面试吗? 2.提一些建议:整体上都挺好的,沟通起来比较顺畅,对项目自己负责的比较熟悉,其他同学的也有了解,有一点你的简历上的重点可以再突出一下。3:为什么面试时间这么短?一面做过题了二面就不做了时间有节省,另外如果简历上的东西比较复杂的话可能会耗时比较多(我的项目也挺复杂的啊)===========================================面了20分钟,问项目的时候,算是问了一个八股,没做题。这种情况正常吗?还是说已经招到人了?
查看11道真题和解析
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务