2026.3.26
如果xxx宕机了怎么办(以redis服务宕机为例) 宕机中:这个阶段主要就看兜底策略能帮助服务缓解多大压力了。比如设置多级缓存,在宕机过程中还能顶住一部分流量。比如开启熔断,降低数据库压力,走降级策略。比如设置好互斥锁,当缓存挂了,请求需要获取锁才能访问数据库。 预防:通过一些手段预防宕机。比如建立集群。 tomcat是什么,有什么用 sevlet容器,用于部署基于sevlet的应用程序,如springboot、spring。 它可以将java程序看不懂的http请求封装成对象,并且选择合适的sevlet去处理这个请求 MVC是什么 M是model:处理业务逻辑,跟数据库进行交互 V是view:我们能看到的视图层,负责与用户交互 C是controller:负责接收view的请求,选择合适的model处理
2026.3.25
面向对象的三大思想 封装:将事物的属性和行为封装为实体,对外隐藏实现,只暴露其接口 继承:对事物本质的抽象,实现了代码的复用 多态:一个接口或方法可以有多个实现,提高灵活性 guava cache 过期分为写入后过期和访问后过期 123456789101112131415161718192021LoadingCache<String, String> userCache = CacheBuilder.newBuilder() // 设置并发级别,允许同时写缓存的线程数 .concurrencyLevel(8) // 设置缓存初始容量 .initialCapacity(100) // 最大容量限制 .maximumSize(5000) // 写入 30 分钟后过期 .expireAfterWrite(30, TimeUnit.MINUTES) // 开启统计功能(可以监控命中率等) .recordStats() // 设置移除监听器(当缓存被清理时触发) ...
2026.3.23
点赞系统的实现 技术:redis hash/set 业务:判断文章的点赞set中有无该用户id,没有就是点赞,有就是取消点赞 问题:数据库与redis的一致性(异步写/同步锁)、大key问题(拆分set) 签到系统的实现 技术:redis bitmap 业务:每个用户按月维护的bitmap,获取连续的签到市场需从当前日期开始向前遍历直到第一个0 问题:大量bitmap也占内存(mysql持久化)、跨月统计(遇到月初继续递归上一个月)、时区问题(依赖统一的UTC时间) 使用netty作为底层的通讯架构,在此基础上封装了很多消息类型,用于实现如服务注册、心跳检测、消息订阅等功能 仿照小红书开发的社交购物平台,主要基于redis实现了各种社交功能 平台优化点 限流:原本是滑动窗口算法的非原子性实现,后改为令牌桶+lua脚本的原子性实现。优化考虑点:1.原方案无法保持原子性 2.滑动窗口针对请求次数限流,令牌桶可以比较tokens限流 3.令牌桶支持突发流量,滑动窗口不支持 缓存:原本是guava...
2026.3.21
Problem: 289. 生命游戏 思路 难点在于题目要求根据当前情况直接得出变化后的情况,但程序肯定需要一个个遍历。 考虑四种状态:0-死细胞,1-活细胞,MAX_VALUE-要活的死细胞,MIN_VALUE-要死的活细胞 解题过程 先遍历一个位置的8个方位,判断细胞所处的状态。 再遍历每个位置的状态,转变不稳定状态的细胞。 复杂度 时间复杂度: $ O(n*m) $ 空间复杂度: $O(1)$ 12345678910111213141516171819202122232425262728293031323334353637class Solution { public void gameOfLife(int[][] board) { int[][] dir = new...
2026.3.18
...
模面5
接口测试用例包含的内容/怎么设计接口测试用例 名称、预制条件(前提条件)、请求方法、请求头、请求体、预期结果 设计思路: 针对数据:1.正确值 2.边界值、空值、特殊符号 针对参数:1.全参、必选参数、可选参数 2.多参、少参、无参、错参 性能测试的测试策略 基准测试: 在单用户下运行,确定系统的基本响应时间指标。 负载测试(Load): 逐步增加压力,找到系统满足 SLA(服务等级协议)的最大并发量。 压力测试(Stress): 持续加压直到系统崩溃,观察系统的极限承载能力和失效模式。 稳定性测试(Soak): 在高负载下长时间运行(如 7x24h),检查是否有内存泄漏或资源耗尽。 SQL 慢的优化策略 打开EXPLAIN分析语句执行情况,重点关注type、rows、extra字段,看看有没有用索引 创建联合索引时注意最左匹配原则 调整sql语句结构,利用join替换子查询 如果数据量太大,可以考虑分库分表或创建缓存 接口自动化怎么做? 先讲手动的接口测试,根据测试用例一个个在postman等工具中调试 我们利用代码减少重复的操作就是自动化。 代码的编写主要包括...
模面4
Redis 为什么使用跳表而不是 B+ 树? B+树很耗费空间,而内存的空间是很宝贵的,相比之下跳表这种可控参数更合适 B+树的范围查询,通过跳表也可以实现 B+树在并发编程下的锁粒度更大 B+树比跳表更难维护和利用 Java 的类加载机制 加载 (Loading): 通过全限定名获取二进制字节流,在内存中生成 java.lang.Class 对象。 链接 (Linking): 验证: 确保字节码符合 JVM 规范,没有安全风险。 准备: 为静态变量分配内存并设置初始默认值(如 int 为 0)。注意:此时还没执行赋值动作。 解析: 将符号引用替换为直接引用(内存地址)。 初始化 (Initialization): 执行类构造器 <clinit>() 方法的过程,真正执行静态变量赋值和 static 代码块。 使用 (Using): 程序执行业务逻辑。 卸载 (Unloading):...
模面3
索引的失效情况 sql层面:使用模糊查询、函数、计算、隐式转换、负向查询 系统层面:条件查询大于30%数据量,可能会优化为全表扫描 redis的应用常见 缓存:存ak、存业务数据 限流:滑动窗口(zset)、令牌桶(string) 消息队列(已优化)、分布式锁(Redisson) redis的内存淘汰和过期策略 过期策略:对于设置了过期时间的key进行的过期淘汰策略 惰性删除:key每次被访问都要先查看剩余时间,过期才删除 定时删除:按照频率依次检测剩余key的过期时间,淘汰过期key 内存淘汰:当内存不足时针对剩余key采取的策略 1. 不淘汰任何key,拒绝本次插入 2. 局部淘汰(针对设置了过期时间的key): 1. lru:淘汰使用次数最少的key 2. ttl:淘汰剩余过期时间最短的key 3. random:随机淘汰 3. 全局淘汰(针对所有key): 1. lru:淘汰使用次数最少的key 2. random:随机淘汰 jvm了解哪些参数,怎么设置? 分为标准参数、非标准参数、稳定参数。 一、内存配置 堆内存核心参数(-X...
模面2
接口和抽象类的区别 接口是对行为的抽象,抽象类是对本质的抽象。一个类具有多种功能,可以实现多个方法,但它只能是“它”,只能继承一个类。使用习惯上,我们一般利用类实现代码的复用,利用接口实现代码的规范与解耦。 接口中的default 和 static方法有什么区别 default方法表示这是它的默认实现,如果你不重写这个方法,被调用时就按照默认的走;static表示这个方法归接口所有,你不需要实现。 final关键字的作用 final关键字可以修饰类(但不能修饰抽象类)、方法、变量。 如果修饰类,表示这个类无法继承。如果修饰方法,表示这个方法无法重写。修饰变量,表示这是一个常量。 不能修饰抽象类:抽象类是为了被继承,但是final会阻止他被继承 如何创建一个不可变对象 类声明为 final(不可继承); 所有成员变量声明为 private final; 不提供修改变量的 setter 方法; 通过构造器初始化时,如果是引用类型,要进行深拷贝(Deep...
模面
AQS队列 state关键字是类的volatile全局变量,0为无锁,1为占有,>1为重入次数。 “非公平锁”的实现并不依赖唤醒所有节点,永远只唤醒下一个节点。它的原理是新线程加入时不需要判断AQS队列情况,可以直接参与锁的竞争。 MySQL的索引 Hash表与B+树对比:Hash表的单点查询效率更高,但是面对频繁的范围查找时B+树的性能更突出,因为B+树天生支持范围查找,而Hash却只能全表扫描。 看门狗 锁未指定过期时间时(但是Rediison有一个默认过期时间),Redisson在后台开启一个定时任务,每隔一段时间向Redis发送一个Lua脚本为锁续期。 当线程宕机时这个定时任务不复存在,锁就会超时过期。





