面试题总结4
自我介绍一下
对 node.js 有了解吗
node 指网络节点,js 指 JavaScript,综合就是开发者使用 JavaScript 编写服务端应用程序。是一个服务端运行的环境
Docker 是什么?常用指令有哪些
Docker 是一个可以将程序环境依赖打包成镜像的一个容器,容器中的各个应用互不影响。
他是一个 CS 架构:客户端发送指令,服务端:接收处理指令、管理镜像容器。
镜像操作的指令:docker pull 从 docker 拉取镜像、docker save 将镜像保存到文件、docker rmi 删除镜像、docker load 加载镜像文件
容器操作的指令:docker run 运行容器、docker exec 进入容器、exit 退出容器、rm 删除容器
介绍一下 rabbitMQ
RabbitMQ 是一种常见的消息队列中间件,是两个系统之间进行通讯的一种方式。优点:服务解耦、一步通讯、流量消峰。缺点:可用性降低、复杂度提高。还有其他的一些消息队列实现:最简单的消息队列 Redis 的 Stream,功能最全面的消息队列 RocketMQ、专注于大数据处理的 kafka。
说一下消息队列中的消息确认机制
消息确认机制他保障了消息的一个可靠性。
对于生产者来说:有两种消息 确认机制
1️⃣ 生产者发送消息后,主动等待 MQ 返回一个 ACK,
2️⃣ 生产者不需要等待返回结果,而是 MQ 返回 ack 后回调函数会通知生产者结果。
对于消费者来说: 消费者在消费消息后想 MQ 发送一个 ack 回执,只有当 MQ 收到回执后才会删除该消息,否则返回会出发重试机制,MQ 重新向消费者发送消息,如果消费者什么都不返回,MQ 会一直等待。当然我们可以设置确认模式为自动,这样就防止消费者一直不发送消息,导致等待。
如何保证缓存和数据库的一致性
在开发中只要使用了缓存,那么就都不能保证强一致问题,只能保证最终一致性,最本质的原因就是数据在存储到缓存和磁盘这几个操作不是原子的,在高并发情况下,可能有线程 A 操作了缓存后再去操作数据库,线程 B 又将缓存修改了回来,这样就导致读到了脏数据。所以我们要考虑的是缓存和数据库的操作顺序问题。所以市面上比较好的一种解决缓存一致性的办法就是:读操作:先读缓存,没有在读数据库,然后在写入缓存。写操作:先更新数据库,在删除缓存。 但是这样也不能完美保证缓存是强一致的,因为会有小概率出现数据不同步的现象。
数据库三范式
第一范式:保证原子性,每一个字段都是不能够再细分的。
第二范式:在第一范式的基础上消除非主属性对候选键的部分依赖。
三范式:在第二范式的基础上,消除传递依赖。
说一下 redis 的数据类型
redis 一共有 9 种数据类型,其中 5 种基本数据类型:String 简单动态字符串,list 列表,set 集合,Hash 散列表,Zset 带分数的集合,4 中特殊数据类型:HyperLogLogs 基数统计,BitMap 位图,geo 地理坐标,Stream 消息队列。
讲一下缓存穿透
缓存穿透产生的原因是:在并发场景下,不断的去访问一个缓存和数据库都不存在的数据,给数据库带来了巨大压力,严重可能导致数据库宕机。解决方案:1️⃣可以缓存一个 null 值,第一个请求访问不到数据后,在缓存中做一个 null 值处理,让其他请求访问缓存时就可以直接拿到数据只不过这个数据是 null。2️⃣使用布隆过滤器 3️⃣增加 key 的复杂度,做好数据校验 4️⃣做好热点限流。
布隆过滤器的特征
TCP 和 UDP 讲一下
TCP 和 UDP 最根本的区别是 TCP 是一个安全的通信协议,UDP 是不安全的,比如视频通话他存在丢包的情况,画面会随着网络质量而卡顿,但是他的传输效率非常高,因为他不需要确认消息发送的结果,所有数据通通发出去就好了。TCP 的话他就是会保证数据包一定要发送到目标手上,他有一个三次握手协议,一开始客户端和服务端都是 close 状态,服务端会监听某个端口。当客户端要向服务端发送消息时首先要 先建立连接:客户端会携带一个 SYN 报文发送给客户端。服务端接收到 SYN 后,他会把 SYN 和 ACK 返回给客户端。客户端收到后,就知道服务端知道我的请求了,接着发送一个 应答报文,去发送消息给服务端。