Redis面试题笔记

1. Redis主从复制的原理 【主从复制的原理】 同步:从节点向主节点发送psync命令进行同步,从节点保存主节点返回的 runid 和 offset 全量复制:如果是第一次连接或者连接失败且repl_backlog_buffer 缓存区不包含slave_repl_offset, 则生成主节点的数据快照(RDB文件)发给从节点 增量复制:全量复制完毕后,主从节点之间会保持长连接。如果连接没有断开或者slave_repl_offset仍然在repl_backlog_buffer中,则将后续的写操作传递给从节点,让数据保持一致。 【全量复制细节】 全量复制的过程是基于TCP长连接的,主要流程如下 从节点发送psync ? -1表示需要建立连接进行同步,主节点返回主节点ID runid 和 复制进度offset (第一次同步用 -1 表示)。从节点接受之后,保存主节点的信息。 主节点执行bgsave命令生成数据快照RDB文件,然后将RDB文件发送给从节点。从节点接受文件后,清除现有的所有数据,然后加载RDB文件 如果在制作数据快照RDB文件的过程当中,主节点接收到了新的写操作,主节点会将其记录在repl buffer 里面。然后将repl buffer当中的写操作发给从节点,让其数据保持一致。 【增量复制细节】 如果主从节点意外断开连接,为了保持数据的一致性,必须重新同步数据。如果使用全量复制来保持一致性的话,开销太大,所以采用增量复制。 增量复制的具体流程如下: 连接恢复后,从节点会发送psync {runid} {offset}, 其中主节点ID runid 和 复制进度offset用于标识是哪一个服务器主机和复制进度。 主节点收到psync 命令之后,会用conitnue响应告知从节点,采用增量复制同步数据 最后,主节点根据offset查找对应的进度,将短线期间未同步的写命令,发送给从节点。同时,主节点将所有的写命令写入repl_backlog_buffer, 用于后续判断是采用增量复制还是全量复制。 【注意】从节点 psync 携带的 offset 为 slave_repl_offset。如果 repl_backlog_buffer包含slave_repl_offset 对应的部分,则采用增量复制,否则采用全量复制。repl_backlog_buffer的默认缓冲区大小为1M 【为什么要主从复制】 备份数据:主从复制实现了数据的热备份,是持久化之外的数据冗余方式 故障恢复:当主节点宕机之后,可以采用从节点提供服务。 负载均衡: 主从复制实现了读写分离,只有主节点支持读写操作,从节点只有都操作。在读多写少的场景下,可以提高Redis服务器的并发量。 2. Redis集群的实现原理是什么? 【Redis集群基本知识】 定义: Redis集群由多个实例组成,每个实例存储部分数据 (每个实例之间的数据不重复) 。 【注】集群和主从节点不是一个东西,集群的某一个实例当中可能包含一个主节点 + 多个从节点 为什么用 问题 解决方案 容量不足 数据分片,将数据分散不存到不同的主节点 高并发写入 数据分片,将写入请求分摊到多个主节点 主机宕机问题 自动切换主从节点,避免影响服务, 不需要手动修改客户端配置 节点通信协议:Redis集群采用Gossip协议, 支持分布式信息传播、延迟低、效率高。采用去中心化思想,任意实例(主节点)都可以作为请求入口,节点间相互通信。 分片原理: 采用哈希槽(Hash Slot)机制来分配数据,整个空间可以划分为16384 (16 * 1024)个槽。 每个Redis负责一定范围的哈希槽,数据的key经过哈希函数计算之后对16384取余可定位到对应的节点。 ...

February 20, 2025 · 2 min · SwimmingLiu

Java集合面试题笔记

1. 说说 Java 中 HashMap 的原理? 【HashMap定义】 结构:数组 + 链表 + 红黑树 (JDK 1.8 之后) 默认值:初始容量为16 (数组长度),负载因子为 0.75。当存储的元素为 16 * 0.75 = 12个时,会触发Resize() 扩容操作,容量 x 2 并重新分配位置。但是扩容是有一定开销的,频繁扩容会影响性能。另外,TREEIFY_THRESHOLD 转换为红黑树的默认链表长度阈值为 8, UNTREEIFY_THRESHOLD 从红黑树转换为链表的阈值为 6。 两个阈值采用不同值的原因是防止刚转换为红黑树,又变成链表,反复横跳,消耗资源。 数组下标位置计算方法:首先使用key的hashCode()方法计算下标位置,然后通过 indexFor() (JDK 1.7 以前) 计算下标值。 JDK 1.7后,为了提高计算效率采用 (len - 1) & hash 来确定下标值。 【注】数组的长度len 是2的幂次方时,(len - 1) & hash 等价于 hash % len。 这也是为什么数组长度必须是2的幂次方。 【HashMap线程不安全】 为了保证HashMap的读写效率高,它的操作是非同步的,也就是说读写操作没有锁保护。所以多线程场景下是线程不安全的。 【HashMap不同版本区别】 JDK 1.7: 数组 + 链表,链表部分采用头插法,多线程会导致出现环形链表。扩容会计算每个元素hash值,并分配到新的位置,开销大。 JDK 1.8:数组 + 链表 + 红黑树,采用高低位置来分配位置,即判断(e.hash & oldCap) == 0, 减少了计算hash的次数 【HashMap的PUT方法】 ...

