前言
再次重申,本项目非原创,视频来源于:
Springboot项目实战 easypan 仿百度网盘 计算机毕业设计 简历项目 项目经验(后端)
再次重申:本人不分享项目源码,支持项目付费!!
一、用户注册与安全
-
如何保证注册接口的幂等性?
考察点:幂等性设计、防重复提交。
参考答案:- 使用唯一键(如邮箱)配合数据库唯一索引,防止重复注册。
- 前端限制重复点击,后端通过Redis记录验证码的请求状态(如
email:code:status
),验证码一次性有效,提交后立即失效。 - 对注册请求生成唯一请求ID(如UUID),利用Redis的
SETNX
实现请求去重。
-
为什么选择QQ邮箱发送验证码?如何防止验证码被滥用?
考察点:安全性设计、防刷策略。
参考答案:- QQ邮箱普及率高,用户接受度广。
- 限制同一IP/邮箱的发送频率(如1分钟1次),使用Redis记录发送时间戳,设置TTL过期时间。
- 验证码添加有效期(如5分钟),并校验请求来源IP与发送IP的一致性。
二、AOP与登录校验
-
AOP切面如何实现登录校验?如何避免性能问题?
考察点:AOP实现细节、性能优化。
参考答案:- 定义注解(如
@LoginRequired
),在切面中拦截带注解的方法,从请求头解析Token并校验有效性。 - 性能优化:将Token解析后的用户信息缓存到ThreadLocal,避免多次解析;对频繁访问的接口(如文件列表)使用本地缓存(如Caffeine)减少数据库查询。
- 定义注解(如
-
双Token机制的具体实现?如何保证无感刷新?
考察点:Token刷新逻辑、安全性。
参考答案:- 双Token:
access_token
(短有效期,如2小时)和refresh_token
(长有效期,如7天)。 - 无感刷新:前端在
access_token
过期前,用refresh_token
调用刷新接口获取新Token;若refresh_token
过期则强制重新登录。 - 安全性:
refresh_token
仅用于刷新接口,存储时加密,服务端绑定设备/IP限制使用。
- 双Token:
三、文件上传与下载
-
分片上传和断点续传的实现细节?
考察点:分片策略、断点恢复逻辑。
参考答案:- 分片上传:前端将文件按固定大小(如10MB)分片,每片上传时携带分片序号、文件哈希、总分片数。
- 断点续传:服务端记录已上传分片信息(如Redis的Hash结构
file:${hash}:chunks
),下次上传时返回已上传分片列表,前端跳过已传分片。 - 合并文件:所有分片上传完成后,按序号排序合并成完整文件,校验整体哈希。
-
如何实现秒传功能?哈希冲突如何处理?
考察点:文件去重、哈希算法选择。
参考答案:- 秒传:计算文件内容的哈希值(如SHA-256),查询数据库是否存在相同哈希的文件,若存在则直接关联用户文件表,无需重复上传。
- 哈希冲突:使用更安全的算法(如SHA-256),理论碰撞概率极低;若业务要求绝对安全,可结合文件大小二次校验。
-
限速下载的代码实现?如何避免恶意下载?
考察点:流控设计、资源保护。
参考答案:- 限速:通过
InputStream
读取文件时,控制每次读取的字节数,结合Thread.sleep
模拟带宽限制(如100KB/s)。 - 防恶意下载:限制单个用户/IP的并发下载数,结合令牌桶算法控制全局下载速率。
- 限速:通过
四、数据库与性能优化
-
联合索引优化查询的具体案例?如何避免索引失效?
考察点:索引设计、SQL优化。
参考答案:- 案例:用户文件列表查询
WHERE user_id=? AND parent_id=?
,建立(user_id, parent_id)
联合索引,避免回表查询。 - 索引失效:避免在索引列上使用函数或运算(如
WHERE YEAR(create_time)=2023
),遵循最左前缀原则。
- 案例:用户文件列表查询
-
为什么用HashMap替代文件树递归查询?有什么缺点?
考察点:数据结构选择、缓存设计。
参考答案:- 替代原因:递归查询文件树时,多次访问数据库导致性能瓶颈;HashMap将父子关系缓存在内存(如
Map<parentId, List<File>>
),一次查询加载所有节点。 - 缺点:内存占用高,不适合超大规模文件系统;数据更新时需同步更新缓存,可能引入一致性风险。
- 替代原因:递归查询文件树时,多次访问数据库导致性能瓶颈;HashMap将父子关系缓存在内存(如
五、定时任务与回收站
- 如何动态管理回收站的定时任务?任务过期后如何清理文件?
考察点:定时任务框架、资源清理逻辑。
参考答案:- 动态管理:使用
ThreadPoolTaskScheduler
,根据用户操作(如删除文件)动态添加/取消任务,任务信息存储在数据库或Redis。 - 清理逻辑:任务触发时,检查文件删除时间是否超过保留期(如30天),物理删除文件并更新数据库状态。
- 动态管理:使用
六、文件预览与分享
-
不同格式文件的在线预览技术方案?大文件预览如何优化?
考察点:文件处理、第三方工具集成。
参考答案:- 技术方案:
- 图片/视频:直接通过HTML5的
<img>
、<video>
标签渲染。 - Office/PDF:使用
LibreOffice
转换文件为PDF,再通过pdf.js
预览。 - 文本:直接读取内容,限制大文件预览行数。
- 图片/视频:直接通过HTML5的
- 大文件优化:分页加载文本内容;视频采用流媒体技术(如HLS)边下边播。
- 技术方案:
-
文件分享的安全设计?如何防止分享链接被爆破?
考察点:安全策略、防攻击设计。
参考答案:- 安全设计:分享链接生成随机Token(如UUID),绑定有效期和访问次数限制。
- 防爆破:Token长度足够(32位以上);对频繁访问的IP进行限流;敏感文件(如私密分享)要求输入提取码。
七、综合设计
-
如果用户同时上传10个1GB文件,系统如何保证稳定性?
考察点:高并发处理、资源隔离。
参考答案:- 资源隔离:限制单用户并发上传数,通过队列(如RabbitMQ)排队处理请求。
- 流量控制:服务端分片上传接口设置限流(如令牌桶算法),避免带宽占满。
- 异步处理:上传完成后,文件合并和元数据更新通过消息队列异步执行。
-
项目中最有挑战的功能是哪一个?如何解决的?
考察点:问题分析能力、复盘总结。
参考答案:- 挑战点:文件预览的格式兼容性问题(如Office版本差异导致转换失败)。
- 解决方案:统一转换为PDF格式,使用开源的
LibreOffice
无头模式进行转换,并对转换失败的文件提供错误提示和日志监控。
八、扩展思考
- 如果用户量增长10倍,系统可能遇到哪些瓶颈?如何优化?
考察点:分布式架构设计、扩展性思维。
参考答案:- 瓶颈:数据库读写压力、文件存储带宽、单机资源限制。
- 优化:
- 数据库分库分表(如按用户ID分片)。
- 文件存储迁移到对象存储(如OSS),支持CDN加速。
- 服务无状态化,通过Kubernetes横向扩容。
总结
面试官会重点考察:
- 技术深度:分片上传、Token刷新、索引优化等实现细节。
- 设计权衡:HashMap替代递归的优缺点、限速方案的合理性。
- 问题解决:如何应对高并发、安全性设计、性能优化思路。
- 扩展能力:从单机到分布式的架构演进思考。
建议候选人提前准备技术原理、数据指标(如优化后接口耗时降低XX%)和难点复盘。
一、项目背景与架构设计
问题1:原单体系统订单错误率高达18%,你认为主要原因是什么?如何通过架构升级解决的?
- 考察点:系统瓶颈分析与架构设计思路。
- 参考答案:
主要原因是单体架构下数据库锁竞争激烈(如库存扣减的行锁),导致事务冲突和超时。通过以下优化:- 业务解耦:将秒杀、订单、支付拆分为独立服务,减少数据库竞争。
- 异步削峰:使用RabbitMQ缓冲瞬时请求,避免直接冲击数据库。
- 缓存预减:通过Redis+Lua原子操作预扣库存,减少数据库访问。
二、核心技术点深入
问题2:如何用Redis+Lua实现秒杀场景?Lua脚本的作用是什么?
- 考察点:Redis原子性和Lua脚本的应用。
- 参考答案:
- 流程:用户请求→Redis预减库存(Lua保证原子性)→成功则生成订单消息→MQ异步落库。
- Lua作用:
- 原子执行:避免多个命令间的并发问题(如库存扣减和资格校验)。
- 减少网络开销:将多个操作合并为一个脚本,减少Redis通信次数。
lua
local stock = tonumber(redis.call('get', KEYS[1])) if stock > 0 then redis.call('decr', KEYS[1]) return 1 -- 成功 end return 0 -- 失败
问题3:如何解决数据库与缓存一致性问题?是否考虑过延迟问题?
- 考察点:缓存一致性方案设计。
- 参考答案:
- 方案:采用“延迟双删+消息队列重试”。
- 更新数据库后删除缓存。
- 通过MQ发送延迟消息,1秒后再次删除缓存。
- 考虑延迟:业务上允许短时间不一致(如商品详情页),但关键数据(库存)通过Redis原子操作保证强一致。
- 方案:采用“延迟双删+消息队列重试”。
三、高并发与分布式问题
问题4:如何解决集群模式下的Session共享问题?
- 考察点:分布式Session方案。
- 参考答案:
- 方案:使用Redis集中存储Session,替代Tomcat Session。
- 实现:
- 用户登录后生成Token,存储用户数据到Redis(Key为Token,Value为序列化用户信息)。
- 每次请求通过Token从Redis获取用户状态。
- 优点:无状态、支持水平扩展,避免集群Session复制开销。
问题5:如何保证“一人一单”的线程安全?
- 考察点:分布式锁与幂等性设计。
- 参考答案:
- 分布式锁:使用Redis的
SETNX
命令(或RedLock)锁定“用户ID+活动ID”,防止重复下单。 - 幂等性:
- 订单表唯一索引(用户ID+活动ID)。
- MQ消费者端去重表校验。
- 分布式锁:使用Redis的
四、缓存与性能优化
问题6:缓存穿透、雪崩、击穿分别如何解决的?
- 考察点:缓存异常场景处理。
- 参考答案:
- 穿透:布隆过滤器(Bloom Filter)拦截无效请求,缓存空值(短TTL)。
- 雪崩:随机过期时间(基础TTL+随机偏移)。
- 击穿:热点数据永不过期,后台异步更新;或互斥锁重建缓存。
问题7:响应时间从27ms降到8ms,具体缓存了哪些数据?如何保证缓存有效性?
- 考察点:缓存策略与淘汰机制。
- 参考答案:
- 缓存数据:店铺信息、优惠券详情、用户基础信息(如头像、昵称)。
- 有效性保证:
- 更新数据库后通过MQ通知缓存删除。
- 设置合理TTL(如店铺信息30分钟)。
- 通过Canel监听数据库Binlog,实时更新缓存。
五、消息队列与异步处理
问题8:RabbitMQ在秒杀中如何保证消息不丢失?
- 考察点:MQ可靠性传输。
- 参考答案:
- 生产者确认:开启
publisher confirm
,确保消息到Broker。 - 持久化:队列和消息均设置持久化(
durable=true
)。 - 消费者手动ACK:业务处理成功后再确认消息,失败则重试或进入死信队列。
- 生产者确认:开启
问题9:异步下单后,如何保证最终一致?
- 考察点:最终一致性方案。
- 参考答案:
- 对账机制:定时任务比对MQ消息状态和订单表数据,修复异常。
- 补偿事务:若下单失败,通过MQ重试或人工介入补偿。
六、其他功能设计
问题10:点赞排行榜用ZSet实现,如何解决分数相同按时间排序?
- 考察点:Redis数据结构设计。
- 参考答案:
- 复合分数:
score = 点赞数 * 1e10 + (1e10 - 时间戳)
,确保先按点赞数排序,相同点赞数按时间倒序。
- 复合分数:
问题11:关注功能用Set实现,如何优化“共同关注”查询性能?
- 考察点:Redis集合操作。
- 参考答案:
- SINTER命令:直接取两个用户关注集合的交集。
- 缓存结果:对高频查询(如大V的共同关注)结果缓存10分钟。
七、开放性考察
问题12:如果QPS从300提升到1000,系统可能出现哪些瓶颈?如何优化?
- 考察点:系统扩展性思考。
- 参考答案:
- 潜在瓶颈:Redis集群带宽、MQ堆积、分布式锁竞争。
- 优化方向:
- Redis分片:按业务拆分集群(如秒杀Redis、缓存Redis)。
- MQ分区:按用户ID哈希分区,提升并行度。
- 锁优化:分段锁(如库存拆分为10个子库存)。
总结
通过这些问题,面试官可以全面评估候选人在高并发系统设计、分布式技术、缓存策略和业务逻辑实现上的能力。候选人在回答时应注重技术细节+业务场景结合,突出解决问题的思考过程和技术选型的权衡。
项目介绍:
一个仿百度云盘面向C端用户的网盘项目,包括用户注册,QQ快捷登录,文件上传,分片上传,断点续传,秒传,文件在线预览,包括文本,图片,视频,音频,excel,word ,pdf 等文件在线预览,文件分享等功能。
技术选型:Springboot + mybatis + mysql+redis+ffmpeg
负责内容:
-
用户注册,登录,发送邮箱验证码,找回密码。
-
文件分片上传,秒传,新建目录,预览,文件重命名,文件移动,文件分享,删除,下载 等功能。
-
回收站功能,还原文件,彻底删除。
-
项目难点:
-
文件分片上传,通过文件MD5实现文件秒传,文件分片上传后,异步对文件进行合并处理,视频文件,调用ffmpeg生成视频缩略图,将文件分片成ts文件。
-
通过redis缓存实时计算用户上传过程中空间占用情况。
-
多级目录线性展示,通过递归查询,查询目录的所有父级目录。
-
用户上传文件,同一级目录重名文件自动重命名,文件移动,同名文件重命名。
-
项目收获:
熟悉了第三方登录接入流程,比如QQ登录。让我熟练使用Springboot,采用spring的aop 的注解方式 实现了不同的接口权限不一样,比如普通用户和超级管理员权限的区别,同时使用aop和java反射实现了后端参数校验。使用redis缓存了一些系统设置,用户上传过程中空间使用实时计算,避免反复查询数据库。项目中解决了如何实现异步调用事务的问题,解决循环依赖的问题,如何调用第三方插件比如ffmpeg来实现对文件的分片处理,合并处理。 云盘项目让我学习到如何从功能点去设计数据库,在数据库设计的时候考虑到后续的扩展,比如文件数据的分表处理,可以根据用户id hash 取模的方式对文件数据进行分表处理,在开发过程中,通过spring的核心 aop来实现与业务的解耦。 该项目让我对java,数据库 所学知识进行了综合运用,让我能够使用java从0开发一个完整的项目。