范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

记一次ThreadLocal引发的线上故障,年终奖没了,可能还面临辞退

  事情起因
  耗子逗猫 —— 没事找事
  前几天,在工作不太忙的时候,为了展示我在工作中积极主动,技术能力较强,并给领导留个好印象,我就去翻翻项目代码有没有可优化的空间。
  没想到,我真让我找着啦。
  祸端就此埋下了!
  有用户反馈查询订单列表接口有点慢,我就去打印每一步的耗时信息。发现查询订单之前,需要先根据用户ID查询用户信息,而查询用户信息接口需要调用用户团队提供的服务,有时候网络较慢的时候,耗时达到200毫秒。
  而查询订单接口层层调用的时候,调用了好几次查询用户信息的接口。当然可以改成再最上层查询一次,然后层层往下传递,这样一来改的地方比较多,也很麻烦。
  我琢磨着能不能加个本地缓存,把用户信息缓存起来,这样就不用每次去调用用户服务查询了。刚好就想到了使用ThreadLocal,听说高级程序员都用ThreadLocal,我也想用一下试试。
  ThreadLocal是线程私有的,调用结束后,线程销毁了,ThreadLocal里面数据也跟着没了。
  听着ThreadLocal是线程安全的,应该没什么问题。
  动手实践
  我先写一个ThreadLocal的工具类,用来存储和获取用户信息:/**  * @author 一灯  * @apiNote 本地缓存用户信息  **/ public class ThreadLocalUtil {      // 使用ThreadLocal存储用户信息     private static final ThreadLocal threadLocal = new ThreadLocal<>();      /**      * 获取用户信息      */     public static User getUser() {         // 如果ThreadLocal中没有用户信息,就从request请求解析出来放进去         if (threadLocal.get() == null) {             threadLocal.set(UserUtil.parseUserFromRequest());         }         return threadLocal.get();     }  }
  然后在查询订单接口里面,调用这个工具类的方法获取用户信息,最后根据用户信息查询订单信息,完美。/**  * 获取订单列表方法  */ public List getOrderList() {     // 1. 从ThreadLocal缓存中获取用户信息     User user = ThreadLocalUtil.getUser();     // 2. 根据用户信息,调用用户服务获取订单列表     return orderService.getOrderList(user); }
  自测、提测、验收、上线,接口访问速度"嗖"一下就上去了,一切看上去都是那么完美。
  我已经开始幻想,升职加薪,迎娶白富美,走上人生巅峰了。
  事与愿违
  上线一个小时后,值班群炸了。
  陆续开始有用户反馈自己刚下的订单不见了,其他用户也有反馈自己的订单列表莫名其妙多了一些订单。
  我一脸懵逼,没碰到过这种情况,逐渐反馈的用户越来越多,我已经不知所措了。
  领导当机立断,小灯,你小子搞什么飞机,赶紧回滚服务。
  半个小时后,回滚完毕,用户的情绪逐渐平复下来。
  故障复盘
  线上故障解决后,紧接着就开始排查问题产生的原因。
  经过无数次打日志、debug,终于定位到问题了。
  ThreadLocal确实是线程私有的,并且会在线程销毁后,ThreadLocal里面的数据也会被清理掉。
  但是问题就出在,无论我们服务端用的是Tomcat、Jetty、SpringBoot、Dubbo等,都不会来一个请求就创建一个线程,而是创建一个线程池,所有请求共享这这个线程池里的线程。
  一个线程处理完一个请求,并不会被销毁。可能导致多个用户请求共用一个线程,最后出现数据越权,看到了别的用户的订单。
  解决方案
  解决办法就是,在使用完ThreadLocal后,再调用remove方法清除ThreadLocal数据。/**  * @author 一灯  * @apiNote 本地缓存用户信息  **/ public class ThreadLocalUtil {      // 使用ThreadLocal存储用户信息     private static final ThreadLocal threadLocal = new ThreadLocal<>();      /**      * 获取用户信息      */     public static User getUser() {         // 如果ThreadLocal中没有用户信息,就从request请求解析出来放进去         if (threadLocal.get() == null) {             threadLocal.set(UserUtil.parseUserFromRequest());         }         return threadLocal.get();     }      /**      * 删除用户信息      */     public static void removeUser() {         threadLocal.remove();     }  }
  使用try/catch包裹代码,然后在finally中清除ThreadLocal数据。/**  * 获取订单列表  */ public List getOrderList() {     // 1. 从ThreadLocal缓存中获取用户信息     User user = ThreadLocalUtil.getUser();     // 2. 根据用户信息,调用用户服务获取订单列表     try {         return orderService.getOrderList(user);     } catch (Exception e) {         throw new RuntimeException(e.getMessage());     } finally {         // 3. 使用完ThreadLocal后,删除用户信息         ThreadLocalUtil.removeUser();     }     return null; }
  故障定级
  影响用户超过10w,或者错误数据超过10w,或者资损大于50w,故障定级为P1,全年绩效C。
  本来想优化程序性能,提高访问速度,给领导一个好印象,显得自己技术能力强,工作积极主动。
  这下好了,不但年终奖没了,工作还可能保不住了。
  睡觉没盖屁股——我是露大脸了!
  事故总结
  经过这次事故,我总结了以下几点教训:没事儿别瞎逞能。没有金刚钻,别揽瓷器活。不求有功,但求无过。灯子,重构优化的水太深,你把握不住。
  推荐阅读:《我爱背八股系列》为什么要用MQ?MQ的作用有哪些?
  高并发场景下,如何保证数据的一致性的?
  如何进行分库分表?分库分表后有哪些问题以及对应的解决方案。
  高并发下怎么生成订单ID?以及每种方案的优缺点。
  如何实现分布式锁?使用数据库、分布式数据库、分布式协调服务分别如何实现?
  MySQL索引为啥用B+树?以及二叉树、红黑树、B树、B+各自的优缺点。

专业影像旗舰来袭,三星GN1加持下的vivoX50Pro表现远超预期随着相关技术的不断发展,不少朋友对于智能手机的影像要求也是越来越高,而在最近,vivo正式推出了vivoX50Pro,这款手机是vivoX50的顶配版本,是非常专业的5G影像旗舰。销量口碑双丰收!超大杯vivoX50Pro获权威媒体集体点赞在手机影像领域,vivo一直以来就有着举足轻重的地位,特别是旗下X系列机型,各个不仅颜值惊艳,影像实力也是尤为出众。前不久vivo也是正式发布了X系列最新款机型vivoX50,强悍5G专业影像旗舰vivoX50Pro,拍人拍景毫无压力vivoX50作为一款专业影像旗舰,在影像方面的性能可以说是非常出色。它的后置超清四摄,每一个摄像头表现都让人感到满意,功能非常齐全,完全可以满足消费者全面的拍摄需求。也有资格成为扉旅汽车实测LS500h矩阵大灯,雷克萨斯的技术被低估了作为一名汽车从业者兼雷克萨斯车主,如果你问我雷克萨斯相比别的品牌好在哪,我想说,除了产品好,服务棒之外,还有一个特点很多人可能并不知道,那就是雷克萨斯品牌所有车型都没有选装服务,即八个月便分手,拜腾前途未卜,富士康找好下家?有一首歌是这么唱的,爱情走得太快就像龙卷风。以此来形容富士康与拜腾的合作倒是贴切。近日,据外媒报道,富士康与拜腾的电动汽车合作项目,由于后者财务状况恶化已被终止。事实上,早在今年7减资43,烧掉上百亿,威马的Top3注定难成?先增再减,就是会玩。9月13日,天眼查APP显示,威马汽车运营主体公司威马智慧出行科技(上海)股份有限公司日前注册资本由12。09亿元减少至6。89亿元,减幅达42。99。而在7月20年购机避不开的2大刚需,懂手机的人都这样选一般来说,手机的选购是一个见仁见智的事情,有些人钟情于手机的CPU屏幕电池内存更看重硬件配置有些人喜欢漂亮的外观,追求独特的个性还有些人就是钟爱苹果非华为不买,没有太多理由可讲。年暑期必备,畅爽一夏!5G流畅先锋iQOOZ1x带来极致畅快体验作为国内手机品牌的后起之秀,iQOO以其发布的多款在各方面的表现都十分出色的手机赢得了众多酷客的喜爱和支持,而前段时间其5G流畅先锋iQOOZ1x的发布更让iQOO品牌成为了一个热六月份头条热门手机品牌vivo以超高增幅挤进前三甲手机市场近年来充满变数,以互联网手机起家的小米,热度和销量都大不如前,而像三星Sony诺基亚这些老牌厂商也因水土不服等原因导致国内市场份额日益缩减。但像华为vivo等厂商却逆流而上台积电突发大火,iPhone断供将持续?网友还是小米品牌给力想要用上苹果新款的小伙伴,少则几周的时间,长则需要一个月的时间,而前几天,为苹果代工芯片的台积电发生了火灾,对于果粉来说真是一波未平一波又起,要是选择苹果的小伙伴无疑是需要等更久的iPhone13来临?快充屏幕各个方面还在挤牙膏?网友评论亮了IPhone手机凭借他性能强劲的处理器,和流畅的IOS系统,完美的质感,一直受着年轻人的喜爱!近期IPhone13系列曝光,距离发布越来越近,让我们来看看,他的配置吧!图片来源于网
小巧轻便快充,摩米士小方钻上手体验前言升级了iPhone12ProMax之后,笔者终于也可以顺势升级配套的快充。对比市场中各种品牌的快充套件,如绿联紫米摩米士倍思等等,最终选择了摩米士的小方钻。主要原因有3点一是价数码产品充电器怎么选?努比亚小黄人联名款丰富你的选择内卷这个词大家想必并不陌生,简单点来说,它就是一个消耗精力的死循环。开始是指人,但后来发现放在企业的发展中也毫无违和感。时下,由于各大厂商正在产品设计方面缺乏创新,普遍存在新产品堆戴庆成MIRROR为何在香港走红?明天(11月3日)是香港什么重要的纪念日?我这几天随机询问了身边一些香港朋友,上了年纪的大多答不出来,平日稍微有留意娱乐新闻的年轻朋友们则能一口答出这一天是MIRROR出道三周年的上海迪士尼乐园因一名确诊游客紧急关闭但万圣节的烟花照常升起(上海北京综合讯)上海市接到浙江省杭州通报检出一名曾入园游玩的冠病阳性病例,前天下午紧急关闭上海迪士尼乐园和迪士尼小镇,并通告上周末和星期天曾进入乐园的所有人员须进行核酸检测。上海消消气,小伙子!拜登向马克龙坦承美在核潜艇事件中做法笨拙拜登(左)与马克龙周五在罗马的法国大使馆会晤。双方同意修补此前出现裂痕的双边关系。(法新社)(罗马综合电)美国总统拜登向法国总统马克龙坦承,美国背着法国与澳大利亚达成潜艇交易做法笨缅甸政府军与人民武装再交火逾160房屋被毁(曼谷综合电)缅甸动荡局势持续恶化,西北部钦邦一城镇上周五发生武装冲突,导致160多个房屋被烧毁,军政府声称火灾是当地反政变民兵所致。缅军方自2月1日发动政变推翻翁山淑枝领导的民选太恐怖了!东京列车发生持刀伤人纵火案日本东京都一列车星期天(10月31日)晚上发生一起持刀伤人并纵火事件,导致17人受伤,一人情况危急。嫌疑人已被警方逮捕。惊恐的列车乘客从列车窗口爬出逃命。(互联网)法新社和新华社综印度部署美制奇努克直升机可改变中印边境游戏规则?(新德里彭博电)中印边界领土争议未休,印度却在东北部与中国有主权争执的地区部署奇努克直升机等美国武器,引发关注。去年6月,中印两国在有主权争议的喜马拉雅山脉边界地区发生冲突,导致2新加坡这款APP能通过捡垃圾累计积分换礼品作者卢慧恩看见地上有垃圾,随手捡起即可积分,兑换红树植物或参与抽奖,还能结识新朋友。新捡拾垃圾应用带动用户自行发起和加入沿途捡垃圾活动,保持环境清洁。为配合新加坡清洁日(SGCle没打第三针?不能在北京做这些工作中国首都北京市昨天(10月28日)宣布,未接种第三剂加强针人员,不得从事重点岗位工作。综合中新网和环球网报道,北京市住房和城乡建设委员会党组成员副主任丁胜在新闻发布上说,北京持续推2021年AI和Python就业有多难?阿里工程师给你答案AI和数据行业的快,让人超乎想象。前几年的热点还是下围棋类的单点技术,如今已经覆盖了衣食住行生活商业的方方面面。AI技术和数据科学发展的快,要求从业者的能力也要快速迭代,除了算法模