请选择 进入手机版 | 继续访问电脑版
搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

《程序人生》系列-害敖丙差点被开除的P0事故

[复制链接]
查看: 55|回复: 0

2万

主题

3万

帖子

8万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
80196
发表于 2019-12-5 13:05 | 显示全部楼层 |阅读模式
  你晓得的越多,你不晓得的越多
  点赞再看,养成风尚
  GitHub  https://github.com/JavaFamily上已经收录有一线大厂口试点脑图、小我联系方式和技术交换群,接待Star和指教
前言

这是帅丙实在事变,大家都晓得很多公司都是有故障品级这么一说的,这就是敖丙在公司背的P0级故障,敖丙差点是以被解雇,事变经过很是惊心动魄,我的心脏病都差点复发
  变乱品级重要针对生产情况,别离根据类似于bug品级。
  P0属于第一流别变乱,比如崩溃,页面没法拜候,支流程欠亨,主功用未实现,大要在影响面上影响很大(即使bug自己不严厉)。
  P1变乱属于高级别变乱,一样平常属于主功用上的分支,干线流程,焦点次功用等,背面还有P2,P3等,重要按照企业现真相况别离。
正文

敖丙之前也负责公司的商品搜索营业,由于营业体量增速太快了,商品表中的商品数据也很快跃入万万级别,查询的RT(response time 响应时候)也越来越高了,而且产物说需要按照更多维度去查询商品
由于之前我们都是按照商品的称号去查询的,可是电商实在城市按照很多个维度去查询商品。
就比如大家去淘宝的查询的时候就会发现,你搜商品称号、色彩、标签等等多个维度都可以找到这个商品,就比以下图的搜索,我只是搜了【帅丙】你会发现,名字里面也没有连续的帅丙两个字,有帅和丙的出来了
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9ksvacqjpj30jg0hv12w
大家晓得的传统的关系型数据库都是用什么 name like %帅丙% 这样的方式查询的,而且查询出来的结果必定只能是name里面带帅丙的对吧。
那你还想搜此外字段比如什么尺寸、关键词、价格等等,都能搜到帅丙,这相当因而多个维度的了,传统的关系型数据库做不到呀。
做技术选型的时候,帅丙第一时候想到了搜索引擎。
那时市道是比力流行的有:Apache LuceneElasticsearchSolr
搜索引擎我背面会讲ELK(Elasticsearch、Logstash、Kibana)Canal,我呀真的是太宠你们了,这样会不会把你们惯坏了。
帅丙我呀,噼里啪啦一顿操纵,末端得出结论:
  相对来说,假如考虑静态搜索,Sorl相对更合适。
  假如考虑实时,触及到散布式,Elasticsearch相对合适。
那我们商品还是要实时的呀,你布景改了价格啥的,能否是都要实时同步进来,否则不是炸了嘛。
看到这,我想心爱的你和帅丙心中都有了答案:Elasticsearch这是个神一样的引擎。
我这里就做一个简单的先容就行了,细节的点我们背面去他的章节讲,啥都写了,敖丙那边有这么多素材写文章?
  ElasticSearch是一个基于Lucene的搜索办事器。
  它供给了一个散布式多用户本事的全文搜索引擎,基于RESTful web接口。
  Elasticsearch是用Java说话开辟的,并作为Apache答应条目下的开放源码公布,是一种流行的企业级搜索引擎。
  ElasticSearch用于云盘算中,可以也许到达实时搜索,安定,牢靠,快速,安装利用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和很多其他说话中都是可用的。
  按照DB-Engines的排名表示,Elasticsearch是最受接待的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
看过敖丙之前文章的朋友都晓得,我们做技术选型之前,要做什么呀,筹划
我们要去了解这玩意的优点毛病常见的坑出了题目标应急预案等等,还有他的数据同步机制啊,持久化机制啥的,就是高可用嘛。
一样的我不大篇幅先容了,今后城市写的嘛,我就给大家看看我那时做的筹划吧。
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kxzcemyyj31170u0qbo
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9lix2yggbj30dw0mvaig
这个只是最初的demo,具体的终稿我就不给大家看了,由于有很多公司内部的逻辑。
不外大家还是可以看到敖丙真的考虑了很多,还是那句话,不打没把握的仗!
筹划做好敖丙就卡卡卡的用起来了。
说真话,真香,这玩意真的好用,进修本钱也很低,查询语句分分钟把握了,官网文档把功用先容得清楚非常。
  https://www.elastic.co/cn/