February 20, 2025 · 4 min · SwimmingLiu

Java基础题面试笔记

1. 序列化和反序列化 1.序列化和反序列化:把对象转换为字节流,用于存储和传输;读取字节流数据,重新创建对象。 2.序列化不包括静态对象:序列化和反序列化的本质是调用对象的writeObject和readObject方法,来实现将对象写入输出流和读取输入流。但是,静态变量不属于对象,所以调用这两个方法就没法儿让静态变量参与。 2. 什么是不可变类? 1.不可变类:初始化之后,就不能修改的类。 2.修饰方法:final 和 private 修饰所有类和变量 3.不可修改:不暴露set方法,只能通过重新创建对象替代修改功能(String的replace方法) 4.优缺点: 优点:线程安全,缓存友好 缺点:频繁拼接和修改会浪费资源 3. Exception和Error区别? 1.Exception和Error定义区别:Exception是可处理程序异常,Error是系统级不可回复错误 2.try-catch建议: 1.范围能小则小 2.Exception最好要写清楚具体是哪一个Exception(IOException) 3.null值等能用if判断的,不要用try-catch,因为异常比条件语句低效 4.finally不要直接return和处理返回值 4. Java 中的 hashCode 和 equals 方法之间有什么关系? 1、equals() 和 hashCode() 的关系 如果两个对象euqals() 为 true, 则其 hashCode()一定相同 如果两个对象hashCode() 相同,其equals()结果不一定为true 2、为什么重写equals()之后,一定要重写hashCode() 当重写equals() 之后,通常是重新定义了两个对象相等的逻辑。如果不重写hashCode()方法, 则在散列集合(HashMap 和 HashSet)中,可能无法正确存储和检索,因为两个相同的对象可能有不同的hash值。 例如,下方Person类重写了equals() 方法,但是没有重新hashCode() public class Person { private String name; private int age; @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person person = (Person) obj; return age == person.age && Objects.equals(name, person.name); } } 创建相同的对象,并添加到HashSet中 ...

February 19, 2025 · 1 min · SwimmingLiu

MySQL面试题笔记

