黑马点评大总结

8.2.1 短信登录

  • 首先是用户提交手机号,后端将生成的验证码以及用户信息存入session中,用户登录时进行拦截并从session中拿出来信息校验,并把用户信息存入ThreadLocal中
  • session共享问题:每个tomcat有自己的一份session,分布式、微服务下有多个tomcat实例,之间的session无法共享
  • 解决: 负载均衡器通过特定算法如IP哈西,保证同一用户的请求始终路由到同一服务器。(失去负载均衡的灵活性)session复制,所有服务器同步session变更。(带宽消耗大)集中存储,将会话数据存储在外部,如redis客户端存储。(安全性挑战)
  • 采用后端生成token存入redis,前端请求头携带token校验身份 方案,并通过两层拦截器解决token刷新TTL问题(背景是有些页面不要求登录即可访问),先拦截所有请求判断token有无,有则刷新并存信息与ThreadLocal,后拦截特殊路径判断是否登录(ThreadLocal中是否有用户信息),有则放行,无则拦截显示请登录 8.2.2 商户缓存
  • 查询逻辑:先查询缓存再查询数据库再写入缓存(背景:老查询数据库,压力很大)
  • 缓存更新策略有内存淘汰、超时剔除、主动更新
  • 缓存双写一致性问题:数据源来自于数据库,数据库发生变化时也要更新缓存
  • 采用先更新数据库再删除缓存的方案,但仍有问题:多线程环境下可能出现缓存正好过期去查询数据库得到旧值,更新操作完成并删除缓存(空缓存)然后旧值被写入(极小概率)
  • 解决: 设置较短的TTL,减少缓存与数据库不一致的时间窗口将策略改为 延迟双删策略
  • 引入缓存提高查询性能,必然会引出一系列问题,上面的缓存双写一致性问题为其一,其二就是缓存穿透问题,若查询本就不存在的数据,每次都会打到数据库上,增加压力
  • 解决: 缓存特殊值:查询数据库后返回特定值比如defaultNull并设置ttl写入缓存,所有命中缓存后增加判断value值一逻辑操作。问题:只能应对正常业务问题,不能应对黑客使用大量不同的key进行攻击问题(还是会全部打到数据库上)布隆过滤器:本质是BitMap+多个Hash函数,将所有有效key存入bitmap,挡在redis前多一次判断。问题:由于其特性(hash冲突问题)导致存在误判(有的不一定有,但无的一定没有)
  • 当大量缓存key同时失效或者redis突然宕机就,导致大量请求打到数据库,造成缓存雪崩
  • 解决: 给不同的Key的TTL添加随机值利用redis集群提高服务的可用性给缓存业务添加降级限流策略给业务添加多级缓存
  • 当一个高并发访问的key突然失效(热门商户),无数的请求打到数据库,造成了缓存击穿问题
  • 解决: 加互斥锁:缓存未命中则加分布式锁(set nx ex)如果失败则进行方法休眠+递归重试,成功则去查询数据库并写入缓存后释放锁。问题1:递归容易造成OOM,改为休眠+自旋重试。问题2:其他线程在重试,当缓存写好锁被释放后,又进行抢锁,改为双检加锁(在自旋过程中尝试去命中缓存),锁被释放后自旋的线程也无需在抢锁。缺点:死锁问题,且只能串行执行,性能受影响逻辑过期:缓存击穿问题主要是key的TTL到了,不设置TTL,而是吧TTL设置到value中,通过逻辑判断是否过期。重新封装一个类包含过期时间以及Object数据。判断过期后获取互斥锁(保证异步任务只提交一次),将查询数据库写入缓存的操作提交给异步线程处理(串行处理也可以)。返回过期数据。缺点:其他线程返回的是脏数据(已经过期的)总结:方案1是串行,执行加锁保证只有一个线程去查询数据库,方案2是异步执行,加锁保证查数据库写入缓存的操作只被执行一次,且先返回已经过期的数据问题:只要加分布式锁(set nx ex)就需要考虑业务未执行完锁超时过期问题,但此处业务是查询以及写入逻辑,即使锁过期导致其他线程获取锁进入逻辑,无非就是多了个线程执行缓存重建操作,但在删除锁时可能会出现张冠李戴的问题(DEL命令即使key不存在也会返回成功),无伤大雅。如果是扣减库存之类的操作就会出现超卖现象,是不允许的,需要增加watchdog。 8.2.3 优惠券秒杀
  • 全局唯一ID:规律性不能太明显,受单表数据量的限制。应当满足 唯一性、高可用、高性能、递增性、安全性。由符号位0+时间戳31bit+序列号32bit(秒内的计数器,支持每秒产生2^32个不同ID)
  • 下单业务逻辑:提交优惠券id - 查询信息 - 判断是否在活动期间 - 库存是否充足 - 扣减库存 - 创建订单
  • 超卖问题: 直接扣减库存在高并发情况下会导致超卖问题。解决:加悲观锁(太重);加乐观锁(CAS):执行sql时多一个库存容量判断是否大于0
  • 一人一单问题:在判断库存后增加 - 根据优惠券id+用户id判断是否已经下过单
  • 问题:多线程下(用户多次点击)可能同时判断出未下单,然后执行下单逻辑造成一人多单
  • 解决:加synchronized锁(判断是否已经购买+下单逻辑)保证只有一个线程执行下单逻辑,加到方法上,锁的粒度太粗,改为在代码块上加锁,用intern()方法从常量池中拿用户数据加锁,因为直接用userId的话不是同一个对象,每个线程都有自己的ThreadLocal,其中的用户信息对象是分别new的,不唯一。问题:方法被spring事务控制,如果在方法内部加锁,可能导致方法事务还没有提交,但是锁已经释放的问题(锁在方法结束时释放,但事务可能还未提交。其他线程可能读取到未提交的数据(脏读),或者覆盖未提交的修改。)
  • 通过加锁可以解决在单机情况下的一人一单安全问题,但是在集群模式(分布式)下还会有超卖问题(用户连多次点击被负载均衡到不同的服务上)
  • 解决:换用分布式锁,在判断完库存充足之后,执行逻辑前先创建锁key,这里以userId作为key(保证该用户的多次请求对应一个分布式锁)。加锁后通过代理对象执行接下来的方法(一人一单判断+扣减库存+创建订单),因为该方法加了@Transactional注解,一个非事务方法调用事务方法,事务不会生效。
  • 问题:若持有锁的线程在执行逻辑时阻塞了,导致锁超时提前释放,这时候其他线程(该用户的相同请求)就会持有锁执行后面逻辑,可能造成超卖问题。(也会出现误删问题,但不是本质问题,重点还是逻辑被执行了多次)
  • 解决:(锁误删解决,属于辅助方案),在获取锁时UUID+ThreadID作为value,在unlock()的时候判断value值是否为自己的锁。问题:unlock的逻辑不是原子的,极端情况下还是会出现误删情况,使用Lua脚本保证逻辑的原子性。(注意:解决误删问题并不能解决超卖问题,这个方案解决的是次要问题-误删锁,属于辅助手段,要想解决这里的超时释放问题得用watchdog机制)
  • 当下分布式锁:需要给锁续期解决超时释放问题,锁不可重入,主从一致性
  • 解决:Redisson中的RedLock 可重入原理:底层Hash结构+Lua脚本实现,大key标识锁是否存在,小key标识锁被那个线程持有重试原理:抢锁过程中,通过tryAcquire进行抢锁,先判锁是否存在,再判断是否属于当前线程watchdog原理:在获取锁后开启一个后台线程监控锁的ttl,超过三分之一后重置TTL 8.2.4 秒杀优化
  • 问题:当前逻辑全是串行执行
  • 解决:将部分逻辑单独提出来,异步执行,在判断用户可以下单后直接返回给用户成功,由后台完成剩下的下单操作,将判断逻辑放入redis中,库存是否足够、是否为一人一单,相应的信息存入redis中,判断后开启异步 queue 难点1:如何在reids中判断,将商品库存信息以及用户下单信息(set集合)提前存入,有库存以及set集合中没有该用户则说明可以下单。基于Lua脚本实现资格判断保证原子性,将订单id返回给前端难点2:如何知道最后下单是否成,将优惠券id和用户id封装后存入阻塞队列 开启独立线程不断从阻塞队列中获取信息实现异步下单逻辑
  • 问题:阻塞队列在JVM内存中,容易OOM;JVM挂了数据订单数据全没了
  • 解决:MQ 基于List的MQ:只支持单消费者,无法避免信息丢失(内存占用多时内存淘汰机制可能淘汰List中的数据,持久化没法保证数据100%持久),使用LPOP/RPOP命令消费消息后,消息立即从队列移除基于Stream的MQ:增加消费者组,生产可用 8.2.5 探店点赞
  • 对于其他用户发的博客可以进行点赞,开始逻辑为 直接数据库+1
  • 问题:用户可以无限点赞,应当为点赞/取消且点赞按钮高亮显示
  • 解决:增加isLike属性,标志是否被当前用户点赞;使用redis set集合判断是否点赞过,key为Blog,value为userId
  • 问题:检查Redis后到执行数据库更新之间存在时间窗口,可能导致多个请求同时通过检查,造成重复更新。
  • 点赞排行榜,显示出最早点赞的几名用户(如TOP5),有唯一性又具备有序性的 zset集合 以时间戳为score存入用户信息 8.2.6 好友关注
  • 一张tb_follow表标示关注信息,根据前端传来的id直接更新数据库保存关系信息
  • 增加共同关注功能需要求交集,利用set集合,存储用户的关注列表,userId作为key,然后用set集合的api求共同关注的用户id,关注则先存入数据库再更新redis,取关则先删除数据库再删除redis
  • 发动态时提醒粉丝,使用 Feed流 完成推送功能,采用TimeLine模式
  • 拉模式:查看时拉去所有Blog然后排序展示
  • 推模式:博主发送Blog时将信息推送给所有粉丝,就是我们在保存完探店笔记后,获得到当前博主的粉丝,然后把数据推送到粉丝的 redis 中去
  • 推拉结合:推送给活跃用户,普通用户拉取
  • 问题:因为数据是不断变化的,传统分页会导致展示重复的数据
  • 解决:Feed流的滚动分页 8.2.7 附近商户
  • redis使用GEO结构存储商家的经纬度以及店铺id,以店铺的typeId为key,将对应的商铺信息存入value 8.2.8 用户签到
  • 直接用数据表记录数据量太大
  • 解决:使用bitmap中的0,1来记录用户的签到情况
  • 吧年和月作为bitMap的key,每次签到把当天对应bitmap位置上的下标从0变为1
  • 获取某月的bitmap数据(十进制展示),与1进行与运算看看此位是否为1,从而进行签到统计(签到总数、连续签到)