用着用偏重头戏来了,你们都晓得敖丙我是做电商活动的,都是什么很高的流量打进来这样,还是如平常一样上线了一个活动。
这是一个月飞风高的夜晚,丝丝凉风当面吹来,敖丙安逸的坐在椅子上,手里拿着陈旧的茶杯,喝着外婆炒的苦荆茶,享用着这舒服的时光。
忽然,说时迟那时快,运维打来了垂危电话ES集群CPU打到了99%要挂了,我的心蓦地一痛,心田还在名誉还是集群没崩。
然后他接着说了一句,欠好集群挂了!
敖丙卒,本篇完….
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9ky95a8s2g308c08c3ze
恶作剧的哈,不外那时敖丙真的要死的心真的都要有了,就在崩掉的1分钟内,就有用户反应搜索未响应,我第一时候想到的就是重启,因而我一个健步冲进来,开启电脑,进呆板,输入了重启命令。
好了,是的好了,还好有惊无险,不外只过了10秒,集群又99%了,呐呢?
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kycthq28j30la0aa0xc
我又只能重启了,此次没挂,过了很久很久,直到活动竣事,还是没挂。
查找题目

可是此次影响到线上,3分钟的搜索未响应,我想我估量来日诰日是要去财政领人为,提早回家过年了。
还好Leader说没事,先找到题目,把他修复掉。
你们都晓得敖丙天赋来的,我第一时候想到的就是看日志,我登上去看es没报错,再看自己的办事,除了超时的毛病啥都没有,卧槽,是确那时我脑壳嗡嗡响。
不外我继续想为啥是我的搜索挂了,会不会是有人搜了什么希奇的工具?
我翻开了我的搜索日志!!!
卧槽这不是吧,哪个坑爹玩意搜这么长的一串中文,差不多250个字吧。
可是我一想,搜这么长也不应当打挂办事啊,会不会是我写了bug
我面颊流下一滴汗水,我看了看四周,发现没人留意到我的垂危,我故作冷静的把它擦掉。
我细致一想,他人查询固然长,就算查数据库也没事啊,为啥es就报错了?会不会?
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kysgpgumj308c06mt8s
Es有Bug!没错必定是Es的锅。
那为啥会这样呢,我间接跟老迈这样表白也似乎不成啊,还是要被解雇的吧!
因而我去看看看代码,我在关键词利用了通配符,我那时是为了婚配更多内容才这么做的,类似数据库的like,Es的通配符就是: * 帅丙 * 这样在关键词前后加“*”号去查询
背面我发现就是通配符的锅,那柯南丙就说一下为啥会这样的题目出现。
很多有RDBMS/SQL背景的开辟者,在初度踏入ElasticSearch全国的时候,很轻易就想到利用通配符(Wildcard Query)来实现暗昧查询(比如用户输入补全),由于这是和SQL里like操纵最类似的查询方式,用起来感受很是舒服。
但是帅丙的故障就显现了,滥用Wildcard query大要带来灾难性的结果
我那时首先复现了题目
复现方式


  • 建立一个只要一条则档的索引
  POST test_index/type1/?refresh=true
  {
  "foo": "bar"
  }
2.利用wildcard query实行一个首尾带有通配符*的长字符串查询
  POST /test_index/_search
  {
  "query": {
  "wildcard": {
  "foo": {
      "value": "悄悄的我走了,正如我悄悄的来;我悄悄的招手,作别西天的云彩。那河滨的金柳,是落日中的新娘;波光里的艳影,在我的心头泛动。软泥上的青荇,油油的在水底招摇;在康河的柔波里,我宁愿做一条水草!那榆荫下的一潭,不是清泉,是天上虹;揉碎在浮藻间,沉淀着彩虹似的梦。寻梦?撑一支长篙,向青草更青处漫溯;满载一船星辉,在星辉斑斓里放歌。但我不能放歌,静静是分此外笙箫;夏虫也为我沉默沉寂,沉默沉寂是今晚的康桥!悄悄的我走了,正如我悄悄的来;我挥一挥衣袖,不带走一片云彩。"
  }
  }
  }
  }

  • 检察结果
  {
  "took": 3445,
  "timed_out": false,
  "_shards": {
  "total": 5,
  "successful": 5,
  "failed": 0
  },
  "hits": {
  "total": 0,
  "max_score": null,
  "hits":
  }
  }
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9lio9m1vcj31eg0lmh57
即使no hits,耗时却是惊人的3.4秒 (测试机是macbook pro, i7 CPU),而且实行进程中,CPU有一个很高的尖峰。
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9lipoweu5j31e80guwod
线上的查询比我这个典范要复杂很多,会同时查几个字段,现实测试下来,一个查询大要会实行十几秒钟。
再有比力多长字符串查询的时候,集群大要就DOS了。
探查深条理根源

