作者:微信小助手
<section style="font-size: 15px;color: rgb(62, 62, 62);line-height: 1.8;word-spacing: 2px;letter-spacing: 2px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;" data-mpa-powered-by="yiban.io"> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.4185185185185185" data-s="300,640" src="/upload/241a952b936253a9c67ed785d8289baa.jpg" data-type="jpeg" data-w="1080" style=""></p> <p style="text-align: right;"><span style="font-size: 12px;color: rgb(178, 178, 178);">作者:陌溪</span></p> <p style="text-align: right;"><span style="font-size: 12px;color: rgb(178, 178, 178);">陌溪的学习笔记:http://note.moguit.cn</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><span style="color: inherit;font-size: inherit;"></span><span style="color: inherit;font-size: inherit;">前阵子,我在快乐搬砖的时候,突然群里小伙伴们疯狂 </span><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">@</strong><span style="color: inherit;font-size: inherit;"> 我,说蘑菇社区今天打不开了!</span><br></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">遇到事情不要慌,我琢磨着估计可能是网站又宕机了,重启一下就完事了</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">然后打开了蘑菇后台,顿时吓了一跳,好家伙今天的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">PV</strong> 竟然有 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">19w</strong>,要知道蘑菇这个小破站,每天撑死也就几千的访问量,咋突然今天蹦到 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">19W</strong> 了,难道蘑菇火了?</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">带着疑惑,看了看下方的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">UV</strong> 数,还是这 260 多的人数,咋就能搞到 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">19W</strong> 的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">UV</strong>,难不成每个人把蘑菇文章都看了一遍?</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="0.234375" src="/upload/ab51800d4cd6bcae55de078a19466bc7.png" data-type="png" data-w="2624" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="蘑菇后台PV、UV"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 蘑菇后台PV、UV </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">我马上切到了蘑菇后台日志,好家伙原来你这小子,现在还在刷着蘑菇接口</p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.9856459330143541" data-s="300,640" src="/upload/32bdaf5835454e3cd5e586dfdea8bb7e.png" data-type="png" data-w="627" style="width: 280px;height: 276px;"></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">还用 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Jmeter</strong> 在这压测蘑菇呢?直接给干了 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">19W</strong> 条记录,把蘑菇服务都给干趴了要</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="0.7918781725888325" src="/upload/d85058909eaa41e1863d100506f83c2d.png" data-type="png" data-w="2364" height="1872" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="蘑菇后台日志" width="2326"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 蘑菇后台日志 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">我反手就是复制一波 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong>,然后打开腾讯云服务器后台,找到防火墙创建新的规则,然后策略改为拒绝,同时这个小伙子的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">ip</strong> 地址给加上去,同时端口选择全部端口,即 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">1-65535。</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="1.1158536585365855" src="/upload/e263caa34d72765010cbb9aff4d9028f.png" data-type="png" data-w="820" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 355px;height: 396px;" title="新增防火墙规则"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 新增防火墙规则 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">创建完规则后,点击确定即可看到此条规则已经开始生效了,整个流程一气呵成。</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="0.1714788732394366" src="/upload/5225fe3b2453d37a1caacb0831111248.png" data-type="png" data-w="2840" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="规则生效"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 规则生效 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">然后切到蘑菇的后台,再也没有看到接口有被刷的迹象,至此恢复了正常。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">突然,我又想到了,这个小伙子会不会回头换了一个 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">ip</strong> 又卷土重来了?</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">那我岂不是他来一个 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">ip</strong>,就得封杀一个 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">ip</strong> ?这也太麻烦了吧</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="0.9062003179650239" src="/upload/a328b26a7a95514de327cb6480145b70.png" data-type="png" data-w="629" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 327px;height: 296px;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">脑袋灵机一动,是不是可以在网关上搞点事,原来的蘑菇网关,啥事没做,就只用来转发了一个请求</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">我们都知道 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Gateway</strong> 是对所有 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">API</strong> 服务进行统一管理的平台, 除了最基本的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">路由</strong> 功能外,还可以实现 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">安全验证</strong>、<strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">过滤</strong>、<strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">流控</strong> 等策略</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">所以,就想到了用 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Gateway</strong> 做一个限流功能,当某个 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">ip</strong> 访问次数过多的时候,直接给它拦截下来,防止一下把我们的服务给打挂了</p> <h2 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;font-size: 1.4em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">定义全局过滤器</span></h2> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">全局过滤器是作用于所有经过网关转发的请求的,实现 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">GlobalFilter</strong> 接口即可</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">同时 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Gateway</strong> 是通过同时实现 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Ordered</strong> 接口来实现控制过滤器的过滤顺序的,其中 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">id</strong> 越小其代表的优先级越高。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">完整的文件结构如下所示:</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="rich_pages wxw-img" data-ratio="1.001700680272109" src="/upload/19dca53f2f57be6d9278376c44edc4c2.png" data-type="png" data-w="588" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 370px;height: 371px;" title="目录结构"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 目录结构 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">在 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Gateway</strong> 项目中,创建全局拦截器文件 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IpLimitFilter.java</strong></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">/**<br> * IP限流<br> * <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">@author</span> 陌溪<br> * <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">@date</span> 2022年3月28日08:40:37<br> */</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@Slf</span>4j<br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@RefreshScope</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@Component</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">class</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">IpLimitFilter</span> <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">implements</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">GlobalFilter</span>, <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">Ordered</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">public</span> Mono<Void> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">filter</span><span style="line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">(ServerWebExchange exchange, GatewayFilterChain chain)</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">null</span>;<br> }<br><br> <span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">int</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">getOrder</span><span style="line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">1</span>;<br> }<br>}<br></code></pre> <h2 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;font-size: 1.4em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">基于 Redis 的分布式限流算法</span></h2> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">实现了全局拦截器后, 陌溪在愉快的网上冲浪时,发现了一个 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">spring-boot-redis-ip-limiter</strong> 开源项目,使用的是 SpringBoot + Redis 组件,实现一个分布式接口 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 限流功能 。</p> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.9em;color: rgb(0, 0, 0);border-left-width: 5px;border-left-color: rgb(239, 112, 96);background: rgb(239, 235, 233);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="font-size: inherit;color: inherit;line-height: inherit;">Github地址:</p> <p style="font-size: inherit;color: inherit;line-height: inherit;">https://github.com/yudiandemingzi/spring-boot-redis-ip-limiter</p> </blockquote> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">项目的场景</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">为了防止我们的接口被人恶意访问,比如有人通过 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">JMeter</strong> 工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即一定时间内同一 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 访问的次数是有限的。</p> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">实现原理</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">用 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Redis</strong> 作为限流组件的核心的原理,将用户的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址当 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Key</strong>,一段时间内访问次数为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">value</strong> ,同时设置该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Key</strong> 过期时间。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">比如某接口设置 相同 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">10</strong> 秒 内请求 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">5</strong> 次,超过 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">5</strong> 次不让访问该接口。</p> <ol style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 32px;" class="list-paddingleft-1"> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>第一次该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址存入 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Redis</strong> 的时候,key值为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址, <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">value</strong>值为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">1</strong>,设置 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">key</strong> 值过期时间为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">10</strong> 秒。</p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>第二次该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址存入 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Redis</strong> 时,如果 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">key</strong> 没有过期,那么更新 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">value</strong> 为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">2</strong>。</p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>以此类推当 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">value</strong> 已经为 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">5</strong> 时,如果下次该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址在存入 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Redis</strong> 同时 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">key</strong> 还没有过期,那么该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">Ip</strong> 就不能访问了。</p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>当<strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">10</strong> 秒后,该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">key</strong> 值过期,那么该 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">IP</strong> 地址再进来,<strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">value</strong> 又从 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">1</strong> 开始,过期时间还是 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">10</strong> 秒,这样反反复复。</p></li> </ol> <p style="font-size: inherit;color: inherit;line-height:
作者:微信小助手
<section class="mp_profile_iframe_wrp" data-mpa-powered-by="yiban.io"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzA5MTU0OTY0Ng==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/zc3KLDBfJlmPt0J5PXYOoiaG8wsQPZrLevbxMZSfgQ0YypNYaicnbS0P9UicluuOySLSP4CjTcRUVHCZzYeXQ9WlA/0?wx_fmt=png" data-nickname="Java派" data-alias="javapai" data-signature="专注Java相关技术栈:Spring全家筒、Docker、k8s、Mysql、集群、微服务、中间件等知识。" data-from="0"></mpprofile> </section> <p style="outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);visibility: visible;text-align: center;"><span style="outline: 0px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);font-size: 14px;color: rgb(255, 41, 65);line-height: 22.4px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">首先,到底啥是分布式事务呢,比如我们在执行一个业务逻辑的时候有两步分别操作A数据源和B数据源,当我们在A数据源执行数据更改后,在B数据源执行时出现运行时异常,那么我们必须要让B数据源的操作回滚,并回滚对A数据源的操作;这种情况在支付业务时常常出现;比如买票业务在最后支付失败,那之前的操作必须全部回滚,如果之前的操作分布在多个数据源中,那么这就是典型的分布式事务回滚;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">了解了什么是分布式事务,那分布式事务在java的解决方案就是JTA(即Java Transaction API);springboot官方提供了 Atomikos or Bitronix的解决思路;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">其实,大多数情况下很多公司是使用消息队列的方式实现分布式事务。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">本篇文章重点讲解springboot环境下,整合 Atomikos +mysql+mybatis+tomcat/jetty;</p> </blockquote> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>一、项目依赖<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">pom.xml中添加atomikos的springboot相关依赖:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #272822;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #75715e;line-height: 26px;"><!--分布式事务--></span><br><span style="color: #f92672;line-height: 26px;"><<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: #f92672;line-height: 26px;"><<span style="line-height: 26px;">groupId</span>></span>org.springframework.boot<span style="color: #f92672;line-height: 26px;"></<span style="line-height: 26px;">groupId</span>></span><br> <span style="color: #f92672;line-height: 26px;"><<span style="line-height: 26px;">artifactId</span>></span>spring-boot-starter-jta-atomikos<span style="color: #f92672;line-height: 26px;"></<span style="line-height: 26px;">artifactId</span>></span><br><span style="color: #f92672;line-height: 26px;"></<span style="line-height: 26px;">dependency</span>></span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">点进去会发现里面整合好了:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">transactions-jms</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">transactions-jta</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">transactions-jdbc</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">javax.transaction-api</code></p> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>二、把数据源的相关配置项单独提炼到一个application.yml中:<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">注意:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">这回我们的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">spring.datasource.type</code> 是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">com.alibaba.druid.pool.xa.DruidXADataSource;</code></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">spring.jta.transaction-manager-id</code>的值在你的电脑中是唯一的,这个详细请阅读官方文档;</p> </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.08054226475279107" src="/upload/1f1c989dc1a16cf03ecad251bb6d69c8.png" data-type="png" data-w="1254" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">完整的yml文件如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #272822;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="line-height: 26px;">spring:</span><br> <span style="line-height: 26px;">datasource:</span><br> <span style="line-height: 26px;">type:</span> <span style="color: #a6e22e;line-height: 26px;">com.alibaba.druid.pool.xa.DruidXADataSource</span><br> <span style="line-height: 26px;">druid:</span><br> <br> <span style="line-height: 26px;">systemDB:</span><br> <span style="line-height: 26px;">name:</span> <span style="color: #a6e22e;line-height: 26px;">systemDB</span><br> <span style="line-height: 26px;">url:</span> <span style="color: #a6e22e;line-height: 26px;">jdbc:mysql://localhost:3306/springboot-mybatis?useUnicode=true&characterEncoding=utf-8</span><br> <span style="line-height: 26px;">username:</span> <span style="color: #a6e22e;line-height: 26px;">root</span><br> <span style="line-height: 26px;">password:</span> <span style="color: #a6e22e;line-height: 26px;">root</span><br> <span style="color: #75715e;line-height: 26px;"># 下面为连接池的补充设置,应用到上面所有数据源中</span><br> <span style="color: #75715e;line-height: 26px;"># 初始化大小,最小,最大</span><br> <span style="line-height: 26px;">initialSize:</span> <span style="line-height: 26px;">5</span><br> <span style="line-height: 26px;">minIdle:</span> <span style="line-height: 26px;">5</span><br> <span style="line-height: 26px;">maxActive:</span> <span style="line-height: 26px;">20</span><br> <span style="color: #75715e;line-height: 26px;"># 配置获取连接等待超时的时间</span><br> <span style="line-height: 26px;">maxWait:</span> <span style="line-height: 26px;">60000</span><br> <span style="color: #75715e;line-height: 26px;"># 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒</span><br> <span style="line-height: 26px;">timeBetweenEvictionRunsMillis:</span> <span style="line-height: 26px;">60000</span><br> <span style="color: #75715e;line-height: 26px;"># 配置一个连接在池中最小生存的时间,单位是毫秒</span><br> <span style="line-height: 26px;">minEvictableIdleTimeMillis:</span> <span style="line-height: 26px;">30</span><br> <span style="line-height: 26px;">validationQuery:</span> <span style="color: #a6e22e;line-height: 26px;">SELECT</span> <span style="line-height: 26px;">1</span><br> <span style="line-height: 26px;">validationQueryTimeout:</span> <span style="line-height: 26px;">10000</span><br> <span style="line-height: 26px;">testWhileIdle:</span> <span style="color: #f92672;font-weight: bold;line-height: 26px;">true</span><br> <span style="line-height: 26px;">testOnBorrow:</span> <span style="color: #f92672;font-weight: bold;line-height: 26px;">false</span><br> <span style="line-height: 26px;">testOnReturn:</span> <span style="color: #f92672;font-weight: bold;line-height: 26px;">false</span><br> <span style="color: #75715e;line-height: 26px;"># 打开PSCache,并且指定每个连接上PSCache的大小</span><br> <span style="line-height: 26px;">poolPreparedStatements:</span> <span style="color: #f92672;font-weight: bold;line-height: 26px;">true</span><br> <span style="line-height: 26px;">maxPoolPreparedStatementPerConnectionSize:</span> <span style="line-height: 26px;">20</span><br> <span style="line-height: 26px;">filters:</span> <span style="color: #a6e22e;line-height: 26px;">stat,wall</span><br> <span style="color: #75715e;line-height: 26px;"># 通过connectProperties属性来打开mergeSql功能;慢SQL记录</span><br> <span style="line-height: 26px;">connectionProperties:</span> <span style="color: #a6e22e;line-height: 26px;">druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000</span><br> <span style="color: #75715e;line-height: 26px;"># 合并多个DruidDataSource的监控数据</span><br> <span style="line-height: 26px;">useGlobalDataSourceStat:</span> <span style="color: #f92672;font-weight: bold;line-height: 26px;">true</span><br> <br> <span style="line-height: 26px;">businessDB:</span><br> <span style="line-height: 26px;">name:</span> <span style="color: #a6e22e;line-height: 26px;">businessDB</span><br> <br> <span style="line-height: 26px;">url:</span> <span style="color: #a6e22e;line-height: 26px;">jdbc:mysql://localhost:3306/springboot-mybatis2?useUnicode=true&characterEncoding=utf-8</span><br> <span style="line-height: 26px;">username:</span> <span style="color: #a6e22e;line-height: 26px;">root</span><br> <span style="line-height: 26px;">password:</span> <span style="color: #a6e22e;line-height: 26px;">root</span><br> <span style="color: #75715e;line-height: 26px;"># 下面为连接池的补充设置,应用到上面所有数据源中</s
作者:微信小助手
<p style="margin-top: 5px;outline: 0px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-size: 16px;text-align: center;line-height: normal;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;font-size: 10px;letter-spacing: 0.544px;text-align: justify;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:https://blog.csdn.net/m0_57315623?type=blog</span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;outline: 0px;max-width: 100%;overflow-wrap: break-word;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;visibility: visible;box-sizing: border-box !important;"> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;border-bottom: 2px solid rgb(239, 112, 96);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">前言</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">咱们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;border-bottom: 2px solid rgb(239, 112, 96);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">一.搜索引擎怎么搜索</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的) 为什么要用索引呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这里我们需要建立索引,索引分别为正排索引,和倒排索引。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> Q技能 阿尔法突袭 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> W技能 冥想 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> E技能 无双 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> R技能 高原血统 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所以这是根据名字选技能</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">倒排索引就是LOL里面谁有剑:</p> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 蛮王 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 无极剑圣 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 剑姬 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所以这是根据特点选择英雄</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">二.模块划分</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">1.索引模块</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">2.搜索模块</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">1)调用索引模块,实现一个搜索的完整过程。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">输入:用户的查询词 输出:完整的搜索结果</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">3.web模块</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。包含了前端和后端。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">三. 怎么实现分词</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">分词的原理:</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">1.基于词库</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">尝试把所有的词都进行穷举,把这些结果放到词典文件中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">2.基于统计</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">java中能够实现分词的第三方工具也是有很多的</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="rich_pages wxw-img" data-ratio="0.44568965517241377" src="/upload/91531c51191bb4cdade7b885de248dc0.png" data-type="png" data-w="1160" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">我们直接下载最新版本然后放入pom.xml里面</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="rich_pages wxw-img" data-ratio="0.5251989389920424" src="/upload/295e6bb7038b3274b437b0fcc30514c4.png" data-type="png" data-w="1885" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/dWYcndbpDnazVNUJia5cWzbHoACC9dMdSFjPicgeoEnMj4TDf4WvXABCaFibYQ1lH0VxEDgPERdAAoUOxDpKGxxtIsqsPxGEYz3/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import org.ansj.domain.Term;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">import org.ansj.splitWord.analysis.ToAnalysis;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">import java.util.List;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">public class TastAnsj {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> String str = <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。"</span>;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> List<Term> terms = ToAnalysis.parse(str).getTerms();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">for</span> (Term term : terms) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> System.out.println(term.getName());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">四.文件读取</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">把刚刚下载好的文档的路径复制到String中并且用常量标记。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/dWYcndbpDnazVNUJia5cWzbHoACC9dMdSFjPicgeoEnMj4TDf4WvXABCaFibYQ1lH0VxEDgPERdAAoUOxDpKGxxtIsqsPxGEYz3/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background:
作者:微信小助手
<section data-mpa-powered-by="yiban.io"> <section> <section data-tools="135编辑器" data-id="93761"> <section> <section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" mp-original-font-size="16" mp-original-line-height="25.600000381469727" style="outline: 0px;white-space: normal;text-size-adjust: auto;font-size: 16px;color: black;line-height: 25.6px;letter-spacing: 0px;word-break: break-word;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;visibility: visible;"> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">在我的上一篇文章中,我向您展示了如何模拟 DDoS 攻击以及如何缓解它。简单回顾一下,DDoS 利用了大量的伪造请求,导致目标服务器消耗大量资源来处理这些无效请求,从而无法正常响应正常用户请求。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">在 Linux 服务器中,可以通过内核调优、DPDK 以及 XDP 等多种方式提高服务器的抗攻击能力,降低 DDoS 对正常服务的影响。在应用程序中,可以使用各级缓存、WAF、CDN 等来缓解 DDoS 对应用程序的影响。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">但是需要注意的是,如果 DDoS 流量已经到达 Linux 服务器,那么即使应用层做了各种优化,网络服务延迟一般也会比平时大很多。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">因此,在实际应用中,我们通常使用 Linux 服务器,配合专业的流量清洗和网络防火墙设备,来缓解这个问题。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">除了 DDoS 导致的网络延迟增加,我想你一定见过很多其他原因导致的网络延迟,例如:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" mp-original-font-size="16" mp-original-line-height="25.600000381469727" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;visibility: visible;line-height: 25.6px;"> <li style="outline: 0px;visibility: visible;line-height: 25.6px;"> <section mp-original-font-size="16" mp-original-line-height="26" style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 网络传输慢导致的延迟。 </section></li> <li style="outline: 0px;visibility: visible;line-height: 25.6px;"> <section mp-original-font-size="16" mp-original-line-height="26" style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> Linux 内核协议栈数据包处理速度慢导致的延迟。 </section></li> <li style="outline: 0px;visibility: visible;line-height: 25.6px;"> <section mp-original-font-size="16" mp-original-line-height="26" style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 应用程序数据处理速度慢造成的延迟等。 </section></li> </ul> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">那么当我们遇到这些原因造成的延误时,我们该怎么办呢?如何定位网络延迟的根本原因?让我们在本文中讨论网络延迟。</p> <h2 data-tool="mdnice编辑器" mp-original-font-size="20" mp-original-line-height="32" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;visibility: visible;line-height: 32px;">Linux 网络延迟</h2> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;visibility: visible;">谈到<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;visibility: visible;line-height: 26px;">网络延迟(Network Latency)</strong>,人们通常认为它是指网络数据传输所需的时间。但是,这里的“时间”是指双向流量,即数据从源发送到目的地,然后从目的地地址返回响应的往返时间:<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;visibility: visible;line-height: 26px;">RTT(Round-Trip Time)</strong>。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;">除了<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">网络延迟</strong>之外,另一个常用的指标是<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">应用延迟(Application Latency)</strong>,它是指应用接收请求并返回响应所需的时间。通常,<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">应用延迟</strong>也称为<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">往返延迟</strong>,它是网络数据传输时间加上数据处理时间的总和。</p> <p data-tool="mdnice编辑器" mp-original-font-size="15" mp-original-line-height="26" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;font-size: 15px;">通常人们使用<span> </span><code mp-original-font-size="14" mp-original-line-height="26" style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;line-height: 26px;">ping</code><span> </span>命令来测试网络延迟,<code mp-original-font-size="14" mp-original-line-height="26" style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;line-height: 26px;">ping</code><span> </span>是基于 ICMP 协议的,它通过计算 ICMP 发出的<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">响应报文</strong>和 ICMP 发出的<strong mp-original-font-size="15" mp-original-line-height="26" style="outline: 0px;line-height: 26px;">请求报文</strong>之间的时间差来获得往返延迟时间。这个过程不需要特殊的认证,从而经常被很多网络攻击所利用,如,端口扫描工
作者:微信小助手
<p style="margin-top: 0.5em;margin-bottom: 0.5em;padding: 0.4em 0.6em;outline: 0px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;color: rgb(33, 37, 41);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;word-spacing: 1px;text-align: left;border-radius: 8px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"><strong><span style="color: rgb(255, 41, 65);">大家好,我是不才陈某~</span></strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">前面刚说到Guava Cache,他的优点是封装了get,put操作;提供线程安全的缓存操作;提供过期策略;提供回收策略;缓存监控。当缓存的数据超过最大值时,使用LRU算法替换。这一篇我们将要谈到一个新的本地缓存框架:Caffeine Cache。它也是站在巨人的肩膀上-Guava Cache,借着他的思想优化了算法发展而来。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">本篇博文主要介绍Caffine Cache 的使用方式,以及Caffine Cache在SpringBoot中的使用。</span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 15px;margin-bottom: 15px;"><span style="font-size: 20px;color: rgb(255, 41, 65);"><strong>| Caffine Cache 在算法上的优点-W-TinyLFU</strong></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">说到优化,Caffine Cache到底优化了什么呢?我们刚提到过LRU,常见的缓存淘汰算法还有FIFO,LFU:</span></p> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: left;white-space: normal;word-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"> <span style="font-size: 15px;">FIFO:先进先出,在这种淘汰算法中,先进入缓存的会先被淘汰,会导致命中率很低。</span> </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"> <span style="font-size: 15px;">LRU:最近最少使用算法,每次访问数据都会将其放在我们的队首,如果需要淘汰数据,就只需要淘汰队尾即可。仍然有个问题,如果有个数据在 1 分钟访问了 1000次,再后 1 分钟没有访问这个数据,但是有其他的数据访问,就导致了我们这个热点数据被淘汰。</span> </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"> <span style="font-size: 15px;">LFU:最近最少频率使用,利用额外的空间记录每个数据的使用频率,然后选出频率最低进行淘汰。这样就避免了 LRU 不能处理时间段的问题。</span> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">上面三种策略各有利弊,实现的成本也是一个比一个高,同时命中率也是一个比一个好。Guava Cache虽然有这么多的功能,但是本质上还是对LRU的封装,如果有更优良的算法,并且也能提供这么多功能,相比之下就相形见绌了。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">LFU的局限性</strong> :在 LFU 中只要数据访问模式的概率分布随时间保持不变时,其命中率就能变得非常高。比如有部新剧出来了,我们使用 LFU 给他缓存下来,这部新剧在这几天大概访问了几亿次,这个访问频率也在我们的 LFU 中记录了几亿次。但是新剧总会过气的,比如一个月之后这个新剧的前几集其实已经过气了,但是他的访问量的确是太高了,其他的电视剧根本无法淘汰这个新剧,所以在这种模式下是有局限性。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">LRU的优点和局限性</strong> :LRU可以很好的应对突发流量的情况,因为他不需要累计数据频率。但LRU通过历史数据来预测未来是局限的,它会认为最后到来的数据是最可能被再次访问的,从而给与它最高的优先级。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">在现有算法的局限性下,会导致缓存数据的命中率或多或少的受损,而命中略又是缓存的重要指标。HighScalability网站刊登了一篇文章,由前Google工程师发明的W-TinyLFU——一种现代的缓存 。Caffine Cache就是基于此算法而研发。Caffeine 因使用 <strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Window TinyLfu</strong> 回收策略,提供了一个<strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">近乎最佳的命中率</strong> 。</span></p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 20px;outline: 0px;border-top-style: none;border-right-style: solid;border-bottom-style: none;border-left-color: rgba(0, 0, 0, 0.65);color: rgb(106, 115, 125);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;border-right-width: 1px;border-right-color: rgba(0, 0, 0, 0.65);background-color: rgb(249, 249, 249);box-sizing: border-box !important;word-wrap: break-word !important;"> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-size: 14px;color: black;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"><span style="font-size: 15px;">当数据的访问模式不随时间变化的时候,LFU的策略能够带来最佳的缓存命中率。然而LFU有两个缺点:</span></p> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-size: 14px;color: black;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"><span style="font-size: 15px;">首先,它需要给每个记录项维护频率信息,每次访问都需要更新,这是个巨大的开销;</span></p> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-size: 14px;color: black;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"><span style="font-size: 15px;">其次,如果数据访问模式随时间有变,LFU的频率信息无法随之变化,因此早先频繁访问的记录可能会占据缓存,而后期访问较多的记录则无法被命中。</span></p> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-size: 14px;color: black;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;text-align: justify;"><span style="font-size: 15px;">因此,大多数的缓存设计都是基于LRU或者其变种来进行的。相比之下,LRU并不需要维护昂贵的缓存记录元信息,同时也能够反应随时间变化的数据访问模式。然而,在许多负载之下,LRU依然需要更多的空间才能做到跟LFU一致的缓存命中率。因此,一个“现代”的缓存,应当能够综合两者的长处。</span></p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">TinyLFU维护了近期访问记录的频率信息,作为一个过滤器,当新记录来时,只有满足TinyLFU要求的记录才可以被插入缓存。如前所述,作为现代的缓存,它需要解决两个挑战:</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">一个是如何避免维护频率信息的高开销;</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">另一个是如何反应随时间变化的访问模式。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">首先来看前者,TinyLFU借助了数据流Sketching技术,Count-Min Sketch显然是解决这个问题的有效手段,它可以用小得多的空间存放频率信息,而保证很低的False Positive Rate。但考虑到第二个问题,就要复杂许多了,因为我们知道,任何Sketching数据结构如果要反应时间变化都是一件困难的事情,在Bloom Filter方面,我们可以有Timing Bloom Filter,但对于CMSketch来说,如何做到Timing CMSketch就不那么容易了。TinyLFU采用了一种基于滑动窗口的时间衰减设计机制,借助于一种简易的reset操作:每次添加一条记录到Sketch的时候,都会给一个计数器上加1,当计数器达到一个尺寸W的时候,把所有记录的Sketch数值都除以2,该reset操作可以起到衰减的作用 。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">W-TinyLFU主要用来解决一些稀疏的突发访问元素。在一些数目很少但突发访问量很大的场景下,TinyLFU将无法保存这类元素,因为它们无法在给定时间内积累到足够高的频率。因此W-TinyLFU就是结合LFU和LRU,前者用来应对大多数场景,而LRU用来处理突发流量。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">在处理频率记录的方案中,你可能会想到用hashMap去存储,每一个key对应一个频率值。那如果数据量特别大的时候,是不是这个hashMap也会特别大呢。由此可以联想到 Bloom Filter,对于每个key,用n个byte每个存储一个标志用来判断key是否在集合中。原理就是使用k个hash函数来将key散列成一个整数。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">在W-TinyLFU中使用Count-Min Sketch记录我们的访问频率,而这个也是布隆过滤器的一种变种。如下图所示:</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="margin-top: 10px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;-webkit-user-select: none;inset: auto;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="rich_pages wxw-img" data-cropselx1="0" data-cropselx2="578" data-cropsely1="0" data-cropsely2="203" data-ratio="0.3507692307692308" src="/upload/f5892b410cda9dbd8a32c24b4c731b16.png" data-type="png" data-w="650" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;display: block;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-radius: 4px;margin: 0px;width: 578px;height: 203px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;inset: auto;"></span> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">如果需要记录一个值,那我们需要通过多种Hash算法对其进行处理hash,然后在对应的hash算法的记录中+1,为什么需要多种hash算法呢?由于这是一个压缩算法必定会出现冲突,比如我们建立一个byte的数组,通过计算出每个数据的hash的位置。比如张三和李四,他们两有可能hash值都是相同,比如都是1那byte[1]这个位置就会增加相应的频率,张三访问1万次,李四访问1次那byte[1]这个位置就是1万零1,如果取李四的访问评率的时候就会取出是1万零1,但是李四命名只访问了1次啊,为了解决这个问题,所以用了多个hash算法可以理解为long[][]二维数组的一个概念,比如在第一个算法张三和李四冲突了,但是在第二个,第三个中很大的概率不冲突,比如一个算法大概有1%的概率冲突,那四个算法一起冲突的概率是1%的四次方。通过这个模式我们取李四的访问率的时候取所有算法中,李四访问最低频率的次数。所以他的名字叫Count-Min Sketch。</span></p> <p data-tool="mdnice编辑器" style="margin-top: 15px;margin-bottom: 15px;"><span style="font-size: 20px;color: rgb(255, 41, 65);"><strong>| 使用</strong></span></p> <p data-tool="mdnice编辑器"><span style="font-size: 15px;">Caffeine Cache 的github地址:</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: justify;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">https://github.com/ben-manes/caffeine</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">目前的最新版本是:</span></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-right: auto;margin-left: auto;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-size: 14px;text-align: left;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;box-sizing: border-box !important;word-wrap: break-word !important;"><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background-color: rgb(30, 30, 30);border-top-left-radius: 5px;border-top-right-radius: 5px;border-bottom-right-radius: 5px;border-bottom-left-radius: 5px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">groupId</span>></span>com.github.ben-manes.caffeine<span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">artifactId</span>></span>caffeine<span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">version</span>></span>2.6.2<span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">version</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;margin-top: 20px;"><span style="font-size: 18px;"><strong>缓存填充策略</strong></span></h3> <h3 data-tool="mdnice编辑器" style="margin-top: 15px;margin-bottom: 15px;"><span style="caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;font-size: 15px;">Caffeine Cache提供了三种缓存填充策略:手动、同步加载和异步加载。</span></h3> <h4 data-tool="mdnice编辑器" style="margin-bottom: 10px;"><strong>手动加载</strong></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;">在每次get key的时候指定一个同步的函数,如果key不存在就调用这个函数生成一个值。</span></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-right: auto;margin-left: auto;outline: 0px;max-width: 100%;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);font-size: 14px;text-align: left;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;box-sizing: border-box !important;word-wrap: break-word !important;"><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background-color: rgb(30, 30, 30);border-top-left-radius: 5px;border-top-right-radius: 5px;border-bottom-right-radius: 5px;border-bottom-left-radius: 5px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">/**<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> * 手动加载<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> * <span style="outline: 0px;max-width: 100%;color: rgb(96, 139, 78);line-height: 26px;">@param</span> key<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> * <span style="outline: 0px;max-width: 100%;color: rgb(96, 139, 78);line-height: 26px;">@return</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> */</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;">public</span> Object <span style="outline: 0px;max-width: 100%;line-height: 26px;">manulOperator(String key)</span> </span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> Cache<String, Object> cache = Caffeine.newBuilder()<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> .expireAfterWrite(<span style="outline: 0px;max-width: 100%;color: rgb(184, 215, 163);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">1</span>, TimeUnit.SECONDS)<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> .expireAfterAccess(<span style="outline: 0px;max-width: 100%;color: rgb(184, 215, 163);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">1</span>, TimeUnit.SECONDS)<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> .maximumSize(<span style="outline: 0px;max-width: 100%;color: rgb(184, 215, 163);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">10</span>)<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> .build();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">//如果一个key不存在,那么会进入指定的函数生成value</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> Object value = cache.get(key, t -> setValue(key).apply(key));<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> cache.put(<span style="outline: 0px;max-width: 100%;color: rgb(214, 157, 133);line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">"hello"</span>,value);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">//判断是否存在如果不存返回null</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> Object ifPresent = cache.getIfPresent(key);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;word-wrap: break-word !important;">//移除一个key</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> cache.invalidate(key);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">  
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">今天给大家分享个生产事故,一个由于MySQL分页导致的线上事故,事情是这样的~</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">背景</span><span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">一天晚上10点半,下班后愉快的坐在在回家的地铁上,心里想着周末的生活怎么安排。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">突然电话响了起来,一看是我们的一个运维同学,顿时紧张了起来,本周的版本已经发布过了,这时候打电话一般来说是线上出问题了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">果然,沟通的情况是线上的一个查询数据的接口被疯狂的失去理智般的调用,这个操作直接导致线上的MySql集群被拖慢了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">好吧,这问题算是严重了,匆匆赶到家后打开电脑,跟同事把Pinpoint上的慢查询日志捞出来。看到一个很奇怪的查询,如下</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">1 POST domain/v1.0/module/method?order=condition&orderType=desc&offset=1800000&limit=500<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">domain、module 和 method 都是化名,代表接口的域、模块和实例方法名,后面的offset和limit代表<span style="font-weight: 700;color: rgb(248, 57, 41);">分页操作</span>的<span style="font-weight: 700;color: rgb(248, 57, 41);">偏移量</span>和每页的<span style="font-weight: 700;color: rgb(248, 57, 41);">数量</span>,也就是说该同学是在 翻第(1800000/500+1=3601)页。初步捞了一下日志,发现 有8000多次这样调用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这太神奇了,而且我们页面上的分页单页数量也不是500,而是 25条每页,这个绝对不是人为的在功能页面上进行一页一页的翻页操作,而是数据被刷了(说明下,我们生产环境数据有1亿+)。详细对比日志发现,很多分页的时间是重叠的,对方应该是多线程调用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">通过对鉴权的Token的分析,基本定位了请求是来自一个叫做ApiAutotest的客户端程序在做这个操作,也定位了生成鉴权Token的账号来自一个QA的同学。立马打电话给同学,进行了沟通和处理。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">分析</span><span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">其实对于我们的MySQL查询语句来说,整体效率还是可以的,该有的联表查询优化都有,该简略的查询内容也有,关键条件字段和排序字段该有的索引也都在,问题在于他一页一页的分页去查询,查到越后面的页数,扫描到的数据越多,也就越慢。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们在查看前几页的时候,发现速度非常快,比如 limit 200,25,瞬间就出来了。但是越往后,速度就越慢,特别是百万条之后,卡到不行,那这个是什么原理呢。先看一下我们翻页翻到后面时,查询的sql是怎样的:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">1 select * from t_name <span style="color: #c18401;line-height: 26px;">where</span> c_name1=<span style="color: #50a14f;line-height: 26px;">'xxx'</span> order by c_name2 <span style="color: #c18401;line-height: 26px;">limit</span> 2000000,25;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种查询的慢,其实是因为limit后面的偏移量太大导致的。比如像上面的 limit 2000000,25 ,这个等同于数据库要扫描出 2000025条数据,然后再丢弃前面的 20000000条数据,返回剩下25条数据给用户,这种取法明显不合理。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.6595744680851063" src="/upload/715928eedac10523c130fc0a644c6b0e.png" data-type="png" data-w="1034" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> image-20220421082735727 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">大家翻看《高性能MySQL》第六章:查询性能优化,对这个问题有过说明:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">分页操作通常会使用limit加上偏移量的办法实现,同时再加上合适的order by子句。但这会出现一个常见问题:当偏移量非常大的时候,它会导致MySQL扫描大量不需要的行然后再抛弃掉。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">数据模拟</span><span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">那好,了解了问题的原理,那就要试着解决它了。涉及数据敏感性,我们这边模拟一下这种情况,构造一些数据来做测试。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">1、创建两个表:员工表和部门表</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*部门表,存在则进行删除 */</span><br><span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">table</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> dep;<br><span style="color: #a626a4;line-height: 26px;">create</span> <span style="color: #a626a4;line-height: 26px;">table</span> dep(<br> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #c18401;line-height: 26px;">int</span> <span style="color: #a626a4;line-height: 26px;">unsigned</span> primary <span style="color: #a626a4;line-height: 26px;">key</span> auto_increment,<br> depno mediumint <span style="color: #a626a4;line-height: 26px;">unsigned</span> <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #986801;line-height: 26px;">0</span>,<br> depname <span style="color: #c18401;line-height: 26px;">varchar</span>(<span style="color: #986801;line-height: 26px;">20</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #50a14f;line-height: 26px;">""</span>,<br> memo <span style="color: #c18401;line-height: 26px;">varchar</span>(<span style="color: #986801;line-height: 26px;">200</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #50a14f;line-height: 26px;">""</span><br>);<br><br><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*员工表,存在则进行删除*/</span><br><span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">table</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> emp;<br><span style="color: #a626a4;line-height: 26px;">create</span> <span style="color: #a626a4;line-height: 26px;">table</span> emp(<br> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #c18401;line-height: 26px;">int</span> <span style="color: #a626a4;line-height: 26px;">unsigned</span> primary <span style="color: #a626a4;line-height: 26px;">key</span> auto_increment,<br> empno mediumint <span style="color: #a626a4;line-height: 26px;">unsigned</span> <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #986801;line-height: 26px;">0</span>,<br> empname <span style="color: #c18401;line-height: 26px;">varchar</span>(<span style="color: #986801;line-height: 26px;">20</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #50a14f;line-height: 26px;">""</span>,<br> job <span style="color: #c18401;line-height: 26px;">varchar</span>(<span style="color: #986801;line-height: 26px;">9</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #50a14f;line-height: 26px;">""</span>,<br> mgr mediumint <span style="color: #a626a4;line-height: 26px;">unsigned</span> <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #986801;line-height: 26px;">0</span>,<br> hiredate datetime <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span>,<br> sal <span style="color: #c18401;line-height: 26px;">decimal</span>(<span style="color: #986801;line-height: 26px;">7</span>,<span style="color: #986801;line-height: 26px;">2</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span>,<br> comn <span style="color: #c18401;line-height: 26px;">decimal</span>(<span style="color: #986801;line-height: 26px;">7</span>,<span style="color: #986801;line-height: 26px;">2</span>) <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span>,<br> depno mediumint <span style="color: #a626a4;line-height: 26px;">unsigned</span> <span style="color: #a626a4;line-height: 26px;">not</span> <span style="color: #0184bb;line-height: 26px;">null</span> <span style="color: #a626a4;line-height: 26px;">default</span> <span style="color: #986801;line-height: 26px;">0</span><br>);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">2、创建两个函数:生成随机字符串和随机编号</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/* 产生随机字符串的函数*/</span><br>DELIMITER $ <br><span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">FUNCTION</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> rand_string;<br><span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">FUNCTION</span> rand_string(n <span style="color: #c18401;line-height: 26px;">INT</span>) <span style="color: #a626a4;line-height: 26px;">RETURNS</span> <span style="color: #c18401;line-height: 26px;">VARCHAR</span>(<span style="color: #986801;line-height: 26px;">255</span>)<br><span style="color: #a626a4;line-height: 26px;">BEGIN</span><br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> chars_str <span style="color: #c18401;line-height: 26px;">VARCHAR</span>(<span style="color: #986801;line-height: 26px;">100</span>) <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #50a14f;line-height: 26px;">'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'</span>;<br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> return_str <span style="color: #c18401;line-height: 26px;">VARCHAR</span>(<span style="color: #986801;line-height: 26px;">255</span>) <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #50a14f;line-height: 26px;">''</span>;<br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> i <span style="color: #c18401;line-height: 26px;">INT</span> <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #986801;line-height: 26px;">0</span>;<br> WHILE i < n <span style="color: #a626a4;line-height: 26px;">DO</span><br> <span style="color: #a626a4;line-height: 26px;">SET</span> return_str = <span style="color: #a626a4;line-height: 26px;">CONCAT</span>(return_str,<span style="color: #a626a4;line-height: 26px;">SUBSTRING</span>(chars_str,<span style="color: #a626a4;line-height: 26px;">FLOOR</span>(<span style="color: #986801;line-height: 26px;">1</span>+<span style="color: #a626a4;line-height: 26px;">RAND</span>()*<span style="color: #986801;line-height: 26px;">52</span>),<span style="color: #986801;line-height: 26px;">1</span>));<br> <span style="color: #a626a4;line-height: 26px;">SET</span> i = i+<span style="color: #986801;line-height: 26px;">1</span>;<br> <span style="color: #a626a4;line-height: 26px;">END</span> <span style="color: #a626a4;line-height: 26px;">WHILE</span>;<br> RETURN return_str;<br><span style="color: #a626a4;line-height: 26px;">END</span> $<br>DELIMITER;<br><br><br><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*产生随机部门编号的函数*/</span><br>DELIMITER $ <br><span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">FUNCTION</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> rand_num;<br><span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">FUNCTION</span> rand_num() <span style="color: #a626a4;line-height: 26px;">RETURNS</span> <span style="color: #c18401;line-height: 26px;">INT</span>(<span style="color: #986801;line-height: 26px;">5</span>)<br><span style="color: #a626a4;line-height: 26px;">BEGIN</span><br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> i <span style="color: #c18401;line-height: 26px;">INT</span> <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #986801;line-height: 26px;">0</span>;<br> <span style="color: #a626a4;line-height: 26px;">SET</span> i = <span style="color: #a626a4;line-height: 26px;">FLOOR</span>(<span style="color: #986801;line-height: 26px;">100</span>+<span style="color: #a626a4;line-height: 26px;">RAND</span>()*<span style="color: #986801;line-height: 26px;">10</span>);<br> RETURN i;<br><span style="color: #a626a4;line-height: 26px;">END</span> $<br>DELIMITER;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">3、编写存储过程,模拟500W的员工数据</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*建立存储过程:往emp表中插入数据*/</span><br> DELIMITER $<br> <span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">PROCEDURE</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> insert_emp;<br> <span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">PROCEDURE</span> insert_emp(<span style="color: #a626a4;line-height: 26px;">IN</span> <span style="color: #a626a4;line-height: 26px;">START</span> <span style="color: #c18401;line-height: 26px;">INT</span>(<span style="color: #986801;line-height: 26px;">10</span>),<span style="color: #a626a4;line-height: 26px;">IN</span> max_num <span style="color: #c18401;line-height: 26px;">INT</span>(<span style="color: #986801;line-height: 26px;">10</span>))<br> <span style="color: #a626a4;line-height: 26px;">BEGIN</span><br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> i <span style="color: #c18401;line-height: 26px;">INT</span> <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #986801;line-height: 26px;">0</span>;<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*set autocommit =0 把autocommit设置成0,把默认提交关闭*/</span><br> <span style="color: #a626a4;line-height: 26px;">SET</span> autocommit = <span style="color: #986801;line-height: 26px;">0</span>;<br> REPEAT<br> <span style="color: #a626a4;line-height: 26px;">SET</span> i = i + <span style="color: #986801;line-height: 26px;">1</span>;<br> <span style="color: #a626a4;line-height: 26px;">INSERT</span> <span style="color: #a626a4;line-height: 26px;">INTO</span> emp(empno,empname,job,mgr,hiredate,sal,comn,depno) <span style="color: #a626a4;line-height: 26px;">VALUES</span> ((<span style="color: #a626a4;line-height: 26px;">START</span>+i),rand_string(<span style="color: #986801;line-height: 26px;">6</span>),<span style="color: #50a14f;line-height: 26px;">'SALEMAN'</span>,<span style="color: #986801;line-height: 26px;">0001</span>,<span style="color: #a626a4;line-height: 26px;">now</span>(),<span style="color: #986801;line-height: 26px;">2000</span>,<span style="color: #986801;line-height: 26px;">400</span>,rand_num());<br> UNTIL i = max_num<br> <span style="color: #a626a4;line-height: 26px;">END</span> <span style="color: #a626a4;line-height: 26px;">REPEAT</span>;<br> <span style="color: #a626a4;line-height: 26px;">COMMIT</span>;<br> <span style="color: #a626a4;line-height: 26px;">END</span> $<br> DELIMITER;<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*插入500W条数据*/</span><br> <span style="color: #a626a4;line-height: 26px;">call</span> insert_emp(<span style="color: #986801;line-height: 26px;">0</span>,<span style="color: #986801;line-height: 26px;">5000000</span>);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">4、编写存储过程,模拟120的部门数据</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*建立存储过程:往dep表中插入数据*/</span><br> DELIMITER $<br> <span style="color: #a626a4;line-height: 26px;">drop</span> <span style="color: #a626a4;line-height: 26px;">PROCEDURE</span> <span style="color: #a626a4;line-height: 26px;">if</span> <span style="color: #a626a4;line-height: 26px;">EXISTS</span> insert_dept;<br> <span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">PROCEDURE</span> insert_dept(<span style="color: #a626a4;line-height: 26px;">IN</span> <span style="color: #a626a4;line-height: 26px;">START</span> <span style="color: #c18401;line-height: 26px;">INT</span>(<span style="color: #986801;line-height: 26px;">10</span>),<span style="color: #a626a4;line-height: 26px;">IN</span> max_num <span style="color: #c18401;line-height: 26px;">INT</span>(<span style="color: #986801;line-height: 26px;">10</span>))<br> <span style="color: #a626a4;line-height: 26px;">BEGIN</span><br> <span style="color: #a626a4;line-height: 26px;">DECLARE</span> i <span style="color: #c18401;line-height: 26px;">INT</span> <span style="color: #a626a4;line-height: 26px;">DEFAULT</span> <span style="color: #986801;line-height: 26px;">0</span>;<br> <span style="color: #a626a4;line-height: 26px;">SET</span> autocommit = <span style="color: #986801;line-height: 26px;">0</span>;<br> REPEAT<br> <span style="color: #a626a4;line-height: 26px;">SET</span> i = i+<span style="color: #986801;line-height: 26px;">1</span>;<br> <span style="color: #a626a4;line-height: 26px;">INSERT</span> <span style="color: #a626a4;line-height: 26px;">INTO</span> dep( depno,depname,memo) <span style="color: #a626a4;line-height: 26px;">VALUES</span>((<span style="color: #a626a4;line-height: 26px;">START</span>+i),rand_string(<span style="color: #986801;line-height: 26px;">10</span>),rand_string(<span style="color: #986801;line-height: 26px;">8</span>));<br> UNTIL i = max_num<br> <span style="color: #a626a4;line-height: 26px;">END</span> <span style="color: #a626a4;line-height: 26px;">REPEAT</span>;<br> <span style="color: #a626a4;line-height: 26px;">COMMIT</span>;<br> <span style="color: #a626a4;line-height: 26px;">END</span> $<br> DELIMITER;<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*插入120条数据*/</span><br> <span style="color: #a626a4;line-height: 26px;">call</span> insert_dept(<span style="color: #986801;line-height: 26px;">1</span>,<span style="color: #986801;line-height: 26px;">120</span>);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">5、建立关键字段的索引,这边是跑完数据之后再建索引,会导致建索引耗时长,但是跑数据就会快一些。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*建立关键字段的索引:排序、条件*/</span><br><span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">INDEX</span> idx_emp_id <span style="color: #a626a4;line-height: 26px;">ON</span> emp(<span style="color: #a626a4;line-height: 26px;">id</span>);<br><span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">INDEX</span> idx_emp_depno <span style="color: #a626a4;line-height: 26px;">ON</span> emp(depno);<br><span style="color: #a626a4;line-height: 26px;">CREATE</span> <span style="color: #a626a4;line-height: 26px;">INDEX</span> idx_dep_depno <span style="color: #a626a4;line-height: 26px;">ON</span> dep(depno); <br></code></pre> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">测试</span><span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">测试数据</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*偏移量为100,取25*/</span><br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">desc</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">100</span>,<span style="color: #986801;line-height: 26px;">25</span>;<br><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*偏移量为4800000,取25*/</span><br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">desc</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">4800000</span>,<span style="color: #986801;line-height: 26px;">25</span>; <br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">执行结果</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">[SQL]<br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">desc</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">100</span>,<span style="color: #986801;line-height: 26px;">25</span>;<br>受影响的行: 0<br>时间: 0.001s<br>[SQL]<br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">desc</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">4800000</span>,<span style="color: #986801;line-height: 26px;">25</span>;<br>受影响的行: 0<br>时间: 12.275s<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">因为扫描的数据多,所以这个明显不是一个量级上的耗时。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">解决方案</span><span></span></h2> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span><span>1、使用索引覆盖+子查询优化</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">因为我们有主键id,并且在上面建了索引,所以可以先在索引树中找到开始位置的 id值,再根据找到的id值查询行数据。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*子查询获取偏移100条的位置的id,在这个位置上往后取25*/</span><br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id >= (<span style="color: #a626a4;line-height: 26px;">select</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">from</span> emp <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">100</span>,<span style="color: #986801;line-height: 26px;">1</span>)<br> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br> <br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*子查询获取偏移4800000条的位置的id,在这个位置上往后取25*/</span><br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id >= (<span style="color: #a626a4;line-height: 26px;">select</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">from</span> emp <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">4800000</span>,<span style="color: #986801;line-height: 26px;">1</span>)<br> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">执行结果</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">执行效率相比之前有大幅的提升:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"> [SQL]<br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id >= (<span style="color: #a626a4;line-height: 26px;">select</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">from</span> emp <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">100</span>,<span style="color: #986801;line-height: 26px;">1</span>)<br> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br> 受影响的行: 0<br> 时间: 0.106s<br> <br> [SQL]<br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id >= (<span style="color: #a626a4;line-height: 26px;">select</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">from</span> emp <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> <span style="color: #a626a4;line-height: 26px;">id</span> <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">4800000</span>,<span style="color: #986801;line-height: 26px;">1</span>)<br> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br> 受影响的行: 0<br> 时间: 1.541s <br></code></pre> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span><span>2、起始位置重定义</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">记住上次查找结果的主键位置,避免使用偏移量 offset</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*记住了上次的分页的最后一条数据的id是100,这边就直接跳过100,从101开始扫描表*/</span><br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id > <span style="color: #986801;line-height: 26px;">100</span> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br> <br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/*记住了上次的分页的最后一条数据的id是4800000,这边就直接跳过4800000,从4800001开始扫描表*/</span><br> <span style="color: #a626a4;line-height: 26px;">SELECT</span> a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br> <span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br> <span style="color: #a626a4;line-height: 26px;">where</span> a.id > <span style="color: #986801;line-height: 26px;">4800000</span><br> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">执行结果</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">[SQL]<br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br><span style="color: #a626a4;line-height: 26px;">where</span> a.id > <span style="color: #986801;line-height: 26px;">100</span> <span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br>受影响的行: 0<br>时间: 0.001s<br> <br>[SQL]<br><span style="color: #a626a4;line-height: 26px;">SELECT</span> a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname<br><span style="color: #a626a4;line-height: 26px;">from</span> emp a <span style="color: #a626a4;line-height: 26px;">left</span> <span style="color: #a626a4;line-height: 26px;">join</span> dep b <span style="color: #a626a4;line-height: 26px;">on</span> a.depno = b.depno<br><span style="color: #a626a4;line-height: 26px;">where</span> a.id > <span style="color: #986801;line-height: 26px;">4800000</span><br><span style="color: #a626a4;line-height: 26px;">order</span> <span style="color: #a626a4;line-height: 26px;">by</span> a.id <span style="color: #a626a4;line-height: 26px;">limit</span> <span style="color: #986801;line-height: 26px;">25</span>;<br>受影响的行: 0<br>时间: 0.000s <br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个效率是最好的,无论怎么分页,耗时基本都是一致的,因为他执行完条件之后,都只扫描了25条数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">但是有个问题,只适合一页一页的分页,这样才能记住前一个分页的最后Id。如果用户跳着分页就有问题了,比如刚刚刷完第25页,马上跳到35页,数据就会不对。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种的适合场景是类似百度搜索或者腾讯新闻那种滚轮往下拉,不断拉取不断加载的情况。这种延迟加载会保证数据不会跳跃着获取。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span><span>3、降级策略</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">看了网上一个阿里的dba同学分享的方案:配置limit的偏移量和获取数一个最大值,超过这个最大值,就返回空数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">因为他觉得超过这个值你已经不是在分页了,而是在刷数据了,如果确认要找数据,应该输入合适条件来缩小范围,而不是一页一页分页。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个跟我同事的想法大致一样:request的时候 如果offset大于某个数值就先返回一个4xx的错误。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">小结</span><span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">当晚我们应用上述第三个方案,对offset做一下限流,超过某个值,就返回空值。第二天使用第一种和第二种配合使用的方案对程序和数据库脚本进一步做了优化。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">合理来说做任何功能都应该考虑极端情况,设计容量都应该涵盖极端边界测试。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">另外,该有的限流、降级也应该考虑进去。比如工具多线程调用,在短时间频率内8000次调用,可以使用计数服务判断并反馈用户调用过于频繁,直接给予断掉。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">哎,大意了啊,搞了半夜,QA同学不讲武德。</p> </section>
作者:微信小助手
<p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);"><strong>常用类概述:</strong></p> <ol style="padding-left: 40px;color: rgb(35, 38, 59);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-size: 15.5px;text-align: left;background-color: rgba(255, 255, 255, 0.9);" class="list-paddingleft-1"> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">内部类</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">Object类</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">包装类</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">数学类</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">时间类</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">字符串</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">String Builder和StringBuffer</p></li> <li style="margin-bottom: 0.5em;list-style: decimal;"><p style="margin: 10px auto;">DecimalFormat</p></li> </ol> <h2 tid="tid-njBzhi" style="margin-top: 10px;margin-bottom: 10px;font-size: 21px;font-weight: bold;line-height: 1.5;color: rgb(35, 38, 59);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;text-align: left;background-color: rgba(255, 255, 255, 0.9);"><br></h2> <p style="outline: 0px;letter-spacing: 0.544px;background: rgb(255, 255, 255);text-align: center;font-size: 14px;font-family: Calibri, sans-serif;color: rgb(0, 0, 0);line-height: 28px;"><img class="rich_pages wxw-img" data-ratio="0.9900990099009901" data-s="300,640" data-type="png" data-w="101" style="outline: 0px;letter-spacing: 0.544px;color: rgb(51, 51, 51);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;box-sizing: border-box !important;visibility: visible !important;width: 39px !important;height: auto !important;" src="/upload/aae6600a288d838d113c0d9ec611c195.png"><br style="outline: 0px;"></p> <p style="margin-right: 16px;margin-left: 16px;outline: 0px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-stretch: normal;font-family: "PingFang SC";color: rgb(0, 0, 0);text-align: center;line-height: 1.75em;"><span style="outline: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;"><strong style="outline: 0px;color: rgb(4, 181, 107);"><strong style="outline: 0px;font-size: 16px;">- </strong><strong style="outline: 0px;font-size: 15px;">一、内部类</strong><strong style="outline: 0px;"><span style="outline: 0px;font-size: 16px;"> -</span></strong></strong></span></p> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);"><strong>概念</strong>:在一个类内部再定义一个完整的类。</p> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);">一般情况下类与类之间是相互独立的,内部类的意思就是打破这种独立思想,让一个类成为另一个类的内部信息,和成员变量、成员方法同等级别。</p> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);"><strong>内部类的好处:</strong></p> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);">把一个类写在外面和写在里面最终达到的结果都一样,那我们为什么还要使用内部类,岂不是多此一举吗?</p> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);"><strong>采用内部类这种技术,可以隐藏细节和内部结构,封装性更好,让程序的结构更加合理!如果类很多且都暴露在外面,那么类与类之间的调用就会十分繁琐!</strong></p> <h3 tid="tid-XnFaCd" style="margin-top: 10px;margin-bottom: 10px;font-weight: bold;line-height: 1.5;color: rgb(35, 38, 59);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;text-align: left;background-color: rgba(255, 255, 255, 0.9);">内部类的分类:</h3> <h3 tid="tid-MGJXXB" style="margin-top: 10px;margin-bottom: 10px;font-weight: bold;line-height: 1.5;color: rgb(35, 38, 59);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;text-align: left;background-color: rgba(255, 255, 255, 0.9);">1.成员内部类(非静态内部类)</h3> <p style="margin: 13px auto;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;letter-spacing: 0.015em;font-feature-settings: "tnum";font-variant-numeric: tabular-nums;font-variant-east-asian: normal;line-height: 1.8;word-break: break-word;color: rgb(35, 38, 59);text-align: left;background-color: rgba(255, 255, 255, 0.9);">【参考代码】</p> <p> <code-box style="margin: 5px;display: block;border-radius: 4px;box-shadow: rgba(37, 44, 97, 0.15) 0px 4px 11px -2px, rgba(93, 100, 148, 0.06) 0px 1px 3px 0px;color: rgb(35, 38, 59);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-size: 15.5px;text-align: left;background-color: rgba(255, 255, 255, 0.9);"></code-box></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/1gvL9ficRs1GibnrTz1DwbL0gBoEDoEtoIEVguf8ic6OicoUssialFIZbicoo7Yxk8msF71QyOvKIzB8n67r4IPRr6sFF4LperFBHp/640?wx_fmt=svg&random=0.5784664163446418") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">package NeiBuLei;<br><br>public class OuterClass {<br> //成员变量<br> private String OuterName;<br> //成员方法<br> public void <span style="line-height: 26px;"><span style="color: #61aeee;line-height: 26px;">display</span></span>(){<br> System.out.println(<span style="color: #98c379;line-height: 26px;">"这是外部类方法!"</span>);<br> System.out.println(OuterName);<br> }<br> //内部类<br> public class InnerClass{<br> //成员变量<br> private String InnerNme;<br> //构造方法<br> public <span style="line-height: 26px;"><span style="color: #61aeee;line-height: 26px;">InnerClass</span></span>() {<br> InnerNme = <span style="color: #98c379;line-height: 26px;">"Inner Class"</span>;<br> }<br> //成员方法<br> public void <span style="line-height: 26px;"><span style="color: #61aeee;line-height: 26px;">display</span></span>(){<br> System.out.println(<span style="color: #98c379;line-height: 26px;">"这是内部类方法!"</span>);<br> System.out.println(InnerNme);<br> }<br> }<br> // 主方法<br> public static void main(String[] args) {<br> OuterClass outerClass = new OuterClass();<br> outerClass.display();//这是外部类方法!null<br><br> // 这个类是内部类,已经不是独立的类了,因此不能像外部类一样直接创建!<br> //InnerClass innerClass = new InnerClass(); 行不通<br> OuterClass.InnerClass innerClass = outerClass.new InnerClass();// 同成员方法/变量 只是加了个前缀<br>
作者:微信小助手
<section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;" data-mpa-powered-by="yiban.io"> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <p><img class="rich_pages wxw-img" data-ratio="0.7655529953917051" src="/upload/fb5ced34303bbdd530013f9251531e64.png" data-type="png" data-w="6944" style="color: inherit;font-size: inherit;letter-spacing: 0px;"><br></p> <section> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">项目地址: https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//github.com/fanux/sealos</span><br>参考地址: https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//fuckcloudnative.io/posts/sealos/</span><br>https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//www.sealyun.com/goodsDetail?type=cloud_kernel&name=kubernetes</span><br>官方教程: https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//www.sealyun.com/instructions/2</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">安装前提条件(k8s官方不支持Rhel8系列)</span></h4> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">!!!!高能警告:Rhel8,Centos8和Rocky8预装了podman和nftables,而nftables和kube-proxy不兼容,Rhel8系列安装k8s不能正常工作.建议使用Centos7(升级内核到5.4以上) 或Ubuntu.</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">issue提了快2年了,我看估计是没戏了。https://github.com/kubernetes/kubernetes/pull/97070</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">高版本离线包自带docker/containerd,如没安装docker/containerd会自动安装.1.22版本以上强制安装containerd,要求卸载docker.</p> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">安装前的注意事项</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Linux系统配置好主机名和IP地址,主机间配置ssh免密登录,无需更多配置<br>下载kubernetes 离线安装包.<br>下载最新版本sealos.<br>务必同步服务器时间<br>主机名不可重复<br>master节点CPU必须2C以上<br>请使用sealos 3.2.0以上版本<br>网卡名称如果是不常见的,建议修改成规范的网卡名称, 如(eth.|en.|em.*)<br>cni组件选择cilium时要求内核版本不低于5.4<br>podSubnet: 100.64.0.0/10<br>serviceSubnet: 10.96.0.0/12<br>继10.0.0.0/8、172.16.0.12、192.168.0.0/16之后又诞生了第四个私有IPv4地址,但100.64.0.0/10是在服务商网络内,不同之处在于只使用。<br>100.64.0.0/10,Shared address space,是预留给ISP运营商做NAT用的。ISP运营商设备给用户分配100.64.0.0/10内的IP,然后再在运营商设备上进行NAT,转换成公网IP。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><img class="rich_pages wxw-img" data-ratio="0.42476060191518467" src="/upload/ff3b0698ac67e93567fa42143c53a34d.png" data-type="png" data-w="2924"></p> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">快速二进制包安装k8s高可用集群</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">不要指定网卡参数 --network,会导致cni启动不了<br>生产环境只建议安装次新版!!!</p> <h5 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">下载并安装sealos, sealos是个golang的二进制工具,直接下载拷贝到bin目录即可, release页面也可下载</span></h5> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">wget</span> -c https://sealyun-home.oss-cn-beijing.aliyuncs.com/sealos/latest/sealos && \<br> chmod +x sealos && mv sealos /usr/bin<br></code></pre> <h5 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">下载离线资源包</span></h5> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">wget</span> -c https://sealyun.oss-cn-beijing.aliyuncs.com/05a3db657821277f5f3b92d834bbaf98-v1.22.0/kube1.22.0.tar.gz<br></code></pre> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">安装一个三master的kubernetes集群</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">##### 如已设ssh免密登录可以不需要--passwd参数</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">##### --podcidr 配置pod网段</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">##### --svccidr 配置clusterip网段</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">##### --network 机器网卡名,CNI网卡发现用</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> init --master <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168.32.200</span> --master <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168.32.202</span> --node <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168.32.221</span> --pkg-url /root/kube1.<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">22</span>.<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">7</span>.tar.gz --version v1.<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">22</span>.<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">7</span> --podcidr <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">10.244.0.0</span>/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">16</span> --svccidr <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">10.93.0.0</span>/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">12</span><br></code></pre> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">安装单master的k8s集群</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">sealos init \<br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--master 192.168.0.2 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--node 192.168.0.12 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--pkg-url /root/kube1.22.0.tar.gz \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--version v1.22.0</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">安装日志<br>安装日志所在位置~/.sealos/sealos.log</p> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">自定义网络</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">pod的ip地址段,也称为cidr<br><br>podcidr 参数指定自定义pod网段 如 <br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--podcidr 10.244.0.0/16 \</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#### svccidr 参数指定clusterip网段 如 </span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--svccidr 10.93.0.0/12 \</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#### 不安装cni插件</span><br>without-cni sealos自带calico网络,如果你想自己装CNI不用默认可加此参数, 如 <br><br>sealos init <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--without-cni …</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#### 自定义cni插件</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">-- network flannel</span><br></code></pre> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">添加证书</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#需要添加证书, 在init的时候指定--cert-sans 域名即可</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#证书有效期是99年</span><br><br>sealos init <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--cert-sans 域名 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--master 192.168.0.2 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--node 192.168.0.12 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--pkg-url /root/kube1.22.0.tar.gz \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--version v1.22.0</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--podcidr 10.244.0.0/16 \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--svccidr 10.93.0.0/12 \</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">参数注释</span></h4> <p><span style="font-size: inherit;color: inherit;line-height: inherit;"><span style="color: rgb(77, 77, 77);font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-size: 16px;font-variant-ligatures: no-common-ligatures;text-align: start;background-color: rgb(255, 255, 255);">详细参数: </span>https://www.sealyun.com/instructions/2</span></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.26619433198380565" data-s="300,640" src="/upload/ab768df92ed0b9abdf3fbb2ebaba4f48.png" data-type="png" data-w="988" style=""></p> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">节点操作</span></h3> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">增加master</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">join</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.7</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">join</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6-192</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.9</span> # 或者多个连续<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">IP</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">增加node</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">join</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.7</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">join</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6-192</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.9</span> # 或者多个连续<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">IP</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">删除指定master节点</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">clean</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.7</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">clean</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--master</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6-192</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.9</span> # 或者多个连续<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">IP</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">删除指定node节点</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">clean</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.7</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">clean</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">--node</span> 192<span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.6-192</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.168</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">.9</span> # 或者多个连续<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">IP</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">清理集群</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#注意clean不加任何参数会清理整个集群,等同于sealos clean --all</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">sealos</span> clean --<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">all</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">备份集群</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 查看备份帮助</span><br>sealos etcd save -h<br><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">##本地备份</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#本地备份, 默认保存在/opt/sealos/ectd-backup这个目录, 默认名称为sanpshot</span><br>sealos etcd save<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#本地备份并复制到各master节点。增加--docker参数, 默认在生成的文件下添加当前的uinx时间戳</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#然后复制到各master节点</span><br><br>sealos etcd save <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--docker</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">####备份上传到阿里云oss</span><br><br>备份上传至oss,首次执行带命令行或者编辑~/.sealos/config.yaml<br><br>sealos etcd save <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--docker \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--aliId youraliyunkeyid \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--aliKey youraliyunkeysecrets \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--ep oss-cn-hangzhou.aliyuncs.com \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--bucket etcdbackup \</span><br> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">--objectPath /sealos/ </span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">升级k8s版本</span></h4> <p>参考: https://www.sealyun.com/instructions/5</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">#升级前注意事项:</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">#确保集群是健康状态</span><br><br>kubectl <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">get</span> nodes -owid<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">#确保kube-system下的pod运行正常</span><br><br>kubectl <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">get</span> pod -n kube-system -owide<br><br><br>#执行升级<br>#版本必须要大于等于<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">1.18</span><span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.0</span>,才可升级<br>#执行升级前提前下载好新版本的离线安装包<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;"># 升级到1.19.2版本</span><br>sealos upgrade --version v1<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.19</span><span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.2</span> --pkg-url /root/kube1<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.19</span><span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.2</span>.tar.gz -f | tee -a upgrade<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">.1183</span><span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">-1192.</span>log <br></code></pre> <h3 style="line-height: inherit;margin-top: 1.5em;font-weight: bold;font-size: 1.3em;margin-bottom: 2em;margin-right: 5px;padding: 8px 15px;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;"><span style="font-size: inherit;color: inherit;line-height: inherit;">containerd镜像和容器管理</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="white-space:pre-wrap;color: rgb(169, 183, 198);font-family: Consolas, Inconsolata, Courier, monospace;font-size: 14px;background-color: rgb(40, 43, 46);">nerdctl用法参考: </span></code><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="white-space:pre-wrap;color: rgb(169, 183, 198);font-family: Consolas, Inconsolata, Courier, monospace;font-size: 14px;background-color: rgb(40, 43, 46);">https:</span><span style="white-space:pre-wrap;color: inherit;font-family: Consolas, Inconsolata, Courier, monospace;font-size: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//mdnice</span><span style="white-space:pre-wrap;color: rgb(169, 183, 198);font-family: Consolas, Inconsolata, Courier, monospace;font-size: 14px;background-color: rgb(40, 43, 46);">.com/writing/c57c45c557b</span><span style="white-space:pre-wrap;color: rgb(169, 183, 198);font-family: Consolas, Inconsolata, Courier, monospace;font-size: 14px;background-color: rgb(40, 43, 46);">f46b0835958134892abc4</span></code><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">官方工具是crictl,但是更推荐使用nerdctl.和docker官方语法几乎完全一致.<br>也可以使用alias将nerdctl设别名为docker.<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># nerdctl要加上-n=k8s.io</span><br>nerdctl -n=k8s.io images<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 配置nerdctl自动补全</span><br>source <(nerdctl completion bash)<br>echo <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'source <(nerdctl completion bash)'</span> >>~<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/.bashrc<br><br># 设置alias别名为docker<br>echo "alias docker='nerdctl -n=k8s.io'" >>~/</span>.bashrc<br>source .bashrc<br><br><br>使用nerdctl打包docker镜像<br>参考: https:<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//mp</span>.weixin.qq.com/<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">s/Bjn0s5qRh2H9I__mAYh4jg<br><br><br>nerdctl使用方法<br>参考: https://mp</span>.weixin.qq.com/<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">s/vs_XIn-cpEXtWoF8Yb9vRw<br><br><br>containerd配置代理<br>老是替换源太麻烦了,直接上代理<br>https://segmentfault</span>.com/a/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">1190000020363043</span><br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 创建/etc/systemd/system/containerd.service.d目录</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">mkdir</span> /etc/systemd/<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">system</span>/containerd.service.d<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 配置代理</span><br>cat > <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/etc/systemd</span><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/system/containerd</span>.service.d/proxy.conf << EOF<br>> [Service] <br>> Environment=<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"HTTP_PROXY=socks5://127.0.0.1:1080"</span> <br>> Environment=<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"HTTPS_PROXY=socks5://127.0.0.1:1080"</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"NO_PROXY=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,docker-registry.somecorporation.com,isdp30x2.mirror.aliyuncs.com,hub-mirror.c.163.com,mirror.baidubce.com"</span><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'<br>> EOF<br><br># 重启containerd服务<br>systemctl daemon-reload<br>systemctl restart containerd<br><br># 查看配置的代理<br>systemctl show --property=Environment containerd.service <br></span></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">containerd配置代理ansible剧本</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">---<br>- hosts: all<br> tasks:<br> - name: 创建containerd.service.d目录<br> file:<br> path: <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/etc/</span>systemd/system/containerd.service.d<br> state: directory<br><br> - name: 创建proxy.conf文件<br> file:<br> path: <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/etc/</span>systemd/system/containerd.service.d/proxy.conf<br> state: touch<br><br> - name: 为http_proxy.conf文件添加配置信息<br> copy:<br> content: |<br> [Service]<br> Environment=<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"HTTP_PROXY=socks5://127.0.0.1:1080"</span> <br> Environment=<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"HTTPS_PROXY=socks5://127.0.0.1:1080"</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"NO_PROXY=localhost,127.0.0.1,docker-registry.somecorporation.com,isdp30x2.mirror.aliyuncs.com,hub-mirror.c.163.com,mirror.baidubce.com"</span><br> dest: <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">/etc/</span>systemd/system/containerd.service.d/proxy.conf<br> notify: 重启containerd服务<br><br> handlers:<br> - name: 重启containerd服务<br> systemd:<br> state: restarted<br> daemon_reload: yes<br> name: containerd<br></code></pre> </section> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <p style="text-align: right;"><span style="font-size: 12px;">格式整理:IT运维技术圈</span><br></p> <p style="text-align: right;"><span style="font-size: 12px;">原文地址:https://blog.csdn.net/omaidb/article/details/116599552</span></p> </section> </section>
作者:微信小助手
<p style="white-space: normal;" data-mpa-powered-by="yiban.io"><span style="font-size: 15px;">Redis 通常是我们业务系统中一个重要的组件,比如缓存、账号登录信息、排行榜等。</span><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;"> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">一旦 Redis 请求延迟增加,可能就会导致业务系统“雪崩”。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我在单身红娘婚恋类型互联网公司工作,在双十一推出下单就送女朋友的活动。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">谁曾想,凌晨 12 点之后用户量暴增,出现了一个技术故障。用户无法下单,当时老大火冒三丈。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">经过查找发现 Redis 报 <strong>Could not get a resource from the pool</strong>。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">获取不到连接资源,并且集群中的单台 Redis 连接量很高。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">大量的流量没了 Redis 的缓存响应,直接打到了 MySQL,最后数据库也宕机了……</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">于是各种更改最大连接数、连接等待数。虽然报错信息频率有所缓解,但还是持续报错。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">后来经过线下测试,发现存放 Redis 中的字符数据很大,返回数据平均需要 1 秒。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">可以发现,一旦 Redis 延迟过高会引发各种问题。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">今天「码哥」跟大家一起来分析下如何确定 Redis 有性能问题和解决方案。</span></p> <ul class="list-paddingleft-1" style="white-space: normal;text-align: left;"> <p style="white-space: normal;text-align: left;"><br></p> </ul> <h1 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">1 Redis 性能出问题了吗?</span></strong></h1> <p><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">最大延迟是客户端发出命令到客户端收到命令的响应的时间,正常情况下 Redis 处理的时间极短,在微秒级别。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">当 Redis 出现性能波动的时候,比如达到几秒到十几秒,这个很明显我们可以认定 Redis 性能变慢了。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">有的硬件配置比较高,当延迟 0.6 毫秒,我们可能就认定变慢了。硬件比较差的可能 3 毫秒我们才认为出现问题。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="text-align: justify;font-size: 14px;color: rgb(136, 136, 136);">那我们该如何定义 Redis 真的变慢了呢?</span><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">所以,我们需要对当前环境的 Redis 基线性能做测量。也就是在一个系统在低压力、无干扰情况下的基本性能。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">当你发现 Redis 运行时时的延迟是基线性能的两倍以上,就可以判定 Redis 性能变慢了。</span></p> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></h
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">大家好,我是悟空呀~</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">最近 xingxing 哥咨询红包系统的架构如何设计,悟空找到一篇不错的文章,感觉非常不错,分享给大家看下~</p> <hr data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;height: 1px;border-width: initial;border-style: none;border-color: initial;text-align: center;background-image: linear-gradient(to right, rgba(248, 57, 41, 0), rgba(248, 57, 41, 0.75), rgba(248, 57, 41, 0));"> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">来源:archsummit<br>链接:https://www.infoq.cn/article/weixin-bonus-load/?_t=t<br>排版:悟空哥</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">今天跟大家分享的主题是如何实现 “有把握” 的春晚摇一摇系统。回忆一下春晚的活动,有什么样的活动形式呢?</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7520661157024794" src="/upload/d18fccabe243984c66ef1c7032d44e94.png" data-type="png" data-w="1452" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">当时我们是直接复用客户端摇一摇入口,专门给春晚摇一摇定制了一个页面,可以摇出 “现金拜年”、“红包”。底下的红包肯定是大家比较感兴趣的,也是今天下午重点介绍的内容。比较精彩的活动背后一定会有一个设计比较独到的系统。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">V0.1 原型系统</span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7434119278779473" src="/upload/e5b5b52cc9bb874ce4c2c18c58649682.png" data-type="png" data-w="1442" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我们看一下这个系统,我们当时做了一个<span style="font-weight: 700;color: rgb(248, 57, 41);">原型系统</span>,比较简单,它已经实现了所有的功能,摇那个手机的时候会通过客户端发出一个请求,接入服务器,然后摇一摇服务,进行等级判断,判断以后把结果给到后端,可能摇到拜年或红包,假设摇到红包,上面有 LOGO 和背景图,客户端把这个 LOGO 和背景图拉回去,用户及时拆开红包,拆的请求会来到红包系统,红包系统进行处理之后会到支付系统,到财富通的转帐系统,最终用户拿到红包。拿到钱以后,只是其中一份,还有好几份是可以分享出去,我们称之为 “分裂红包”,通过信息系统转发给好友或群里,好友跟群里的人可以再抢一轮。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">整个过程归一下类,叫资源流、信息流、业务流、资金流,今天讲的主要是资源流跟信息流。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">原始系统看起来比较简单,是不是修改一下直接拿到春晚上用就可以了?</span>肯定不行的。到底它有什么样的问题呢,为什么我们不能用,在回答这个问题之前想请大家看一下我们面临的挑战。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">1、我们面临怎样的挑战?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第一个挑战</span>是比较容易想到的,<span style="font-weight: 700;color: rgb(248, 57, 41);">用户请求量很大</span>,当时预计 7 亿观众,微信用户也挺多的,当时预估一下当时峰值达到一千万每秒,通过图对比一下,左边是春运抢火车票,一秒钟请求的峰值是 12 万,第二个是微信系统,微信系统发消息有个小高峰,那时候峰值每秒钟是 33 万,比较高一点的是预估值一千万每秒,右边是春晚时达到的请求峰值是 1400 万每秒。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这个活动跟春晚是紧密互动的,有很多不确定因素,体现在几个方面。一个是在开发过程中,我们的活动怎么配合春晚,一直没有定下来,很可能持续到春晚开始前,显然我们的客户端跟我们的系统到那时候才发布出去,这时候我们的开发就会碰到比较多的问题了,这是第一个。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第二个挑战</span>,在春晚过程中,因为春晚是<span style="font-weight: 700;color: rgb(248, 57, 41);">直播型节目</span>,节目有可能会变,时长会变,顺序会变,活动过程跟春晚节目紧密衔接在一起,自己也是会有挑战的,这也是不确定的因素。再就是我们系统是定制的,专门为春晚定制,只能运行这么一次,这是挺大的挑战,运行一次的系统不能通过很长的时间,检查它其中有什么问题很难,发出去了以后那一次要么就成功了,要么就失败了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第三个挑战</span>,因为春晚观众很多,全国人民都在看,高度关注,我们必须保证成功,万一搞砸了就搞砸在全国人民面前了。<span style="font-weight: 700;color: rgb(248, 57, 41);">这么大型的活动在业界少见,缺少经验,没有参考的东西</span>。还有就是我们需要做怎样的准备才能保证万无一失或者万有一失,保证绝大部分用的体验是 OK 的,有很多问题需要我们不断地摸索思考。原型系统不能再用的,再用可能就挂了。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">2、原型系统存在哪些问题?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">原型系统有哪些问题呢?</span>第一个是在流量带宽上,大量的用户请求会产生大量的<span style="font-weight: 700;color: rgb(248, 57, 41);">带宽</span>,预估带宽峰值是 3000pb 每秒,假设我们资源是无限的能够满足带宽需求,也会碰到一个问题,用户摇到以后有一个等待下载的过程。第二个问题,在接入质量这一块,我们预估同时在线 3.5 亿左右,特别是在外网一旦产生波动的时候怎么保证用户体验不受损而系统正常运作。第三个挑战,请求量很大,1000 万每秒,如何转到摇一摇服务,摇一摇服务也面临一千万请求量,我们系统要同时面对两个一千万请求量,这不是靠机器的,大家都有分布式的经验,这么大请求量的时候任何一点波动都会带来问题,这是一个很大的挑战。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">3、我们是如何解决这些问题的?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">针对以上几点,我们详细看一下每一点我们是怎么做到的。我们首先看一下信心指数,把这个系统拿到春晚去跑有多少信心,这里的指数是 10,如果这个系统拿到春晚去用,而且还成功了,这个概率是 10%。当然我们的系统不能建立在运气的基础上,应该怎么做?第一个,在带宽这一块客户端可以摇到多种多样的结果,结果大部分都是<span style="font-weight: 700;color: rgb(248, 57, 41);">静态资源</span>,静态资源我们可以提前制作出来下发到客户端,在后台做了资源推送的服务,客户端拿到列表以后可以先行下载,<span style="font-weight: 700;color: rgb(248, 57, 41);">客户端利用闲时把资源拉过去</span>。碰到几个问题,资源交付情况的问题,需要增量的发下去;二是资源更新;三是资源下载失败,失败的话怎么办呢;四是资源覆盖率,依靠这个系统下载资源的用户,比如覆盖率只有 20%、30%,两个东西就没有意义了,覆盖率要达到 90% 左右;五是离线资源下载,万一有些人把里面的东西修改了,可能会产生意想不到的结果,怎么保证离线资源的安全。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这里有个数据,2 月 9 号到 2 月 18 号下发资源 65 个,累积流量 3.7PB,峰值流量 1Tb/s。通过这种方式解决了下载资源的问题。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7545582047685835" src="/upload/8646750db902b4f3e1139ce1b8d46e39.png" data-type="png" data-w="1426" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">再就是<span style="font-weight: 700;color: rgb(248, 57, 41);">外网接入质量</span>,在上海跟深圳两地建立了十八个接入集群,每个城市有三网的介入,总共部署了 638 台接入服务器,可以支持同时 14.6 亿的在线。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">所有用户的请求都会进入到接入服务器,我们建立了 18 个接入集群,保证如果一个出现问题的时候用户可以通过其它的接入,但是在我们内部怎么把请求转给摇一摇服务,摇一摇处理完还要转到后端,怎么解决呢?解决这个问题代价非常大,需要很多资源,最终我们选择把摇一摇服务去掉,把一千万每秒的请求干掉了,把这个服务挪入到接入服务。除了处理摇一摇请求之外,所有微信收消息和发消息都需要中转,因为这个接入服务本身,摇一摇的逻辑,因为时间比较短,如果发消息也受影响就得不偿失了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">恰好有一个好处,我们的接入服务的架构是有利于我们解决这个问题的,在这个接入节点里分为几个部分,<span style="font-weight: 700;color: rgb(248, 57, 41);">一个是负责网络 IO 的,提供长链接</span>,用户可以通过长链接发消息,回头可以把请求中转到另外一个模块,就是接入到逻辑模块,平时提供转发这样的功能,现在可以把接入逻辑插入。这样做还不够,比方说现在做一点修改,还需要上线更新,摇一摇的活动形式没有怎么确定下来,中间还需要修改,但是上线这个模块也不大对,我们就把接入的逻辑这一块再做一次拆分,把逻辑比较固定、比较轻量可以在本地完成的东西,不需要做网络交互的东西放到了接入服务里。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">另外一个涉及到<span style="font-weight: 700;color: rgb(248, 57, 41);">网络交互</span>的,需要经常变更的,处理起来也比较复杂的,<span style="font-weight: 700;color: rgb(248, 57, 41);">做了个 Agent</span>,通过这种方式基本上实现了让接入能够内置摇一摇的逻辑,而且接入服务本身的逻辑性不会受到太大的损伤。解决这个问题之后就解决了接入的稳定性问题,后面的问题是摇一摇怎么玩,摇一摇怎么玩是红包怎么玩,在红包过程中怎么保证红包是安全的呢,红包涉及到钱,钱是不能开玩笑的。第三个问题是<span style="font-weight: 700;color: rgb(248, 57, 41);">怎样跟春晚保持互动</span>,春晚现场直播,我们怎么跟现场直播挂钩衔接起来。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">先看红包如何发放。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7479108635097493" src="/upload/f45606fd925a99ff4dde4c3066d5e738.png" data-type="png" data-w="1436" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">前面说道摇一摇请求</span>,其实是在接入服务做的,红包也是在接入服务里发出去的,为了在发红包过程中不依赖这个系统,我们把红包的种子文件在红包系统里生成出来,切分,分到每个接入服务器里,每个接入服务器里都部署了专门的红包文件。一个红包不能发两次,红包的发放速率需要考虑,发放红包一定有用户拆,拆了还要再抢,我们需要精确控制,确保所有请求量都是在红包系统能够接受的范围内。在这个过程中还会有另外一个风险,用户摇到红包之后还可以有一些分裂红包分出去,他也可以不分享,不分享的也不会浪费,可以回收过来,会通过本地拉回去。这部分因为是比较少量的,问题不大,因为所有红包已经发出去了,只是补充的。这里我们就搞定了红包发放。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">二是怎么样保证红包不被多领或恶意领取</span>,每个客户领三个红包,这是要做限制的,但这是有代价的,就是存储的代价。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我们在我们的协议里后台服务接入的摇一摇文件里下发红包的时候<span style="font-weight: 700;color: rgb(248, 57, 41);">写一个用户领取的情况,客户端发再次摇一摇请求的时候带上来,我们检查就行了</span>,这是一个小技巧,这种方式解决用户最多只能领三个、企业只能领一个限制的问题。这个只能解决正版客户端的问题,<span style="font-weight: 700;color: rgb(248, 57, 41);">恶意用户可能不用正版,绕过你的限制,这是有可能的</span>。怎么办呢?一个办法是在 Agent 里面,通过检查本机的数据能够达到一个目的,摇一摇接入服务例有 638 台,如果迫到不同的机器,我们是长连,还可以短连,还可以连到另一台服务器,可以连到不同的地方去。还有一个问题是人海战术,有些人拿着几万、几十万的号抢,抢到都是你的,那怎么办呢?这个没有太好的办法,用大数据分析看用户的行为,你平时养号的吗,正常养号吗,都会登记出来。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">怎样跟春晚现场保持互动?</span>需要解决的问题有两个,一个是要迅速,不能拖太长时间,比如现在是刘德华唱歌,如果给出的明星摇一摇还是上一个节目不太合适,要求我们配置变更需要迅速,二是可靠。我们怎么做的呢?</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7496522948539638" src="/upload/dd7e2d6f99544340d0f51ce2e2543977.png" data-type="png" data-w="1438" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">春晚现场我们是专门有同学过去的,在他们电脑装了系统,可以跟我们后台进行交互的,节目变了节切一下,变动的请求会发到后台,我们部署两套,一套在深圳、一套在上海,在这个配置里还准备了三步服务,哪一步都可以,同时还可以同步这个数据,这个数据还可以下发到所有的接入机器,会把它同步过去,不是用一种方式,而是用三种方式,通过这种方式可以迅速的在一千台服务器成功,是不是能够达到配置一定能够用?不一定,<span style="font-weight: 700;color: rgb(248, 57, 41);">春晚现场是不可控的,万一指令没有发出怎么办?</span>如果六个配置服务都挂了怎么办,从上一个节目切到下一个节目的时候发生这种问题不是太大,但是主持人在十点三十的时候如果摇红包一摇啥都没有,这就怒了,口播出不来也就挂了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">怎么做的呢?主持人肯定有口播,口播的时间点我们大致知道,虽然不知道精确的时间点,比如彩排的时候告诉我们一个时间,后来变了,我们大致知道时间范围,可以做倒计时的配置,比如十点半不管你有没有口播我们都要发红包了。如果节目延时太长了,你的红包十分钟发完了,之后摇不到,那也不行,这种情况下我们做了校正,<span style="font-weight: 700;color: rgb(248, 57, 41);">在节目过程中我们不断校正倒计时的时间</span>,设了一个策略,定了一个流程,半小时的时候要通知一下我这个时间,因为它是预估的,节目越到后面能定下来的时间范围越精确,提前告诉我们,我们就可以调整。那时候现场是在春晚的小会议室,在小会议室看不到现场什么情况,也是通过电视看,结果电视没信号了,就蒙了,校准就不知道现在怎么回事,进行到哪一步了,当时很着急,还好后来没事,后续的几个节目还是校正回来了,最终我们是精确的在那个时间点出现了抢红包。前面讲了怎么在系统解决流量的问题、请求量的问题,最重要的一点是我们预估是一千万每秒,<span style="font-weight: 700;color: rgb(248, 57, 41);">但如果春晚现场出来的是两千万、三千万或四千万怎么办,是不是整个系统就挂掉了</span>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我们就是采用<span style="font-weight: 700;color: rgb(248, 57, 41);">过载保护</span>,过载保护中心点是两点,前端保护后端,后端拒绝前端。一个是在客户端埋入一个逻辑,每次摇变成一个请求,摇每十秒钟或五秒钟发送一个请求,这样可以大幅度降低服务器的压力,这只会发生到几个点,一个是服务访问不了、服务访问超时和服务限速。实时计算接入负载,看 CPU 的负载,在衔接点给这台服务器的用户返回一个东西,就是你要限速了,你使用哪一档的限速,通过这种方式,当时有四千万用户在摇我们也能扛得住。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">V0.5 测试版</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这是我们的 0.5 测试版,对这个我们的信心指数是 50,为什么只有 50% 的把握?</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7444444444444445" src="/upload/e79b98b1c839b71ca672dc623fe1ddd6.png" data-type="png" data-w="1440" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我们前面解决的问题都是解决用户能摇到红包,服务器还不会坏掉,但是对摇红包来说那是第一步,后面还有好几步,还要把红包拆出来,还要分享,分享完以后其它人可以抢,这个体验是要保证的,简单分析一下可以发现前面是本人操作,后面是好友操作,这里就存在一个契机,你可以做一些服务,一旦出现问题是可以利用的点,可以做延时。剩下的问题是保证本人操作比较好,后面出点问题可以延迟,有延迟表示有时间差处理那个东西。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">1、核心体验是什么?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这里面我们需要确保成功,确保体验是完全 OK 的,确保成功的时候前面提到原型的系统里解决了摇到红包的问题,剩下的就是拆红包和分享红包。怎么样确保拆红包和分享红包的用户体验?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">2、如何确保拆 / 分享红包的用户体验?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">拆红包和分享红包可以做一下切割,可以切割成两个部分,一个是用户的操作,点了分享红包按纽,之后是转帐,对我们来说确保前面一点就可以了,核心体验设计的东西再次缩小范围,确保用户操作这一步能够成功。怎么确保呢?我们称之为 “铁三角” 的东西,拆 / 分享红包 = 用户操作 + 后台彰武逻辑。这是我们能做到的最高程度了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">3、还能做得更极致吗?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">但我们还可以做的更好一点,前面这个用户看起来还是成功的,只是入帐入的稍微迟一点点,用户感觉不到。如果我们异步队列这里挂了,或者网络不可用了,概率比较低,我们有三个数据中心,挂掉一个问题不大,万一真的不能用呢,我们又做了一次异步,分两部分:一个是业务逻辑,校验这个红包是不是这个用户的,还有一个透传队列,把这个数据再丢到后边,其实可以相信本机的处理一般是可以成功的,只要做好性能测试基本上是靠谱的。在后面出现问题的时候我们用户的体验基本不受损,保证绝大多数用户的体验是 OK 的。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">V0.8 预览版</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我们又做了 0.8 的版本,预览版,信心指数 70,我们认为这个东西有七成把握是可以成功的。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7402777777777778" src="/upload/8db873249e05e063569d2b455ae6c467.png" data-type="png" data-w="1440" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> img </figcaption> </figure> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">大家知道设计并不等于实现,设计的再好,实践有问题也很崩溃,要保证设计一是全程压测,二是专题 CODE REVIEW,三是内部演练,四是线上预热,五是复盘与调整。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">复盘</span>包括两部分,有问题的时候可以把异常问题看出来,二是很正常,跑的时候是不是跟想象的一样,需要对正常情况下的数据做预估的重新评估,看看是不是符合预期。两次预热,一次是摇了 3.1 亿次,峰值 5000 万一分钟,100 万每秒,跟我们估算的一千万每秒差很远,当时只是针对 iPhone 用户,放开一个小红点,你看到的时候可以抢,发放红包 5 万每秒,春晚当晚也是五万每秒。后面又发了一次,针对前面几个问题再做一次。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">V1.0 正式版</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">做完这两次连接后面就迎接 2 月 18 号春晚的真正考验。这是 1.0 正式版,信心指数达到 80,我们认为 80% 是可以搞定的。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7517433751743375" src="/upload/ea140387d3d9389e9bfda2b071bbfa33.png" data-type="png" data-w="1434" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">剩下 20% 在哪里?有 10% 是在现场,现场不可能一帆风顺,有可能现场摇的很 High,但后面到处灭火,10% 是在现场处置的时候有比较好的预案和方案能够解决,另外 10% 是人算不如天算,一个很小的点出现问题导致被放大所有用户受影响也是有可能的,我们很难控制了。要做出完美无缺的基本不太可能,剩下 10% 就是留运气。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">2 月 18 号跑出来的结果是这样的,当时摇了 110 亿次,峰值是 8.1 亿每分钟,1400 万每秒。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7357440890125174" src="/upload/b5086b9bfb76fcfef25bf0a9696790da.png" data-type="png" data-w="1438" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我今天跟大家的分享到这里。谢谢大家。</p> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">我是悟空,期待与你一起打怪升级变强!<br></p> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU3NzU5NTg5Mg==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/GfOyjHGwCoN5Ky9IZgsdyZgM3lbEC5Ixe3ZgxBu5MdzvjWFyC7uqrsffcyhtrD8r8t0qicxbGmNxKYr4l4mANKQ/0?wx_fmt=png" data-nickname="面试突击" data-alias="PassJava1" data-signature="大厂面试突击,专注分享面试题,如计算机基础、计算机网络、Java后端、前端Vue。" data-from="0"></mpprofile> </section>