MySQL 中 INNER JOIN、LEFT JOIN 和 RIGHT JOIN 的区别是什么?回答重点INNER JOIN:
只返回两个表中匹配的行。如果没有匹配,则该行不会出现在结果集中。
适用于只关心交集数据的场景。
LEFT JOIN(或 LEFT OUTER JOIN):
返回左表中的所有行,即使右表中没有匹配的行。如果右表没有匹配,则结果中的右侧列会显示为NULL。
适用...
MySQL 三层 B+ 树能存多少数据?回答重点在 MySQL 的 InnoDB 存储引擎中,B+ 树默认数据页大小为 16KB。
参数:
每个节点页大小为 16KB(即 16384 字节)。
假设每个数据记录的主键和数据大小为 1KB(一般会比这个小,但这里取整方便计算)。
每个内部节点(非叶子节点)存储的是指向子节点的指针和索引键。
三层 B+ 树的存储计算:
叶子节点:第三层为...
MySQL 事务的二阶段提交是什么?回答重点MySQL 事务的二阶段提交是指在 MySQL 中,为了确保redo log(重做日志)和 binlog(二进制日志)之间的一致性,使用的一种机制。MySQL 通过二阶段提交来保证在crash recovery(崩溃恢复)时,不会出现数据丢失或数据不一致的情况。
二阶段提交的两个阶段:
准备阶段(Prepare Phase):在事务提交时,MyS...
MySQL 在设计表(建表)时需要注意什么?回答重点设计表的时候,在满足业务需求的情况下,需要额外考虑表结构的高效性、扩展性以及维护性。
1)选择合适的数据类型:为字段选择合适的数据类型可以有效减少存储空间,并提高查询效率。例如:
使用 INT 而不是 BIGINT,前提是如果数据不会超出 INT 范围。
使用 VARCHAR 而不是 TEXT,如果字段长度比较短且可变。
使用 DATE、...
什么是 Netty,它在网络编程中解决了什么问题?回答重点Netty 是高性能 Java 网络通信的底层框架,它使用异步、事件驱动等架构,解决了传统 Java 网络编程中的一些复杂问题:
传统BIO阻塞瓶颈:通过NIO多路复用实现单线程万级连接,避免线程爆炸
原生NIO开发复杂度:封装Selector/Channel/Buffer,提供Pipeline责任链式API
网...
说一下 Netty 的应用场景?回答重点Netty 的应用场景主要有以下几个:
许多框架底层通信的实现,比如说 RocketMQ、Dubbo、Elasticsearch、Cassandra 等,底层都使用到了 Netty。
游戏行业,在游戏服务器开发中,Netty 用于处理大量并发的游戏客户端连接,提供低延迟的网络通信能力
实现一个通讯系统,比如聊天室、IM 等,处理高并发的实时消息传输。...
介绍一下 Reactor 线程模型?回答重点Reactor 是服务端在网络编程时的一个编程模式,主要由一个基于 Selector (底层是 select/poll/epoll)的死循环线程,也称为 Reactor 线程。
基于事件驱动,将 I/O 操作抽象成不同的事件,每个事件都配置对应的回调函数,由 Selector 监听连接上事件的发生,再进行分发调用相应的...
简单说说 Netty 的零拷贝机制?回答重点
前置知识:零拷贝的基本理念
避免在用户态和内核态之间拷贝数据,从而降低 CPU 占用和内存带宽的消耗。
除了系统层面的零拷贝,Netty 还强调在 buffer 之间避免不必要的数据拷贝。
Netty 中的零拷贝包括以下四个方面:
零拷贝机制
描述
FileRegion 接口
利用操作系统的 sendfile 系统调用,将文...
为什么不选择使用原生的 NIO 而选择使用 Netty 呢?回答重点因为原生的 NIO 存在一些问题:
1)原生 NIO 接口较多,能支持更精细化的调用,但是对于通常的使用而言过于复杂。就好下面这张图,对于已经深耕的专业人员来说,可能极好,但对于大部分人员使用来说太复杂了。
所以如果用原生 NIO 开发的话,需要进行二次封装,开发效率不高,且原生 NIO 对开发者要求较高,不好开发。
2...
简单说说 Netty 的线程模型,并且其是如何完成工作的?回答重点Netty 主要采用了 Reactor 模型,且通过细化线程池管理来处理不同的 I/O 任务。
Netty 的线程模型可以分为三个部分:
Boss 线程组:负责接收客户端的连接请求。
Worker 线程组:负责处理 I/O 读写操作。
业务线程组(可选):负责处理具体的业务逻辑。
具体工作机制1)Bos...
Netty 性能为什么这么高?回答重点Netty 性能高的主要原因如下:
非阻塞 I/O 模型:Netty 底层使用了 NIO 非阻塞模型,并且利用I/O 多路复用,通过 Selector 监听多个 Channel 的 IO 事件,使得系统资源得到了充分利用,减少了线程开销。
高效的内存操作与内存池设计:ByteBuf 提供了丰富的功能,如动态扩展、复合缓冲区等,能高效...
说一下 TCP 半包和粘包问题?回答重点因为TCP 协议是面向字节流的,数据在传输过程中没有明确的边界,所以会发生粘包和半包问题。
1)粘包问题:
粘包指的是多个应用层的数据包在传输过程中被合并成一个 TCP 数据包,导致接收方无法区分各个独立的数据包。
2)半包问题:
半包指的是一个应用层的数据包在传输过程中被拆分成多个 TCP 数据包,接收方需要多次读取才能获取完整的数据。
常见解决粘包...
Netty 是如何解决粘包和拆包问题的?回答重点Netty 提供了丰富的自带解码器为我们解决粘包和拆包的问题,也可以让我们自定义序列化解码器。
Netty 自带的解码器
DelimiterBasedFrameDecoder:分隔符解码器,使用特定分隔符来分割消息。
FixedLengthFrameDecoder:固定长度的解码器,可以按照指定长度对消息进行拆包,如果长度不够的话,可以使用空格...
Netty 采用了哪些设计模式?回答重点Netty 作为许多中间件的底层网络通讯框架,内部设计使用了很多的设计模式:
1)策略模式
例如,Netty 提供了多种 EventLoopGroup 实现(如 NioEventLoopGroup、EpollEventLoopGroup),可以根据不同的操作系统和需求选择不同的实现。
2)单例模式
我们在面试鸭设计模式题库中提到池化设计经常就需要用到单...
Netty 如何解决 JDK NIO 中的空轮询 Bug?回答重点Netty 实际上并没有解决 JDK 原生 NIO 中空轮询 bug,而是通过其他途径绕开了这个错误。
具体操作如下:
1)统计空轮询次数:Netty 通过 selectCnt 计数器来统计连续空轮询的次数。每次执行 Selector.select() 方法后,如果发现没有 I/O 事件,selectCnt 就会递增...
在 Netty 中,什么是 Channel ? 什么是 ChannelHandlerContext?回答重点在 Netty 中,Channel 表示一个网络连接,抽象了底层的网络操作,提供绑定、连接、读写和关闭等操作,是网络 I/O 操作的核心抽象。
ChannelHandlerContext 是 Netty 中用来在 ChannelPipeline 中传递数据和处理事件的上下文对...
Redis Zset 的实现原理是什么?回答重点Redis 中的 ZSet(有序集合,Sorted Set) 是一种由 跳表(Skip List) 和 哈希表(Hash Table) 组成的数据结构。ZSet 结合了集合(Set)的特性和排序功能,能够存储具有唯一性的成员,并根据成员的分数(score)进行排序。
ZSet 的实现由两个核心数据结构组成:
跳表(Skip List):用于存...
Redisson 看门狗(watch dog)机制了解吗?回答重点Redisson 的看门狗(watchdog)主要用来避免 Redis 中的锁在超时后业务逻辑还未执行完毕,锁却被自动释放的情况。它通过定期刷新锁的过期时间来实现自动续期。
主要原理:
定时刷新:如果当前分布式锁未设置过期时间,Redisson 基于 Netty 时间轮启动一个定时任务,定期向 Redis 发送命令更新锁的过...
Redis 源码中有哪些巧妙的设计,举几个典型的例子?回答重点Redis 作为一款高性能的内存数据库,其源码中包含了许多巧妙的设计。这些设计不仅体现了高效的数据处理和管理能力,也为后续的系统扩展和性能优化奠定了基础。
巧妙的设计主要包括:线程模型、数据结构、共享对象池、过期设计、数据持久化设计等。
线程模型Redis 使用单线程模型来处理所有的客户端请求。
虽然看似单线程简单,但这种设计减少...
说说 Redisson 分布式锁的原理?回答重点Redisson 是基于 Redis 实现的分布式锁,实际上是使用 Redis 的原子操作来确保多线程、多进程或多节点系统中,只有一个线程能获得锁,避免并发操作导致的数据不一致问题。
1)锁的获取:
Redisson 使用 Lua 脚本,利用 exists + hexists + hincrby 命令来保证只有一个线程能成功设置键(表示获得锁...
Redis 的订阅发布功能是什么?你了解吗?回答重点Redis 的订阅发布功能(Publish/Subscribe,简称 Pub/Sub),是一种消息通信机制,用于在不同客户端之间实现消息的实时传递和广播。使用 Pub/Sub 模型,客户端可以订阅一个或多个频道,当有其他客户端向这些频道发布消息时,所有订阅了该频道的客户端都会立即收到消息。
主要功能包括:
发...
分布式锁在未完成逻辑前过期怎么办?回答重点若锁在未完成逻辑前就过期,此时可能会产生数据不一致的问题。因为锁过期了,此时如果再出现一个客户端争抢锁,即可拿到锁然后同时进行业务操作,这等于锁失效了。
此时可以在逻辑执行过程中定期续期锁,确保锁在处理过程中不会过期。
扩展知识看门狗机制业界出了一个看门狗机制来防止这种情况的产生。
理论很简单,在抢到锁之后,后台会有一个任务,定时向 redis...
Redis 的 Red Lock 是什么?你了解吗?回答重点Red Lock,又称为红锁,是一种分布式锁的实现方案,旨在解决在分布式环境中使用 Redis 实现分布式锁时的安全性问题。
一般情况下,我们在生产环境会使用主从+哨兵方式来部署 Redis。
如果我们正在使用 redis 分布式锁,此时发生了主从切换,但从节点上不一定已经同步了主节点的锁信息。
所以新的主节点上可能没有锁的信息。此...
如何使用 Redis 统计大量用户唯一访问量(UV)?回答重点Redis 中 HyperLogLog 结构,可以快速实现网页 UV 、PV 等统计场景。它是一种基数估算算法的概率性数据结构,可以用极少的内存统计海量用户唯一访问量的近似值。
Set 也可以实现,用于精确统计唯一用户访问量,但是但当用户数非常大时,内存开销较高。
扩展知识HyperLogLog 使用介绍HyperLogLog...
Redis String 类型的底层实现是什么?(SDS)回答重点Redis 中的 String 类型底层实现主要基于 SDS(Simple Dynamic String 简单动态字符串)结构,并结合 int、embstr、raw 等不同的编码方式进行优化存储。
扩展知识C 语言字符串的缺陷Redis 为什么没有使用 C 标准库提供的字符串,而是实现了一种动态字符串?因为 C 语言的字符串本...
Redis 中的 Geo 数据结构是什么?回答重点Redis 中的 Geo(Geolocation 的简写形式,代表地理坐标) 数据结构主要用于地理位置信息的存储。通过这个结构,可以方便地进行地理位置的存储、检索、以及计算地理距离等操作。Geo 数据结构底层使用了 Sorted Set,并且结合了 Geohash 编码算法来对地理位置进行处理。
它是 Redis 2.2 版本后新增的数据类...
Redis 字符串类型的最大值大小是多少?回答重点Redis 字符串能存储的最大容量是 512 MB 的数据,可以查看官方文档:
无论是网络传输、内存分配还是字符串操作,大字符串都会增加 Redis 服务器的负载。
且过大的字符串在 GET、SET、APPEND、STRLEN 等操作都会导致性能瓶颈。
所以官方给字符串的大小做了限制,防止单个键值对占用过多的内存,影响整体性能和稳定性。
...
Redis 中 EMBSTR 对象的阈值设置为何为 44?其调整历史是什么?为什么 EMBSTR 的阈值大小是 44 个字节?这个问题有几个关键点:
1)Redis 使用的是 jemalloc 作为内存分配器。
2)jemalloc 是以 64 字节作为内存单位进行内存分配的,如果超过了 64 字节,即超过了一个内存单元,使用的就是 raw 编码,反之使用的就是 EMBSTR 编码。
3)核...
Redis 中原生批处理命令(MSET、MGET)与 Pipeline 的区别是什么?回答重点原生批处理命令(MSET、MGET) 和 Pipeline 都可以用于一次性处理多个命令,但它们在实现方式和应用场景上有所不同:
1)MSET / MGET(原生批处理命令):
MSET 和 MGET 是 Redis 提供的原生批处理命令,用于批量设置和获取多个键值。
它们是 单个命令,...
为什么 Redis Zset 用跳表实现而不是红黑树?B+树?回答重点为什么不用红黑树?1)相比红黑树而言实现简单
跳表基于多层链表实现,通过概率算法动态生成索引层级,没有左旋右旋等操作,逻辑理解上更为简单。而红黑树需要复杂的平衡操作(旋转)来维护结构,代码实现复杂度较高,理解门槛更高。
2)范围查询更高效
范围查询跳表可以通过 O(logn) 的时间复杂度定位起点,然后在原始的链表中往后遍...