个人评价

安全狗主要还是做安全的,所以java开发约等于小厂。后端开发主要使用的技术栈技术ssh+jsp。

技术可谓是先当的古老,本次面试内容主要以项目为主。也是首次收到面试官的夸奖,面试下来也是非常开心的。

介绍一下实习项目吧? (合并写请求)

我的实习项目主要就是做C端的在线教育项目,并且呢,它采用的基于alibaba那套落地的微服务方案。可能也是因为我是实现生的源固,我没有负责黄金链路,从用户登录到用户下单再到用户观看视频的整个流程,我主要负责的就是负责辅助模块的开发。评论区,点赞,排行榜模块的开发。

那我给您介绍一下我记得比较清楚的难点吧。

当时要做一个续播功能,也就是用户切换其他设备的时候也能从对应的位置上继续观看,本质上就是去修改数据库中观看记录表的数据,在公刚开始的想法就是直接去操作数据库,对了,每个用户前端每隔15秒会提交一次观看位置的请求,并且上级这边说qps会达到3000左右,也就是同时观看人数最多会有3000人左右,因此我们要进行优化,我们会发现这些请求中只有最后一次的观看位置是有用的,所以设计的解决方案就是使用redis的hash结构+延迟消息来实现的。Hash结构中,使用大key存储课表Id,课表用来关联userId和课程的Id,使用小key存储节Id,value存储观看位置的数据,在每次请求进来后直接修改Hash中的数据,并且每次发送一个延迟消息,使用Redis的死信发送一个延迟15秒消息,并且也是当前的节点去监听该消息,监听到消息后,使用监听到的观看位置和当前在Hash结构中的观看位置进行比较,如果发现二者的相同,说明在这15秒内没有再次进行观看了,这个时候就去修改数据库。反之,如果不相同的话,说明此时用户还在进行观看,我们就直接丢掉消息。最终减少99%的DB操作。

那我在做完这个业务之后,也在思考,因为我们使用的是RabbitMq来存储观看位置的消息,此时可能就会出现问题,消费者的消费速度小于生成者生成速度。我目前主要了解到的解决方案就是增加消费者的个数,因为采用的是微服务的落地方案,所以我们可以增加消费者的个数。提升消费者的消费能力,我会创建线程池,使用多线程来消费消息,对消息队列进行扩容,我们可以使用惰性队列来存储消息,因为惰性队列使用磁盘进行存储,就导致它的容量非常大,但是呢,涉及到大量的文件IO操作,所以在速度上效率是比较低的。

还有没有其他的难点?

我记得比较深刻的就是这个评论模块,那评论模块有点类似B站,我觉得比较难得就是点赞模块,再设计上,我们并没有直接操作数据库中点赞记录表,主要还是怕恶意的请求,大量的点赞和取消赞请求,我们主要的解决方案就是redis的set结构 + zset结构+定时任务来解决的,set结构用来存储userId和业务的点赞关系,zset结构用来统计每一个业务对应的点赞数量(key存储业务类型,member存储业务id,scope存储点赞数)。在发送点赞请求后,我们会修改set中的数据,使用scard方法统计点赞数(因为set结构中存在一个位置存储count,所以调用scard方法的效率为O(N),效率十分的高),修改zset中的总点赞数。并且使用xxl-job做定时任务,调用popmin方法,每隔15秒就从zset中去30条数据做批量修改的操作,最终完成点赞模块。

在该业务完成后,我也在思考,点赞业务本来就是一个低频的业务,所以我自己认为其实没有必要做这个优化的,直接打db比较合适一点,这样也不需要RabbitMq。

HashMap是线程安全的吗?那要怎么保证线程安全?

HashMap不是线程安全的,解决线程安全的方法,我目前知道的就是SynchronziedMap和ConcurrentHashMap。ConcurrentHashMap的底层我也是有了解过的,在JDK1.8之前底层使用的Segement数组+数组来实现的。Segement数组中的每一个节点又是一定范围的数组数据,在进行上锁的时候锁住的是Segement节点,锁的粒度是比较大的,而在JDK1.8之后底层使使用Hash数组+链表+红黑树来实现的,在每次进行上锁的时候锁住的是数组节点或链表头或红黑树根。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部