1.MySQL 中的数据排序是怎么实现的? 1.排序方法:索引排序和文件排序 (filesort) 2.索引排序:如果order by xxx的字段为索引字段,则利用索引进行排序。效率最高,索引默认有序。 3.文件排序 (filesort):内存排序(单路排序和双路排序)和磁盘排序,具体取决于排序数据的大小。其中,内存排序使用单路排序或双路排序,取决于max_length_for_sort_data(默认为4096个字节) 4.双路排序:取row_id(如果有主键,则为主键)和select a,b,c order by xxx的xxx字段放入sort_buffer(排序缓存)中,将排序后的row_id回表查询a,b,c 5.单路排序: 直接把要查的所有字段放入sort_buffer里,排序后直接得到结果集合 6.磁盘排序(归并排序):将数据分为多份文件,单独对文件进行排序,然后合并成一个有序的大文件 2. MySQL 的 Change Buffer 是什么?它有什么作用? 1.ChangeBuffer定义:Change Buffer是InnoDB缓冲当中的一块缓存区,用于暂存二级索引的修改,避免二级索引页修改产生的随机IO 2.ChangeBuffer注意事项:只能用于二级索引,不能用于其他任何索引,包括主键索引和唯一索引都不行。 3.如果ChangeBuffer挂了,更改操作未执行,是否会出现脏数据? 首先,ChangeBuffer也会保存在磁盘空间里面,redo log会记录Change Buffer当中的修改操作,确保数据一致性。 知识拓展1:一级索引和二级索引区别 一级索引(聚簇索引):数据表的主键索引,数据和索引存储在同一B+树的叶子节点中。每个表只能有一个一级索引。 二级索引(非聚簇索引):除主键外的其他索引,叶子节点存储索引列的值和对应的主键值。通过二级索引查询时,需要先通过二级索引获取主键值,再通过主键值查询数据,这个过程称为“回表”。 知识拓展2: MySQL中有哪些常见索引?都有什么区别? 在MySQL中,索引是提高查询效率的关键工具。常见的索引类型包括主键索引、唯一索引、普通索引、全文索引和空间索引。 1. 主键索引(Primary Key Index) 定义:主键索引是一种特殊的唯一索引,用于唯一标识表中的每一行数据。每个表只能有一个主键索引,且主键列的值不能为空。 特点:主键索引的叶子节点存储完整的数据行,因此查询效率高。在InnoDB存储引擎中,主键索引是聚簇索引,数据存储与索引结构合并。 2. 唯一索引(Unique Index) 定义:唯一索引确保索引列的每个值都是唯一的,但允许有空值。与主键索引类似,不同之处在于唯一索引允许列值为NULL。 特点:唯一索引的叶子节点存储索引列的值和对应的主键值。在InnoDB中,唯一索引是非聚簇索引,数据存储与索引结构分开。 3. 普通索引(Index) 定义:普通索引是最基本的索引类型,没有任何限制。索引列的值可以重复,也可以为NULL。 特点:普通索引的叶子节点存储索引列的值和对应的主键值。在InnoDB中,普通索引是非聚簇索引,数据存储与索引结构分开。 4. 全文索引(Fulltext Index) 定义:全文索引用于对文本数据进行全文搜索,适用于MyISAM存储引擎。它允许对文本字段进行复杂的搜索,如查找包含特定单词的记录。 特点:全文索引的叶子节点存储文档的词项信息。在MyISAM中,全文索引是非聚簇索引,数据存储与索引结构分开。 5. 空间索引(Spatial Index) 定义:空间索引用于对地理空间数据进行索引,支持空间数据类型的快速查询。它适用于存储地理位置、地图等空间数据的表。 特点:空间索引的叶子节点存储空间数据的索引信息。在MyISAM中,空间索引是非聚簇索引,数据存储与索引结构分开。 总结: 主键索引:用于唯一标识每一行数据,值不能为空。 唯一索引:确保索引列的值唯一,但允许有空值。 普通索引:最基本的索引类型,允许重复和空值。 全文索引:用于对文本数据进行全文搜索,适用于MyISAM存储引擎。 空间索引:用于对地理空间数据进行索引,支持空间数据类型的快速查询。 3. 详细描述一条 SQL 语句在 MySQL 中的执行过程。 1.连接器判断用户是否成功建立连接,数据库连接的权限校验 2.分析器分析SQL语法和词法是否有误 3.优化器生成SQL的执行计划,确定使用的索引和调整where的执行顺序(包括连表顺序) 4.执行器判断当前用户是否有权限查询该表,然后执行该SQL语句 ...

February 19, 2025 · 3 min · SwimmingLiu

Java面试题-随手记

== 和 equals 区别 == 基本类型(int, long, float, char, boolean) 值比较, 引用类型(String,List) 进行地址比较 equals 默认就是 == ,但是部分引用类型(String,List)重写了该方法,进行值比较 get 和 post 区别 特性 GET POST 目的 获取资源,查询数据 提交数据,创建或更新资源 请求数据方式 参数通过 URL 查询字符串传递 数据通过请求体传递 数据暴露 数据暴露在 URL 中,较不安全 数据存储在请求体中,相对安全 数据大小限制 URL 长度有限制(约 2048 个字符) 没有数据大小限制 适用场景 获取数据,查询,展示资源 提交表单,上传文件,修改资源,发送敏感数据等 SpringMVC中@ReponseBody、@PathVariable、@RequestParameters在什么情况下使用? @ReponseBody 用于接受请求体数据,一般用于POST请求 @PathVariable 用于接受路径参数,一般用户接受 id @RequestParameters 用于接受请求参数,一般用于GET请求 JVM堆的结构、GC介绍和作用 JVM堆结构的参考文章 、 GC垃圾回收过程 区域 主要用途 特点 新生代(Young Generation) 存储新创建的对象,快速垃圾回收 包含 Eden 区和两个 Survivor 区,采用复制算法进行回收 老年代(Old Generation) 存储长期存活的对象 回收频率较低,垃圾回收较耗时 永久代(Permanent Generation) (jdk 1.7) 存储类的元数据、方法字节码等 在 jdk 1.8 被 Metaspace 替代 元空间(jdk 1.8) 存储类的元数据 不再属于堆,使用本地内存,大小由系统限制 GC 是垃圾回收器, 作用是自动内存管理和避免内存泄漏 ...

December 27, 2024 · 3 min · SwimmingLiu