全部评论
整体基本没有结构,我觉着一步一步思考是连贯的是没有太多结构的,总之挨着看下来肯定会有收获的
8 回复 分享
发布于 2025-05-06 22:44 河南
可以很全
4 回复 分享
发布于 2025-05-09 15:33 上海
3 回复 分享
发布于 2025-05-06 14:31 广东
牛逼,辛苦了
2 回复 分享
发布于 2025-05-22 00:21 吉林
谢谢佬
1 回复 分享
发布于 2025-05-29 21:34 北京
m
1 回复 分享
发布于 2025-05-29 17:06 江苏
mark学习
1 回复 分享
发布于 2025-05-28 15:35 江西
请问记这些面试够了吗
1 回复 分享
发布于 2025-05-16 17:15 美国
想问一下大家 本人力扣能力 自我感觉良好 项目经历很差 视频速过了黑马点评 而且面试的过程中 感觉面试官基本上都是出手撕 所以侥幸通过 hr电话口头offer 想问一下大家实习过程中 如果项目这些不懂 会被辞退嘛
1 回复 分享
发布于 2025-05-10 15:02 江苏
mark
点赞 回复 分享
发布于 2025-11-22 18:09 北京
mark学习
点赞 回复 分享
发布于 2025-09-28 16:04 湖北
mark学习
点赞 回复 分享
发布于 2025-09-06 12:45 江苏
mark学习
点赞 回复 分享
发布于 2025-09-02 22:04 广东
mark
点赞 回复 分享
发布于 2025-07-20 14:37 浙江
mark学习
点赞 回复 分享
发布于 2025-07-13 16:00 江西
辛苦了!太厉害了
点赞 回复 分享
发布于 2025-07-12 16:04 江苏
mark
点赞 回复 分享
发布于 2025-07-03 14:24 湖北
mark
点赞 回复 分享
发布于 2025-06-24 08:58 辽宁
mark学习
点赞 回复 分享
发布于 2025-06-07 23:25 河北
接好运
点赞 回复 分享
发布于 2025-06-02 13:42 河南

