靠伙伴匹配系统找到实习工作
投递简历到获得第一次面试机会 10 天。
个人背景:民办二本,只有一个伙伴匹配项目,没有实习经验。
面试到发 offer 大概 2 天。
面试整体流程有卡壳但是还算挺顺畅的。这里感谢鱼皮哥提供的项目与项目面试题。
面经
1. 自我介绍
2. 项目问题
- 编辑距离算法
- 优先队列
- 如何使用Redis GEO 实现寻找附近的人
- 线程池批量导入数据
- 遇到了哪些难点
- 登录问题:分布式除了使用Redis实现 ,还有哪些实现方式
3. 技能
- 做过微服务项目吗
- 配置中心和注册中心用什么?
- Nacos,如何获得最新的配置
- Gateway 的作用
- Spring MVC 的请求流程
- 适配器模式
4. 其余:
- 你家住哪里,几号可以入职,毕业设计的问题
以下是复盘之后的回答,修改过,主要是伙伴匹配系统的回答(球友们仅供参考)...
自我介绍:
参考星球专栏-》面霸手把手教你面试》自我介绍
总结
- 向面试官问好,几句话介绍自己的优势,要与众不同
- 讲述下自己的技术成长经历 7-8句
- 几个关键词总结,以及结束语
答:
面试官,你好,我叫xxx,我是一名xx大学生同时是24届毕业生,我在学校不仅每天拿出大量的时间学习编程,我还担任班长团支书,xxx的负责人。
我是从 xxx年xx月开始自学Java 后端编程,至今已经有着xx年的编程学习经验,参与过多个项目的开发。熟练掌握SpringBoot进行后端开发和MySQL,Redis等数据库进行项目开发。
用两个关键词总结我的学习经历是,“坚持”、“复盘迭代”。接下来我会继续投入在编程学习中。
我的介绍完毕,谢谢你的倾听。
(总结:其实写的一般般,并没有数据的量化,例如拿到什么比赛的名次,写过多少篇技术文章等等,项目达到什么效果也没说。不过是因为我没得说哈哈,太菜了,下一步要继续努力,做一些可以数据量化的事情。)
项目
编辑距离算法:
编辑距离算法是可以实现两个字符串之间的相识度与差异度的算法。
字符串A 进行多少次 增删改 可以变成字符串B
项目的是标签:【java,大一】变成【java,大二】需要经过一次修改。相识度分数为 1
我当时的实现思路是
引入网上一个现成的运算字符串匹配度的算法。
在单元测试类中,将其转化为字符串数组的匹配度的算法。
在项目中封装成一个工具类,使用的时候将用户的标签转化为String字符串数组来做为参数。
优先队列:
优先队列是根据优先级来实现出队入队的。
项目中,维护一个优先队列,保持 N 个,比优先队列内优先级低的不选择入队,比优先队列优先级大的,实现入队,并淘汰一个低的,使得队列保持在 N 中,减少内存的使用,Java的优先队列使用 PriorityQueue
具体的实现思路:
- 创建大顶堆的优先队列。
- 通过传入比较器创建,泛型是Pair(Pair 是存储键值对的,第一个键是user,第二个是相识度的分数),
- 先查询数据库中的所有用户
- 优先队列初始化,将前 num(这个值是前端传递过来的,默认为5) 个用户数量插入队列中。
- 计算相识度
- 将之后的用户与登录用户逐一相比较计算分数,比较堆顶的距离与计算的分数,若计算分数要小于,则删除堆顶元素,插入新元素到优先队列中。
- 通过Stream 流将优先队列中存储的userid 获取出来,收集为UserIdList。
- 根据 UserIdList 查询出最终的用户列表,进行脱敏返回。
Redis GEO实现查询附近的人:
我提供两个接口。1.上传地理位置,2.查询附近的人。查询附近的人之前必须先上传地理位置
- 先封装一个请求类:包含userId,经度lon,纬度lat,半径redius,两个接口的请求参数都是使用这个类
- 封装常量类,用来定义上传Redis的key值
上传地理位置接口:
- 校验参数:是否为空?
- 上传地址位置,存入Redis中,创建 RedisGeoCommands.GeoLocation对象,使用redisTemplate.opsforGeo.add
查询附近的人接口:
校验参数
1 获取用户id是否登录
2 redius 是否为空,空则默认为3000m
3 查询经度,纬度,为空的话在 redis 中获取
查询
1 根据 Redius 创建 Distance 对象,根据经度、纬度创建 point,根据 point,distance对象 创建 circle
2创建 Geo 命令参数对象 RedisGeoCommands.GeoRadiusCommandArgs设置查询限制条件返回限制 20人,返回包含距离,按由近及远排序。
3开始查询:使用命令查询redisTemplate.opsForGeo().radius(key, circle, args);获取附近的人的结果。
处理结果
1.创键map,第一个参数 是 userid 第二参数是泛型参数 Vo 类包装着(userId ,distance距离,username昵称,userUrl头像),forEach遍历查询GeoResults 结果,将其封装到 map 中,根据 map.keySet()方法获取UserId 查询附近的人的信息,并添加到对应的 vo类中。
返回结果
通过map.values(),返回结果:newArrayList(map.values())
线程池批量导入数据:
项目中,我使用 ThreadPoolExecutor 来实现线程池,创建任务列表,在循环中创建单一任务,加入到任务列表中。循环外使用线程池异步,并发的执行任务列表
遇到了哪些难点:
- 腾讯云实现头像
- 编辑距离算法
- 定时任务+Redisson分布式锁
具体的球友按照自身实际情况
用户登录问题:分布式除了使用Redis实现 ,还有哪些实现方式
Session 复制:利用 Tomcat 等 Web 容器同步复制
Session 前端存储:利用用户浏览器中 Cookie 保存 Session 信息
Session 粘滞方案:利用 Nginx 可以做四层 Hash 或七层 Hash 的特性,保证用户的请求都落在同一台机器上
Session 后端集中存储方案:利用 Redis 集中存储 Session,Web 应用重启或扩容,Session 也无需丢失。
上面四种方案,优先推荐第四种。
当然第四种方案需要一定的开发工作量,前期还没改造的过程可以选择 第三种方案中间过渡。