为什么对只要一条数据的索引做这个查询开销这么高? 直觉上应当是瞬间返回结果才对!
回答这个题今朝,可以再做个测试,假如继续加大查询字符串的长度,到了必定长度后,ES间接抛很是了,办事器ES里很是给出的cause以下:
  Caused by: org.apache.lucene.util.automaton.TooComplexToDeterminizeException: Determinizing automaton with 22082 states and 34182 transitions would result in more than 10000 states. at org.apache.lucene.util.automaton.Operations.determinize(Operations.java:741) ~[lucene-core-6.4.1.jar:6.4.1
表白:该很是来自org.apache.lucene.util.automaton这个包,很是原因原由的字面寄义是说“自动机过于复杂而没法肯定状态: 由于状态和转换太多,肯定一个自动机需要天生的状态横跨10000个上限"
柯南丙网上查找了大量材料后,终究搞清楚了题目标后果结果。
为了加速通配符和正则表达式的婚配速度,Lucene4.0起头会将输入的字符串形式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern机关出来的DFA大要会很复杂,开销很大
比如a*bc机关出来的DFA就像下面这个图一样:
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kzf4mkxmj30em08474m
Lucene机关DFA的实现

看了一下Lucene的里相关的代码,构建进程大略以下:

  • org.apache.lucene.search.WildcardQuery里的toAutomaton方式,遍历输入的通配符pattern,将每个字符酿成一个自动机(automaton),然后将每个字符的自动机链接起来天生一个新的自动机。
  1. public static Automaton toAutomaton(Term wildcardquery) {
  2.         List automata = new ArrayList();
  3.         String wildcardText = wildcardquery.text();
  4.         for (int i = 0; i < wildcardText.length();) {
  5.             final int c = wildcardText.codePointAt(i);
  6.             int length = Character.charCount(c);
  7.             switch(c) {
  8.                 case WILDCARD_STRING:
  9.                     automata.add(Automata.makeAnyString());
  10.                     break;
  11.                 case WILDCARD_CHAR:
  12.                     automata.add(Automata.makeAnyChar());
  13.                     break;
  14.                 case WILDCARD_ESCAPE:
  15.                     // add the next codepoint instead, if it exists
  16.                     if (i + length < wildcardText.length()) {
  17.                         final int nextChar = wildcardText.codePointAt(i + length);
  18.                         length += Character.charCount(nextChar);
  19.                         automata.add(Automata.makeChar(nextChar));
  20.                         break;
  21.                     } // else fallthru, lenient parsing with a trailing \
  22.                 default:
  23.                     automata.add(Automata.makeChar(c));
  24.             }
  25.             i += length;
  26.         }
  27.         return Operations.concatenate(automata);
  28.     }
复制代码

  • 此时天生的状态机是不肯定状态机,也就是Non-deterministic Finite Automaton(NFA)。
  • org.apache.lucene.util.automaton.Operations类里的determinize方式例会将NFA转换为DFA
  1. /**
  2.   \* Determinizes the given automaton.
  3.   \*
  4.   \* Worst case complexity: exponential in number of states.
  5.   \* @param maxDeterminizedStates Maximum number of states created when
  6.   \*  determinizing. Higher numbers allow this operation to consume more
  7.   \*  memory but allow more complex automatons. Use
  8.   \*  DEFAULT_MAX_DETERMINIZED_STATES as a decent default if you don't know
  9.   \*  how many to allow.
  10.   \* @throws TooComplexToDeterminizeException if determinizing a creates an
  11.   \*  automaton with more than maxDeterminizedStates
  12.   */
复制代码
代码表白里说这个进程的时候复杂度最差情况下是状态数目标指数级别!
为避免发生的状态过量,消耗过量的内存和CPU,类里面对最大状态数目做了限制
  1. /**
  2.   * Default maximum number of states that {@link Operations#determinize} should create.
  3.   */
  4. public static final int DEFAULT_MAX_DETERMINIZED_STATES = 10000;
复制代码
在有首尾通配符,而且字符串很长的情况下,这个determinize进程会发生大量的state,以致会横跨上限。
至于NFA和DFA的区分是什么? 怎样相互转换?
网上有很大都学层面的材料和论文,限于帅丙算法方面有限的常识,无精神去深入探讨。
可是一个粗浅的大白是: NFA在输入一个条件的情况下,可以从一个状态转移到多种状态,而DFA只会有一个肯定的状态可以转移,是以DFA在字符串婚配时速度更快。
DFA固然搜索的时候快,可是机关方面的时候复杂度大要比力高,出格是带有首部通配符+长字符串的时候。
回想Elasticsearch官方文档里对于Wildcard query有出格分析,要禁止利用通配符开首的term
  " Note that this query can be slow, as it needs to iterate over many terms. In order to prevent extremely slow wildcard queries, a wildcard term should not start with one of the wildcards * or ?."
团结对上面Wildcard query底层实现的探讨,也就不难明白这句话的寄义了!
小结: Wildcard query应根绝利用通配符打头,实在不得已要这么做,就必定需要限制用户输入的字符串长度。
最好换一种实现方式,经过在index time做文章,选用合适的分词器,比如nGram tokenizer预处置赏罚数据,然后利用更廉价的term query来实现齐截的暗昧搜索功用。
对于部分输入即提醒的利用处景,可以考虑优先利用completion suggester, phrase/term suggeter一类性能更好,暗昧水平略差的方式查询,待suggester没有婚配结果的时候,再fall back到更暗昧但性能较差的wildcard, regex, fuzzy一类的查询。
补充: 有同学问regex, fuzzy query能否有一样的题目,答案是有,原因原由在于他们底层和wildcard一样,都是经过将pattern机关成DFA来加速字符串婚配速度的。
回想:为啥之前挂了一次重启规复了,立即又挂了?用户搜了两次。。。
打点计划

实在打点这类题目很简单,既然晓得关键词长了会有题目,我就做限制嘛,大家可以去看看搜索引擎某度、某宝啥的,能否是都做了长度限制?
我复制了很长的一段汉字进去百度就是这个结果咯,某宝太长都返回默许页面了。
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kzk65eauj30fw04o3z3
image-20191204205715057
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9kzmp624jj30su06ftah
假如你的产物必定要给用户一点工具,简单,找出一些热词分析出来就行了,大要给点热搜商品兜底
我怎样做的呢?判定字符串长度大于50我就间接返回空数组了,这样对用户体验好点,你返回个参数毛病大要默许毛病他人还以为你有Bug呢对吧。
总结

实在敖丙我啥变乱品级都没背哈哈,这个算是变乱,可是敖丙我这么心爱,带领也疼爱我啊,必定不会怪我的拉,重如果我筹划都考虑了很多计划和场景了,没想到有这个坑。(yy:敖丙你个渣男,又是题目党,人家还以为你没工作了要养你呢!)
大家也可以经过此次变乱领会到,技术选型的时候,计划的垂危性了吧,就算你考虑不全,可是不至于实在的题目来了手足无措啊,并不是全数的变乱都可以像此次这样重启就搞定了,不要存有侥幸心理,心存畏敬
罗唆

敖丙啊,又有牌面了,获得阿里云消息中心件团队小同伴的认可,而且发现居然是我学姐-风云(混名)!!!
她是个勤学的蜜斯姐,大家多多像杰出的仔进修,学姐不是做技术的,可是都在不停进修,说真话我的眼角又湿了。
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9l48ouvc1j30jg0idacq
别跑,投票!!!

我预备把我的公众号JavaFamily 这个名字改了,这个名字还是差点意义,可是又不能叫敖丙了,被注册商标了,我就问了下群里的人材,现在有两个我比力喜好的

  • 帅丙
  • 三太子敖丙
  • 其他给我留言
由于这个大要会陪伴我很久,以致直到死去,盼望大家都给点倡议哈哈。
别问我为啥要跟敖丙这个名字相关,再问自杀
我混名就叫这个,所以
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006tNbRwly1g9l023nupwj306y099mxr
一样平常求赞

好了列位,以上就是这篇文章的全数内容了,能看到这里的人呀,都是人材
我背面会每周都更新几篇一线互联网大厂口试和常用技术栈相关的文章,很是感激人材们能看到这里,假如这个文章写得还不错,以为「敖丙」我有点工具的话   求点赞 求关注  求分享  对暖男我来说真的 很是有用!!!
创作不易,列位的支持和认可,就是我创作的最大动力,我们下篇文章见!
敖丙 | 文  【原创】【转载请联系本人】  假如本篇博客有任何毛病,请批评指教,不胜感激 !
  文章每周持续更新,可以关注我的公众号「 JavaFamily 」第一时候阅读和催更(公众号比博客早一到两篇哟),本文GitHub https://github.com/JavaFamily 上已经收录,有一线大厂口试颔领袖导图,接待Star和美满,里面也有我小我联系方式有什么题目也可以间接找我,也有技术交换群,我们一路有点工具。
《程序人生》系列-害敖丙差点被开除的P0事故  游戏 006y8mN6ly1g9e2keyxw6j30m80nmjyj
书三千,吾全取。
人万万,独暖你。 ---暖男敖丙

免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 妈妈网-中国妈妈第一,是怀孕、育儿、健康等知识交流传播首选平台 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表