相关推荐

国际商业化产品与技术-测试开发实习生(面向2027届毕业生)团队介绍:国际商业化产品与技术团队支持字节跳动国际产品的广告产品与变现技术。我们负责end2end的大型广告系统建设,为客户提供商业推广方式与方案。我们的团队遍布北京、上海、美国、新加坡等地,在这里你将有机会开阔自己的国际化视野,接触到全球领先的商业产品架构、模型和算法,并有机会参与并推动互联网广告行业的创新和变革。职位描述:1、深度参与商业变现测试开发工作;2、负责Web/Server/客户端产品的业务相关测试;3、对测试过程中发现的问题进行跟踪分析和报告;负责跟进Bug迭代进程,积极主动与产品、技术沟通,及时合理的解决测试中发现的问题;4、完成产品的集成测试、系统测试,以及必要的自动化测试、性能测试;5、推动并监控整个项目流程的实施,评估项目风险,推动问题的解决,保障产品质量。职位要求:1、本科及以上学历在读,计算机等相关专业优先;2、能熟悉以下一门或几门语言优先:Python/Go/Java;Linux/Shell;3、热爱软件测试开发工作,工作细致认真,有耐心;4、沟通表达能力强,快速理解工程和产品的细节;5、有大规模系统测试开发经验者优先,熟悉计算广告,或者有相关测试开发经验者优先。6、每周出勤至少4天,可实习4个月以上有兴趣欢迎先私聊我,私聊后发字节邮箱验证真伪主要就我派活,不搞心态,友好相处共同做牛马。这个岗位工作压力较大(我自己是1095左右,不要求实习生早来晚走,活干完之后早走完全ok),没有转正名额,干的好了我辞职让贤。希望也别搞我心态,互相理解互相尊重,打工人不互相为难。可能的收获:对go语言会有较大加强,一起写端到端的复杂的自动化case,以及数据校验的流程。会对业务有比较深入的理解。对python小幅加强,单接口的case比较多国际同事很多,对各国风土人情感兴趣的话会是个不错的机会广告业务的核心流程会对你开放,有一些东西还蛮有意思,一个视频从制作到投广,怎么找到为它付费的人,怎么找到受众,怎么算钱balabala...反正了解新东西吧,有点增量不纯搬砖一些职场通用能力和福利,字节有很多好玩的工具功能,甚至还包括心理咨询呀gemini额度呀可以来薅
点赞 评论 收藏
分享
2025-12-11 08:57
门头沟学院 Java
先定方向:要么选 Java/Go 做后台,要么 Python 整算法,别在语言上纠结,先跑通一个项目再说。花两周搓个能跑的系统:图书管理、二手交易、博客都行,记得把代码扔 GitHub,README 写清楚怎么启动;再花九块钱包个学生机,把项目挂上去,能打开就有说服力。性能别吹太大,能说出“把查询时间从 3 秒压到 300 毫秒”就够。算法别裸考,每天刷几道 ******** 热门题。简历只要一页,标题别写“课程设计”,直接叫“迷你电商平台”。三句话:我干了啥、解决啥、结果啥,能带数字就带数字。技能行写“SpringBoot Redis MySQL Git Linux”一行完事,别凑字数。页眉放 GitHub 链接,HR 能点进去才算数。找坑先翻校友群,吼一句“学长你们组还缺人吗?”一周能约两三面。没学长就蹲******** 的“急招”“可转正”,看到“立即到岗”就撩,回复率比官网高得多。三月开始大厂暑期实习,0 经验也能投,先拿笔试练手,面评留档不亏。面试准备三件套:项目三分钟讲清场景、模块、难点、结果;手写代码把 Top 100 抽 10 题练到徒手 A;出勤直接说“五天全勤、连干三月、随时到岗”,HR 听完基本稳。第一份实习别嫌小,把代码、文档、bug 记录全存好,三个月后这就是你的“真实项目”。在岗继续刷题背八股,第二轮跳中大厂,工资和履历一起翻倍。能跑项目、能讲思路、能随时到岗,你已经跑赢八成零经验选手。快去把名字写进实习系统。 #
0经验如何找实习?
点赞 评论 收藏
分享
2025-12-31 14:37
北京理工大学 golang
提要:这是本人第5次面字节,自认为对字节面试了如指掌,奈何没有水平,前4轮面试通过率仅50%,更是达成了一次2面挂一次3面挂的大满挂成绩一面 12.17聊项目,纯聊,聊两段字节实习内容,拷打设计(因为全都是如实写的,所以根本问不倒),又聊两段项目经历。整个过程半小时。八股:浏览器输入url之后的全过程;mysql引擎是什么,索引是什么,B+树和B树区别。因为在实习,八股没看,所以都没怎么回答,直言自己不清楚。手撕:lc92. 反转链表 II,一道medium(这已经是第n次考链表题了,字节真的很喜欢问链表)反问:组里做什么的二面 12.25聊最近一段实习的一个工作内容,聊了40分钟,感觉面试官很感兴趣,一直在问,遂详细的从头到尾拆开揉碎了说自己做的这个工作。因为这个的的确确是本人100%设计并开发的,感觉有很多点可以说,更是用到了不少组里第一次用的新内容,所以能够承受40min的深入拷打。八股:依旧直言自己没看八股。面试官就问我会哪一块,遂答mysql,便追问表是如何设计的,查询时会用到哪些索引手撕:没有lc题,让写一个二分查找,秒了反问:组里业务;lz脑子抽了还问了对方如何看待ks前几天的问题,对方滔滔不绝给我分析了一遍ks的问题和审核的模式,十分的能说会道,lz无不佩服三面 12.30无八股,无手撕,纯拷打先讲组里的工作内容,5min自我介绍,2min提问:什么时候毕业,实习多久,为什么不干创业的东西介绍一段实习中的一段项目(做的一个agents实现舆情搜索及推送),20min开始最难的拷打 30min 先总结了我的项目内容 然后提出n个问题进行逐一提问:没有使用爬虫进行召回的原因;对于关键词的选择策略;在设计workflow中哪些环节要设计reflection,怎么设计;舆情如何定义;召回效果的评估策略;反问:之后会具体做什么工作答得依托,感觉完蛋,又要似在三面吗更新:次日上午约hr面
查看15道真题和解析
点赞 评论 收藏
分享
评论
153
868
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务