文章列表

Netty 如何做到单机百万并发?

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, 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;"><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: 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;">说道这把剑,剑身上铭刻着这样一句话:ONLY THE KING CAN TAKE THE SWORD FROM THE STONE。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">虽然典故中的 the king 是指英明之主亚瑟王,但是在本章中,这个 king 就是读者自己。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们今天不仅要从百万并发基石上拔出这把 epoll 之剑,也就是 Netty,而且要利用这把剑大杀四方,一如当年的亚瑟王凭借此剑统一了英格兰全境一样。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">说到石中剑 Netty,我们知道他极其强悍的性能以及纯异步模型,释放出了极强的生产力,内置的各种编解码编排,心跳包检测,粘包拆包处理等,高效且易于使用,以至于很多耳熟能详的组件都在使用,比如 Hadoop,Dubbo 等。</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> <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);">Netty 的异步模型</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;">说起 Netty 的异步模型,我相信大多数人,只要是写过服务端的话,都是耳熟能详的,bossGroup 和 workerGroup 被 ServerBootstrap 所驱动,用起来简直是如虎添翼。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">再加上各种配置化的 handler 加持,组装起来也是行云流水,俯拾即是。但是,任何一个好的架构,都不是一蹴而就实现的,那她经历了怎样的心路历程呢?</p> <p data-tool="mdnice编辑器

SQL优化20招

作者:微信小助手

<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;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;margin-bottom: 0px;" data-mpa-powered-by="yiban.io"> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg4NjYyODc4OA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/J4jTHmo8Xh6qM32ASOtVbXNoiaegrI26qLRw6r6FTI7dZw6TMT7vecvnjd1O8xSsM5MiajIuQZicxSC6KFK8TMpbg/0?wx_fmt=png" data-nickname="java突击队" data-alias="" data-signature="技术经验分享" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <section> <span style="font-size: 22px;font-weight: bold;letter-spacing: 0px;">一、查询SQL尽量不要使用select *,而是具体字段</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、反例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.42147950636039333&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、正例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.6110297429065883&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>,username,tel&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">3、理由</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);"> 节省资源、减少网络开销。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 可能用到覆盖索引,减少回表,提高查询效率。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><code style="font-size: 14px;overflow-wrap: break-word;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;">注意:为节省时间,下面的样例字段都用*代替了。</code></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>二、避免在where子句中使用 or 来连接条件</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、反例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.45506078189057786&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>=<span style="color: #d19a66;line-height: 26px;">1</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">OR</span>&nbsp;salary=<span style="color: #d19a66;line-height: 26px;">5000</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、正例</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">(1)使用union all</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.23322449049420357&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>=<span style="color: #d19a66;line-height: 26px;">1</span>&nbsp;<br><span style="color: #c678dd;line-height: 26px;">UNION</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">ALL</span><br><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;salary=<span style="color: #d19a66;line-height: 26px;">5000</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">(2)分开两条sql写</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.42296411262398004&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>=<span style="color: #d19a66;line-height: 26px;">1</span><br><br><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;salary=<span style="color: #d19a66;line-height: 26px;">5000</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">3、理由</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);"> 使用 <code style="font-size: 14px;overflow-wrap: break-word;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;">or</code>可能会使索引失效,从而全表扫描; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 对于 <code style="font-size: 14px;overflow-wrap: break-word;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;">or</code>没有索引的 <code style="font-size: 14px;overflow-wrap: break-word;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;">salary</code>这种情况,假设它走了 <code style="font-size: 14px;overflow-wrap: break-word;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;">id</code>的索引,但是走到 <code style="font-size: 14px;overflow-wrap: break-word;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;">salary</code>查询条件时,它还得全表扫描; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 也就是说整个过程需要三步:全表扫描+索引扫描+合并。如果它一开始就走全表扫描,直接一遍扫描就搞定; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 虽然 <code style="font-size: 14px;overflow-wrap: break-word;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;">mysql</code>是有优化器的,出于效率与成本考虑,遇到 <code style="font-size: 14px;overflow-wrap: break-word;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;">or</code>条件,索引还是可能失效的; </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>三、尽量使用数值替代字符串类型</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、正例</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);"> 主键(id): <code style="font-size: 14px;overflow-wrap: break-word;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;">primary key</code>优先使用数值类型 <code style="font-size: 14px;overflow-wrap: break-word;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;">int</code>, <code style="font-size: 14px;overflow-wrap: break-word;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;">tinyint</code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 性别(sex):0代表女,1代表男;数据库没有布尔类型, <code style="font-size: 14px;overflow-wrap: break-word;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;">mysql</code>推荐使用 <code style="font-size: 14px;overflow-wrap: break-word;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;">tinyint</code> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、理由</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);"> 因为引擎在处理查询和连接时会逐个比较字符串中每一个字符; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 而对于数字型而言只需要比较一次就够了; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 字符会降低查询和连接的性能,并会增加存储开销; </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>四、使用varchar代替char</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、反例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.1487005287252634&quot;) 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;">`address`&nbsp;char(100)&nbsp;DEFAULT&nbsp;NULL&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'地址'</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、正例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.48912539676743383&quot;) 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;">`address`&nbsp;varchar(100)&nbsp;DEFAULT&nbsp;NULL&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'地址'</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">3、理由</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);"> <code style="font-size: 14px;overflow-wrap: break-word;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;">varchar</code>变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>按声明大小存储,不足补空格; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 其次对于查询来说,在一个相对较小的字段内搜索,效率更高; </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>五、技术延伸,char与varchar2的区别?</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>的长度是固定的,而<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>的长度是可以变化的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">比如,存储字符串<code style="font-size: 14px;overflow-wrap: break-word;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;">“101”</code>,对于<code style="font-size: 14px;overflow-wrap: break-word;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;">char(10)</code>,表示你存储的字符将占10个字节(包括7个空字符),在数据库中它是以空格占位的,而同样的<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2(10)</code>则只占用3个字节的长度,10只是最大值,当你存储的字符小于10时,按实际长度存储。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>的效率比<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>的效率稍高。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">3、何时用<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>,何时用<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>和<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>是一对矛盾的统一体,两者是互补的关系,<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>比<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>节省空间,在效率上比<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>会稍微差一点,既想获取效率,就必须牺牲一点空间,这就是我们在数据库设计上常说的“以空间换效率”。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>虽然比<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>节省空间,但是假如一个<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>列经常被修改,而且每次被修改的数据的长度不同,这会引起“行迁移”现象,而这造成多余的I/O,是数据库设计中要尽力避免的,这种情况下用<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>代替<code style="font-size: 14px;overflow-wrap: break-word;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;">varchar2</code>会更好一些。<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>中还会自动补齐空格,因为你<code style="font-size: 14px;overflow-wrap: break-word;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;">insert</code>到一个<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>字段自动补充了空格的,但是<code style="font-size: 14px;overflow-wrap: break-word;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;">select</code>后空格没有删除,因此<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>类型查询的时候一定要记得使用<code style="font-size: 14px;overflow-wrap: break-word;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;">trim</code>,这是写本文章的原因。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如果开发人员细化使用<code style="font-size: 14px;overflow-wrap: break-word;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;">rpad()</code>技巧将绑定变量转换为某种能与<code style="font-size: 14px;overflow-wrap: break-word;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;">char</code>字段相比较的类型(当然,与截断<code style="font-size: 14px;overflow-wrap: break-word;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;">trim</code>数据库列相比,填充绑定变量的做法更好一些,因为对列应用函数<code style="font-size: 14px;overflow-wrap: break-word;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;">trim</code>很容易导致无法使用该列上现有的索引),可能必须考虑到经过一段时间后列长度的变化。如果字段的大小有变化,应用就会受到影响,因为它必须修改字段宽度。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">正是因为以上原因,定宽的存储空间可能导致表和相关索引比平常大出许多,还伴随着绑定变量问题,所以无论什么场合都要避免使用char类型。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>六、where中使用默认值代替null</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、反例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.3315913750656072&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;age&nbsp;<span style="color: #c678dd;line-height: 26px;">IS</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、正例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.11152508358738711&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;age&gt;<span style="color: #d19a66;line-height: 26px;">0</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">3、理由</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);"> 并不是说使用了 <code style="font-size: 14px;overflow-wrap: break-word;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;">is null</code>或者 <code style="font-size: 14px;overflow-wrap: break-word;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;">is not null</code>就会不走索引了,这个跟 <code style="font-size: 14px;overflow-wrap: break-word;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;">mysql</code>版本以及查询成本都有关; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 如果 <code style="font-size: 14px;overflow-wrap: break-word;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;">mysql</code>优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 <code style="font-size: 14px;overflow-wrap: break-word;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;">!=,&lt;&gt;,is null,is not null</code>经常被认为让索引失效; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 其实是因为一般情况下,查询的成本高,优化器自动放弃索引的; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 如果把 <code style="font-size: 14px;overflow-wrap: break-word;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;">null</code>值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点; </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>七、避免在where子句中使用!=或&lt;&gt;操作符</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1、反例</p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/jJtbwFuzNwAyACKZoFrWzlobVRojf28Fa84GmHIdBxYF3wibia2z9m3Oom6CWgqlxFtztfRC7pl9Rda4XTCsMPwiamia50ZrHNOV/640?wx_fmt=svg&amp;random=0.6723977198373741&quot;) 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;"><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;salary!=<span style="color: #d19a66;line-height: 26px;">5000</span><br><br><span style="color: #c678dd;line-height: 26px;">SELECT</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">FROM</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">WHERE</span>&nbsp;salary&lt;&gt;<span style="color: #d19a66;line-height: 26px;">5000</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">2、理由</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);"> 使用 <code style="font-size: 14px;overflow-wrap: break-word;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;">!=</code>和 <code style="font-size: 14px;overflow-wrap: break-word;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;">&lt;&gt;</code>很可能会让索引失效 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 应尽量避免在 <code style="font-size: 14px;overflow-wrap: break-word;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;">where</code>子句中使用 <code style="font-size: 14px;overflow-wrap: break-word;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;">!=</code>或 <code style="font-size: 14px;overflow-wrap: break-word;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;">&lt;&gt;</code>操作符,否则引擎将放弃使用索引而进行全表扫描 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 实现业务优先,实在没办法,就只能使用,并不是不能使用 </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>八、inner join 、left join、right join,优先使用inner join</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">三种连接如果结果相同,优先使用inner join,如果使用left join左边表尽量小。</p> <ul 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);"> inner join 内连接,只保留两张表中完全匹配的结果集; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> left join会返回左表所有的行,即使在右表中没有匹配的记录; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> right join会返回右表所有的行,即使在左表中没有匹配的记录; </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top

计算机网络详解(强推经典字典帖)

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" mp-original-font-size="17" mp-original-line-height="27.200000762939453" style="margin-bottom: 0px;" data-mpa-powered-by="yiban.io"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <section> <section powered-by="xiumi.us" style="margin: 0px 0px 24px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;"> <section> <p><strong><span style="font-size: 18px;">1.TCP和UDP的区别</span></strong></p> <p style="text-align: left;"><strong><span style="font-size: 18px;"><br></span></strong></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section> <p style="text-align: left;">TCP是面向连接的,UDP是面向无连接的;</p> </section></li> <li> <section> <p style="text-align: left;">TCP只能一对一通信,UDP支持一对一,一对多,多对一和多对多交互通信;</p> </section></li> <li> <section> <p style="text-align: left;">TCP是面向字节流的,UDP是面向报文的;</p> </section></li> <li> <section> <p style="text-align: left;">TCP是可靠传输,使用流量控制和拥塞控制;UDP是不可靠传输<span style="font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"></span></p> </section></li> <li> <section> <p style="text-align: left;">TCP首部最小20字节,最大60字节;UDP首部仅8字节。</p> </section></li> </ul> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">2.ISO七层模型及相关协议</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li><p>物理层:建立、维护、断开物理连接。</p></li> <li><p>数据链路层:在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路。</p></li> <li><p>网络层:进行逻辑地址寻址,实现不同网络之间的路径选择,协议有ICMP、IGMP、IP等。</p></li> <li><p>传输层:定义传输数据的协议端口号,以及流量控制和差错校验,协议有TCP、UDP。</p></li> <li><p>会话层:建立、管理、终止会话,指本地主机与远程主机正在进行的会话。</p></li> <li><p>表示层:确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。</p></li> <li><p>应用层:网络服务与最终用户的一个接口,常见的协议有:HTTP、FTP、SMTP、DNS。</p></li> </ul> <p><strong>TCP/IP 四层模型</strong></p> <section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js"><code><span class="code-snippet_outer">网络接口层</span></code><code><span class="code-snippet_outer">网际层</span></code><code><span class="code-snippet_outer">传输层</span></code><code><span class="code-snippet_outer">应用层</span></code></pre> </section> </section> <p><strong>五层体系结构</strong></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js"><code><span class="code-snippet_outer">物理层</span></code><code><span class="code-snippet_outer">数据链路层</span></code><code><span class="code-snippet_outer">网络层:IP网际协议、ARP地址转换协议、RIP路由信息协议</span></code><code><span class="code-snippet_outer">传输层:TCP传输控制协议、UDP用户数据报文协议</span></code><code><span class="code-snippet_outer">应用层:HTTP超文本传输协议、FTP文本传输协议、DNS域名系统</span></code></pre> </section> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">3.如何理解HTTP协议是无状态的</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p>当浏览器第一次发送请求给服务器时,服务器响应了;</p> <p><br></p> <p>如果同个浏览器发起第二次请求给服务器时,它还是会响应。但是呢,服务器不知道你就是刚才的那个浏览器。</p> <p><br></p> <p>简而言之,服务器不会去记住你是谁,所以是无状态协议。</p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">4.简述从浏览器地址栏输入url到显示主页的过程</span></strong></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section> <p>DNS解析,查找域名对应的IP地址。</p> </section></li> <li> <section> <p>与服务器通过三次握手,建立TCP连接</p> </section></li> <li> <section> <p>向服务器发送HTTP请求。</p> </section></li> <li> <section> <p>服务器处理请求,返回网页内容。</p> </section></li> <li> <section> <p>浏览器解析并渲染页面。</p> </section></li> <li> <section> <p>TCP四次握手,连接结束。</p> </section></li> </ul> <p><img class="rich_pages wxw-img" data-ratio="0.39537037037037037" src="/upload/e77b63bd0e8068234b936fff3ea233a2.png" data-type="png" data-w="1080"></p> <p><br></p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">5.说下 HTTP/1.0,1.1,2.0 的区别</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p>HTTP/1.0</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="67" data-source-title=""> <section class="js_blockquote_digest"> <section> 默认使用短连接,每次请求都需要建立一个TCP连接。它可以设置Connection: keep-alive 这个字段,强制开启长连接。 </section> </section> </blockquote> <p><br></p> <p>HTTP/1.1</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="102" data-source-title=""> <section class="js_blockquote_digest"> <section> <p>默认使用长连接,即TCP连接默认不关闭,可以被多个请求复用。</p> <p>分块传输编码,即服务端每产生一块数据,就发送一块,用“流模式”取代“缓存模式”。</p> <p>管道机制,即在同一个TCP连接里面,客户端可以同时发送多个请求。</p> </section> </section> </blockquote> <p><br></p> <p>HTTP/2.0</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="207" data-source-title=""> <section class="js_blockquote_digest"> <section> <p>二进制协议,1.1版本的头信息是文本(ASCII编码),数据体可以是文本或二进制;2.0中,头信息和数据体都是二进制。</p> <p><br></p> <p>完全多路复用,在一个连接里,客户端和服务器都可以同时发送多个请求或响应,而且不用按照顺序一一对应。</p> <p><br></p> <p>报头压缩,HTTP协议不带有状态,每次请求都必须带上所有信息。HTTP/2.0引入了头信息压缩机制,使用gzip或compress压缩后再发送。</p> <p><br></p> <p>服务端推送,允许服务器未经请求,主动向客户端发送资源。</p> </section> </section> </blockquote> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">6.POST和GET有哪些区别</span></strong></p> <p><img class="rich_pages wxw-img" data-ratio="0.287962962962963" src="/upload/f040e8db9efff4ed5ff7d531d89e089.png" data-type="png" data-w="1080"></p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">7.HTTP 如何实现长连接?在什么时候会超时?</span></strong></p> <p>什么是HTTP的长连接?</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="162" data-source-title=""> <section class="js_blockquote_digest"> <section> <p>HTTP分为长连接和短连接,本质上说的是TCP的长短连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才具有真正的长连接和短连接这一说法。</p> <p>TCP长连接可以复用一个TCP连接,来发起多次HTTP请求,这样就可以减少资源消耗,比如一次HTML请求,如果是短连接的话,可能还需要请求后续的JS/CSS。</p> </section> </section> </blockquote> <p><br></p> <p>如何设置长连接?</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="81" data-source-title=""> <section class="js_blockquote_digest"> <section> 通过在请求头和响应头设置Connection字段指定为keep-alive,HTTP/1.0协议支持,但默认是关闭的,从HTTP/1.1以后,连接默认都是长连接。 </section> </section> </blockquote> <p><br></p> <p>在什么时候会超时?</p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="242" data-source-title=""> <section class="js_blockquote_digest"> <section> <p>HTTP一般会有httpd守护进程,里面可以设置keep-alive timeout,当tcp连接闲置超过这个时间就会关闭,也可以在HTTP的header里面设置超时时间。</p> <p>TCP 的keep-alive包含三个参数,支持在系统内核的net.ipv4里面设置;当 TCP 连接之后,闲置了tcp_keepalive_time,则会发生侦测包,如果没有收到对方的ACK,那么会每隔 tcp_keepalive_intvl 再发一次,直到发送了tcp_keepalive_probes,就会丢弃该连接。</p> </section> </section> </blockquote> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="ini"><code><span class="code-snippet_outer"><span class="code-snippet__attr">tcp_keepalive_intvl</span> = <span class="code-snippet__number">15</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">tcp_keepalive_probes</span> = <span class="code-snippet__number">5</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">tcp_keepalive_time</span> = <span class="code-snippet__number">1800</span></span></code></pre> </section> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">8.HTTP 与 HTTPS 的区别</span></strong></p> <p>HTTP 即超文本传输协议,是一个基于TCP/IP通信协议来传递明文数据的协议。HTTP会存在这几个问题:</p> <p><br></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li><p>请求信息是明文传输,容易被窃听截取。</p></li> <li><p>没有验证对方身份,存在被冒充的风险。</p></li> <li><p>数据的完整性未校验,容易被中间人篡改。</p><p><br></p></li> </ul> <p>为了解决HTTP存在的问题,HTTPS出现啦。</p> <p>HTTPS是什么?</p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="66" data-source-title=""> <section class="js_blockquote_digest"> <section> HTTPS= HTTP+SSL/TLS,可以理解为 HTTPS 是身披 SSL(Secure Socket Layer,安全套接层)的HTTP。 </section> </section> </blockquote> <p>它们的主要区别如下:</p> <p><img class="rich_pages wxw-img" data-ratio="0.2462962962962963" src="/upload/20d87af5d2aa9c419fe09580b2c7c7fc.png" data-type="png" data-w="1080"></p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">9.HTTPS的工作流程是怎样的?</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p>HTTPS = HTTP + SSL/TLS,也就是用SSL/TLS对数据进行加密和解密,用HTTP进行传输。</p> <p><br></p> <p>SSL,即Secure Sockets Layer(安全套接层协议),是网络通信提供安全及数据完整性的一种安全协议。</p> <p><br></p> <p>TLS,即Transport Layer Security(安全传输层协议),它是SSL3.0的后续版本。</p> <p><img class="rich_pages wxw-img" data-ratio="0.8351851851851851" src="/upload/a308c25e08b3714d29944fb61b8d4350.png" data-type="png" data-w="1080"></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section> 客户端发起HTTPS请求,连接到服务器的443端口。 </section></li> <li> <section> 服务器必须要有一套数字证书(证书内容有公钥、证书颁发机构、失效日期等)。 </section></li> <li> <section> 服务器将自己的数字证书发送给客户端(公钥在证书里面,私钥由服务器持有)。 </section></li> <li> <section> 客户端收到数字证书之后,会验证证书的合法性。如果证书验证通过,就会生成一个随机的对称密钥,用证书的公钥加密。 </section></li> <li> <section> 客户端将公钥加密后的密钥发送到服务器。 </section></li> <li> <section> 服务器接收到客户端发来的密文密钥之后,用自己之前保留的私钥对其进行非对称解密,解密之后就得到客户端的密钥,然后用客户端密钥对返回数据进行对称加密,这样子传输的数据都是密文啦。 </section></li> <li> <section> 服务器将加密后的密文返回到客户端。 </section></li> <li> <section> 客户端收到后,用自己的密钥对其进行对称解密,就能得到服务器返回的数据。 </section></li> </ul> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">10.说说HTTP的状态码,301和302的区别?</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li><p>301:永久重定向,表示所请求的资源已经永久地转移到新的位置,这包含域名的改变或者是资源路径的改变。</p><p><br></p></li> <li><p>302:临时重定向,表示所请求的资源临时地转移到新的位置,一般是24到48小时以内的转移会用到302。</p></li> </ul> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">11.说说什么是数字签名?什么是数字证书?</span></strong></p> <p><img class="rich_pages wxw-img" data-ratio="0.832807570977918" src="/upload/cbc1d16b708ebdaf211b67cd545b5559.png" data-type="png" data-w="951"></p> <p>数字证书构成:</p> <p><br></p> <p>公钥和个人等信息,经过Hash算法加密,形成消息摘要;将消息摘要拿到拥有公信力的认证中心(CA),用它的私钥对消息摘要加密,形成数字签名。</p> <p>公钥和个人信息、数字签名共同构成数字证书。</p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">12.对称加密和非对称加密有什么区别</span></strong></p> <p>对称加密:指加密和解密使用同一密钥,优点是运算速度较快,缺点是不能安全地将密钥传输给另一方。常见的对称加密算法有:DES、AES等。</p> <p><img class="rich_pages wxw-img" data-ratio="0.26851851851851855" src="/upload/429719cb6256ef04099acf7694474aba.png" data-type="png" data-w="1080"></p> <p><br></p> <p>非对称加密:指的是加密和解密使用不同的密钥(即公钥和私钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。常见的非对称加密算法有 RSA。</p> <p><img class="rich_pages wxw-img" data-ratio="0.32222222222222224" src="/upload/61c4f0530c79018b49e7964cd35a5ef2.png" data-type="png" data-w="1080"></p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">13.说说 DNS 的解析过程?</span></strong></p> <p>DNS的解析过程如下图:</p> <p><img class="rich_pages wxw-img" data-ratio="1.3471502590673574" src="/upload/79e61740bfa226bba70bd84944f0d444.png" data-type="png" data-w="772"></p> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="72" data-source-title=""> <section class="js_blockquote_digest"> <section> 假设你要查询www.baidu.com的IP地址:浏览器 -&gt; 本地DNS服务器 -&gt; 根域名服务器 -&gt; 顶级域名服务器 -&gt; 权威域名服务器 </section> </section> </blockquote> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li><p>首先会查找浏览器的缓存,看看是否能找到www.baidu.com对应的IP地址,找到就直接返回;否则进行下一步。</p></li> <li><p>将请求发往本地DNS服务器,如果查找到也直接返回,否则继续进行下一步;</p></li> <li><p>本地DNS服务器向根域名服务器发送请求,根域名服务器返回负责.com的顶级域名服务器的列表。</p></li> <li><p>本地DNS服务器再向其中一个顶级域名服务器发送一个请求,返回负责.baidu的权威域名服务器的列表。</p></li> <li><p>本地DNS服务器再向其中一个权威域名服务器发送一个请求,返回www.baidu.com所对应的IP地址。</p></li> </ul> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">14.说说 WebSocket与socket的区别</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p>Socket是一套标准,它完成了对TCP/IP的高度封装,屏蔽网络细节,以便开发者更好地进行网络编程。</p> <p><br></p> <p>Socket等于IP地址 + 端口 + 协议。</p> <p><br></p> <p>WebSocket是一个持久化的协议,它是伴随H5而出的协议,用来解决HTTP不支持持久化连接的问题。</p> <p><br></p> <p>Socket是一个网络编程的标准接口,而WebSocket则是应用层通信协议。</p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">15.HTTP请求的过程与原理</span></strong></p> <p>HTTP是一个基于TCP/IP协议来传递数据的超文本传输协议,传输的数据类型有HTML、图片等。</p> <p><img class="rich_pages wxw-img" data-ratio="0.4759259259259259" src="/upload/a696ca58bc52d570f13234e77ae7ac6d.png" data-type="png" data-w="1080"></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section> <p>客户端进行DNS域名解析,得到对应的IP地址</p> </section></li> <li> <section> <p>根据这个IP地址,找到对应的服务器建立TCP连接(三次握手)</p> </section></li> <li> <section> <p>建立TCP连接后发起HTTP请求(一个完整的http请求报文)</p> </section></li> <li> <section> <p>服务器响应HTTP请求,客户端得到html代码</p> </section></li> <li> <section> <p>客户端解析html代码,用html代码中的资源(如 js、css、图片等等)渲染页面。</p> </section></li> <li> <section> <p>服务器关闭TCP连接(四次挥手)</p> </section></li> </ul> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">16.forward和redirect的区别?</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p>是servlet中的两种主要跳转方式。forward:转发,redirect:重定向</p> <p><br></p> <p>从地址栏显示来说</p> <p>forward是服务器内部的重定向,服务器直接访问目标地址,把里面的东西取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。</p> <p><br></p> <p>redirect是服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新地址。</p> <p><br></p> <p>从数据共享来说</p> <p>由于在整个转发的过程中使用的是同一个request,因此forward会将request信息带到被重定向的jsp或servlet中使用,即可以共享数据。</p> <p><br></p> <p>redirect不能共享数据。</p> <p><br></p> <p>从运用的地方来说</p> <p>forward一般用于用户登录时,根据角色转发到相应的模块</p> <p><br></p> <p>redirect一般用于用户注销登录时返回主页面</p> <p><br></p> <p>从本质上来说</p> <p>forward转发是服务器上的行为,redirect重定向是客户端的行为。</p> <p><br></p> <p>从效率上来说</p> <p>forword效率高,而redirect效率低。</p> <p><br></p> <p>从请求的次数来说</p> <p>forword只有一次请求,而redirect有两次请求。</p> <p><br></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">17.Session和Cookie的区别</span></strong></p> <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;"><br></span></strong></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li><p>Cookie 是保存在客户端的一小块文本串的数据。客户端向服务器发起请求时,服务器会向客户端发送一个 Cookie,客户端就把 Cookie 保存起来。下次向同一服务器再发起请求时,Cookie 就被携带发送到服务器。服务器可以根据这个 Cookie 判断用户的身份和状态。</p><p><br></p></li> <li><p>Session 指的是服务器和客户端一次会话的过程。它是另一种记录客户端状态的机制。不同的是 Cookie 是保存在客户端浏览器中的,而 Session 是保存在服务器上的。客户端浏览器在访问服务器时,服务器会把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找用户的状态。</p></li> </ul> <p><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="23" data-source-title=""> <section class="j

云原生--kubectl 命令全汇总

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" mp-original-font-size="17" mp-original-line-height="27.200000762939453" style="margin-bottom: 0px;" data-mpa-powered-by="yiban.io"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <section> <section powered-by="xiumi.us" style="margin: 0px 0px 24px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 2px;clear: both;min-height: 1em;visibility: visible;"> <section> <p style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-size: 16px;orphans: 3;widows: 3;margin-bottom: 0.85em;font-family: &quot;helvetica neue&quot;, Helvetica, Arial, sans-serif;letter-spacing: 0.2px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><code style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-family: Consolas, &quot;liberation mono&quot;, Menlo, Courier, monospace;font-size: 0.85em;break-inside: avoid;direction: ltr;padding: 0.2em;border-width: initial;border-style: none;border-color: initial;color: inherit;background-color: rgb(247, 247, 247);">kubectl</code>&nbsp;命令是操作 Kubernetes 集群的最直接和最高效的途径,这个60多 MB 大小的二进制文件,到底有啥能耐呢?</p> <h2 style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-size: 1.75em;orphans: 3;widows: 3;break-after: avoid;margin-top: 1.275em;margin-bottom: 0.85em;font-weight: 700;font-family: &quot;helvetica neue&quot;, Helvetica, Arial, sans-serif;letter-spacing: 0.2px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">Kubectl 自动补全</h2> <pre style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-family: consolas, &quot;bitstream vera sans mono&quot;, &quot;courier new&quot;, Courier, monospace;font-size: 0.9em;break-inside: avoid;direction: ltr;margin-top: 0.5em;margin-bottom: 0.5em;padding: 1em;border-width: 1px;border-style: solid;border-color: rgb(221, 221, 221);color: rgb(57, 58, 52);overflow: auto;overflow-wrap: normal;background: rgb(255, 255, 255);text-align: left;word-break: normal;line-height: 1.2em;tab-size: 4;hyphens: none;letter-spacing: 0.2px;"><code style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-family: Consolas, &quot;liberation mono&quot;, Menlo, Courier, monospace;font-size: 0.85em;break-inside: avoid;direction: ltr;border-width: initial;border-style: none;border-color: initial;color: inherit;background: 0px 0px;display: inline;max-width: initial;overflow: initial;line-height: inherit;">$ <span style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-size: inherit;">source</span> <span style="-webkit-tap-highlight-color: transparent;text-size-adjust: none;-webkit-font-smoothing: antialiased;font-size: inherit;">&lt;</span><span style="-webkit-tap-highlight-color: transparent;text-size-

数据异构就该这样做,yyds~

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, 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;">何谓数据异构,上周交易部门商品的同事过来做分享,又看到这个词,他的PPT里面是 数据库异构。其实我们以前做的事情,也是可以称之为数据异构。比如我们将DB里面的数据持久化到Redis里面去,就是一种数据异构的方式。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如果要下个定义的话:<span style="font-weight: 700;color: rgb(248, 57, 41);">把数据按需(数据结构、存取方式、存取形式)异地构建存储。</span></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></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">分库分表中有一个最为常见的场景,为了提升数据库的查询能力,我们都会对数据库做分库分表操作。比如订单库,开始的时候我们是按照订单ID维度去分库分表,那么后来的业务需求想按照商家维度去查询,比如我想查询某一个商家下的所有订单,就非常麻烦。</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> <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.667447306791569" data-w="427" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/ee7d0f0eca0e385d61a7d2097355281c.png"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 异构维度 </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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">数据异构总结起来大概有以下几种场景</span></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 数据库镜像 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 数据库实时备份 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 多级索引 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> search build(比如分库分表后的多维度数据查询) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 业务cache刷新 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 价格、库存变化等重要业务消息 </section></li> </ol> <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></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="1.1186868686868687" data-w="396" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/2213755b3dba619e737cd6c93f98e668.png"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 异构的几种方向 </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;">在日常业务开发中大致可以分为以上几种数据去向,<span style="font-weight: 700;color: rgb(248, 57, 41);">DB-DB</span>这种方式,一般常见于分库分表后,聚合查询的时候,比如我们按照订单ID去分库分表,那么这个时候我们要按照用户ID去查询,查询这个用户下面的订单就非常不方便了,当然可以使用统一加到内存中去,但这样不太好。</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的维度来分一个表,像在上面常见应用场景中介绍的那样。把数据异构到redis、elasticserach、slor中去要解决的问题跟按照多维度来查询的需求差不多。这些存储天生都有聚合的功能。当然同时也可以提高查询性能,应对大访问量,比如redis这种抗量银弹。</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></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">1. 完整克隆</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个很简单就是将数据库A,全部拷贝一份到数据库B,这样的使用场景是离线统计跑任务脚本的时候可以。缺点也很突出,不适用于持续增长的数据。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">2. 标记同步</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个是业务场景比较简单的时候,理想情况下数据不会发生改变,比如日志数据,这个时候可以去标记,比如时间戳,这样当发生故障的时候还可以回溯到上一次同步点,开始重新同步数据。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">3. binlog方式</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">通过实时的订阅MySQL的binlog日志,消费到这些日志后,重新构建数据结构插入一个新的数据库或者是其他存储比如es、slor等等。订阅binlog日志可以比较好的能保证数据的一致性。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">4. MQ方式</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">业务数据写入DB的同时,也发送MQ一份,也就是业务里面实现双写。这种方式比较简单,但也很难保证数据一致性,对简单的业务场景可以采用这种方式。</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);">binlog方式</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.6746143057503506" data-w="713" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/e8830ba86dd412875ed2ed1e29c0d865.png"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> canal异构方式 </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;">binglog是数据的日志记录方式,每次对数据的操作都会有binlog日志。现在开源的订阅binlog日志的组件,比如使用比较广泛的canal,它是阿里开源的基于mysql数据库binlog的增量订阅和消费组件。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">由于cannal服务器目前读取的binlog事件只保存在内存中,并且只有一个canal客户端可以进行消费。所以如果需要多个消费客户端,可以引入activemq或者kafka。如上图绿色虚线框部分。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们还需要确保全量对比来保证数据的一致性(canal+mq的重试机制基本可以保证写入异构库之后的数据一致性),这个时候可以有一个全量同步WORKER程序来保证,如上图深绿色部分。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">canal的工作原理</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">先来看下mysql主备(主从)复制原理如下图,在此原理基础之上我们再来理解canal的实现原理就一眼能明白了。</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.6699604743083004" data-w="506" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/bfc55c654fce37a9287c81aea783235b.jpg"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> mysql主备复制实现原理 </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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">mysql主备(主从)复制原理,从上层来看,复制分成三步:</span></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">slave将master的binary log events拷贝到它的中继日志(relay log);</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">slave重做中继日志中的事件,将改变反映它自己的数据。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">再来看下canal的原理,如下图:</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.46308724832214765" data-w="894" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/145e3605e7f3cc1a86cc0bbb00d5e7c0.jpg"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> canal工作原理 </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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">cannal实现原理相对比较简单(参照上面的mysql主备复制实现原理):</span></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">mysql master收到dump请求,开始推送binary log给slave(也就是canal)</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">canal解析binary log对象(原始为byte流)</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们在部署canal server的时候要部署多台,来保证高可用。但是canal的原理,是只有一台服务器在跑处理,其它的服务器作为热备。canal server的高可用是通过zookeeper来维护的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">有关canal更具体的使用和详细原理请参照:https://github.com/alibaba/canal</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">注意点</span><span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 确认MySQL开启binlog,使用 <span style="font-weight: 700;color: rgb(248, 57, 41);">show variables like 'log_bin';</span> 查看ON为已开启 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 确认目标库可以产生binlog, <span style="font-weight: 700;color: rgb(248, 57, 41);">show master status</span> 注意Binlog_Do_DB,Binlog_Ignore_DB参数 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 确认binlog格式为ROW,使用 <span style="font-weight: 700;color: rgb(248, 57, 41);">show variables like 'binlog_format';</span> 非ROW模式登录MySQL执行 <span style="font-weight: 700;color: rgb(248, 57, 41);">set global binlog_format=ROW; flush logs;</span> 或者通过更改MySQL配置文件并重启MySQL生效。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 为保证binlake服务可以获取Binlog,需添加授权,执行 <span style="font-weight: 700;color: rgb(248, 57, 41);">GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'admin'@'%' identified by 'admin'; FLUSH PRIVILEGES;</span> </section></li> </ul> <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);">MQ方式</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="1.083657587548638" data-w="514" style="border-top-left-radius: 6px;border-top-right-radius: 6px;border-bottom-right-radius: 6px;border-bottom-left-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/18d0a4f92de8dcd93ab59328c7a0a30e.png"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> MQ异构方式 </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;">mq的方式,就相对简单,实际上是在业务逻辑中写DB的同时去写一次MQ,但是这种方式不能够保证数据一致性,就是不能保证跨资源的事务。<span style="font-weight: 700;color: rgb(248, 57, 41);">注:调用第三方远程RPC的操作一定不要放到事务中。</span></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></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">本文主要叙述了数据异构的使用场景,方法。这里面涉及到的activemq以及canal并没有深入分析,关于这块的内容可以直接参考相关具体文档,文中已给了链接地址。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">根据数据异构的定义,将数据异地构建存储,我们可以应用的地方就非常多,文中说的分库分表之后按照其它维度来查询的时候,我们想脱离DB直接用缓存比如redis来抗量的时候。数据异构这种方式都能够很好的帮助我们来解决诸如此类的问题。</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></h2> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247518108&amp;idx=1&amp;sn=006365f9f0a4ec117cfd49c16fb42e4c&amp;chksm=fcf75851cb80d147f5d85ea33be318158c247b45381061cea47d04170cfb7309b8ff331b6559&amp;token=1204159206&amp;lang=zh_CN&amp;scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">Netty 如何做到单机百万并发?</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247518201&amp;idx=1&amp;sn=fe4c6ff32e519b4b0c9e472dcd7aa8e1&amp;chksm=fcf75834cb80d122135364dbaf7199803f5e6acdfd9a6ce2d814e28ee6b5b127d8484823da4c&amp;token=1146871646&amp;lang=zh_CN&amp;scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">最安全的加密算法 Bcrypt,再也不用担心数据泄密了~</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247503249&amp;idx=1&amp;sn=b33ae3ff70a08b17ee0779d6ccb30b53&amp;chksm=fcf7125ccb809b4aa4985da09e620e06c606754e6a72681c93dcc88bdc9aa7ba0cb64f52dbc3&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">实战干货!Spring Cloud Gateway 整合 OAuth2.0 实现分布式统一认证授权!</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247514933&amp;idx=1&amp;sn=374da0ea32321baf6938ff2e611d8fce&amp;chksm=fcf764f8cb80edee2a0c493f58570b1502fb093ccd38fd498de1f6c1213e24e0355d8bcd713f&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">从实现原理来讲,Nacos 为什么这么强?</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247498039&amp;idx=1&amp;sn=3a3caee655ff015b46249bd51aa4dc79&amp;chksm=fcf726facb80afecea4d48faf94a9940b80ba21b325510cf4be6f7c7bce2f3c73266857f65d1&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">阿里限流神器Sentinel夺命连环 17 问?</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247496653&amp;idx=1&amp;sn=7185077b3bdc1d094aef645d677ec472&amp;chksm=fcf72c00cb80a516a8d1bc3b89400e202f2cbc1fd465e6c51e84a9a3543ec1c8bcfe8edeaec2&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">openFeign夺命连环9问,这谁受得了?</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247499894&amp;idx=1&amp;sn=f1606e4c00fd15292269afe052f5bca2&amp;chksm=fcf71fbbcb8096ad349e6da50b0b9141964c2084d0a38eba977fe8baa3fbe8af3b20c7591110&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">Spring Cloud Gateway夺命连环10问?</a> </section></li> </ol> </section> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU3MDAzNDg1MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/19cc2hfD2rA07Je2pY1o0ic2KcPRn44icO8GVcKRdwiaYvrE6bNeTbWPicyV7c7jWmSyzsiaWASjjckzBcsJMJw06pA/0?wx_fmt=png" data-nickname="码猿技术专栏" data-alias="oneswholife" data-signature="前蚂蚁P8,纯粹的技术人,以专栏的形式分享java全栈技术:SSM、Spring全家桶、微服务、MySQL、分布式、中间件、Linux、偶尔讲点运维Jenkins、Nexus、Docker、ELK.." data-from="0"></mp-common-profile> </section> <p style="text-align: right;"><span style="color: rgb(248, 57, 41);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-weight: 700;letter-spacing: 0.8px;text-align: right;word-spacing: 0.8px;background-color: rgb(255, 255, 255);"></span></p> <p style="text-align: right;"><span style="color: rgb(248, 57, 41);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-weight: 700;letter-spacing: 0.8px;text-align: right;word-spacing: 0.8px;background-color: rgb(255, 255, 255);">如果你喜欢这篇文章,请帮忙点赞转发支持,感谢~</span></p>

vivo 全球商城:电商平台通用取货码设计

作者:微信小助手

<section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzI4NjY4MTU5Nw==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/4g5IMGibSxt45QXJZicZ9gaNU2mRSlvqhQd94MJ7oQh4QFj1ibPV66xnUiaKoicSatwaGXepL5sBDSDLEckicX1ttibHg/0?wx_fmt=png" data-nickname="vivo互联网技术" data-alias="vivoVMIC" data-signature="分享 vivo 互联网技术干货与沙龙活动,推荐最新行业动态与热门会议。" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <p><br></p> <section style="font-size: 15px;line-height: 1.6;box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;"> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);font-size: 14px;text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">vivo官网商城开发团队 - Zhou Longjian</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 1px solid rgb(65, 94, 255);font-size: 17px;color: rgb(65, 94, 255);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">一、背景</p> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">随着O2O线上线下业务的不断扩展,电商平台也在逐步完善交易侧相关的产品功能。在最近的需求版本中,业务方为进一步提升用户的使用体验,规划了取货码生成及订单核销相关逻辑,目的是让线上的用户在付完款之后能够到店取货或者安排导购派送。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">日常生活中,我们对取货码、核销这类功能使用的经历大部分都来自:看电影前取票、吃饭后出示券码、快递柜取包裹等等,它们都有一些类似的特点,比如:</p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: right;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);height: auto;box-sizing: border-box;"> <section style="text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <ul class="list-paddingleft-1" style="list-style-type: disc;box-sizing: border-box;"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">取货码长度相对较短,比起动辄十几二十位订单号,几位的数字码更方便记忆和输入;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">除了数字取货码,还提供二维码,方便终端进行扫描并核销。</p></li> </ul> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">取货码使用起很简单,然而像“冰山”一样,隐藏在简单外表下面却需要严谨的设计和细致的逻辑,可以说麻雀虽小五脏俱全。本文介绍的设计也比较有趣,而且按此思路可以实现市面上大多数核销类券码的生成,同时也能满足业务的SaaS化,算是一个相对通用的能力,在此把整个设计分享给大家。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.684375" data-s="300,640" src="/upload/d6e0143dc1e25ffadc174b195ee2b992.jpg" data-type="jpeg" data-w="640" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;text-align: center;" powered-by="xiumi.us"><span style="font-size: 14px;color: rgb(136, 136, 136);">(图片来源:<a target="_blank" href="https://pixabay.com/zh/photos/iceberg-antarctica-polar-ice-sea-404966/" textvalue="pixabay.com" linktype="text" imgurl="" tab="outerlink" data-linktype="2">pixabay.com</a>)</span></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 1px solid rgb(65, 94, 255);font-size: 17px;color: rgb(65, 94, 255);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">二、简单系统的单表业务</p> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">如果业务的体量不大,店铺流量比较小,未形成平台的规模,比如给个体经营者使用的系统。那么取货码或券码的实现就比较简单,跟订单共享一张大横表或者使用扩展表跟订单进行关联就行了,这个阶段也无需做过度设计。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">表的设计如下图:</p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.2125" data-s="300,640" src="/upload/39104f37ce3d05c4244984c7263ab824.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">不过需要注意的是一般订单号都是比较长的,通常都在十几二十位(当然也有比较短的订单号,如果订单号比较短,取货码也可采用订单号)我们假设订单号18位,取货码8位,即订单号的取值范围远大于取货码,那么在订单号的生命周期内,取货码是有很大几率存在重复的。解决起来相对简单,我们只需要保证在任意条件下,<strong style="box-sizing: border-box;">未核销</strong>状态的数字码不重复即可,也即已核销的数字码可以回收利用。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">那么取货码的生成逻辑就很清晰了,下面用伪代码模拟真实的实现逻辑:</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">伪代码实现</p> </section> </section> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> (;;) {</span></code><code><span class="code-snippet_outer"> step1 获取随机码:String code = this.getRandomCode();</span></code><code><span class="code-snippet_outer"> step2 执行SQL:SELECT COUNT(1) FROM order_main WHERE code = <span class="code-snippet__variable">${code}</span> AND write_off_status = 0;</span></code><code><span class="code-snippet_outer"> step3 判断是否可以插入:<span class="code-snippet__keyword">if</span> ( count &gt; 0) { <span class="code-snippet__built_in">continue</span>; }</span></code><code><span class="code-snippet_outer"> step4 执行数据写入:UPDATE order_main SET code = <span class="code-snippet__variable">${code}</span>, qr_code = <span class="code-snippet__variable">${qrCode}</span>, write_off_status = 0 WHERE order_no = <span class="code-snippet__variable">${orderNo}</span></span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">*注意:</strong>这里step2和step4不是原子操作,存在并发问题,实际应用中最好使用分布式锁,把操作锁住。</p> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 1px solid rgb(65, 94, 255);font-size: 17px;color: rgb(65, 94, 255);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">三、&nbsp;复杂平台的分库分表业务</p> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">通过简单的单表设计,我们能管窥一斑,了解取货码大致的实现逻辑。不过我们在把简单方案往大型项目上进行落地的时候,就需要考虑很多方面,设计也需要更精巧。SaaS化的电商平台会比简单的单表业务复杂很多,重点体现在:</p> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <section style="font-size: 14px;box-sizing: border-box;" powered-by="xiumi.us"> <ol class="list-paddingleft-1" style="list-style-type: decimal;box-sizing: border-box;"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">&nbsp;SaaS 产品涉及的店铺很多且订单量大,需要设计大容量存储,所以订单表基本使用分库分表,显然作为订单附属的取货码表也得使用相同的策略;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">B端和C端用户的体验非常重要,服务端接口的设计需要充分考虑鲁棒性,完善最基本的重试及容错能力;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">不同业务方对于取货码的要求可能不太一样,取货码的设计需要具有通用性以及个性化的配置属性。</p></li> </ol> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="font-size: 16px;color: rgb(65, 95, 255);box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">3.1 详细设计</p> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">取货码表的设计推荐使用和订单一致的分库分表策略,好处是:</p> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <ol class="list-paddingleft-1" style="list-style-type: decimal;box-sizing: border-box;" powered-by="xiumi.us"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">&nbsp;和订单一样,支撑海量订单行的存储;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">&nbsp;方便利用同样的分库分表因子进行查询(例如:open_id、member_id)。</p></li> </ol> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">在考虑落地实现上,我们遇到了第一个讨论的点,那就是取货码是做到“<strong style="box-sizing: border-box;">门店唯一</strong>”还是“<strong style="box-sizing: border-box;">全局唯一</strong>”?</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="font-size: 16px;color: rgb(65, 95, 255);box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">3.2 门店唯一方案</p> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">刚开始考虑使用类似饭馆取餐码类似的逻辑,保证取货码在各自门店保持唯一就行了。类似如下图交互,图中用户A和用户B持有相同的取货码,用户A、B分别去他们对应的店铺完成核销,整个交易过程就结束了。但是这得保证用户A和B能正确地在各自订单归属的店铺完成核销,显然这个方案是带有风险的!</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.41875" data-s="300,640" src="/upload/14b127c6c3ecfedbc4e106bbd1f19e35.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">下图所示的这种情况下,用户A、B也能正常核销,不过串单了,原本属于用户A的订单被用户B核销了。这种问题出现的本质原因在于纯粹的数字码无法带有用户的标识,虽然可以在核销前做人为的核验身份来避免,但依然属于高风险的系统设计,所以门店唯一方案不可取!</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.41875" data-s="300,640" src="/upload/a57046b7b9447248c45ecf01eeebd82.jpg" data-type="jpeg" data-w="1280" style="margin: 0px;padding: 0px;max-width: 100%;height: auto !important;vertical-align: bottom;color: rgb(51, 51, 51);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: center;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="font-size: 16px;color: rgb(65, 95, 255);box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">3.3 全局唯一方案</p> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">全局唯一方案风险小,但实现难度稍高一点。核心问题在于如何判定随机生成的取货码是全局唯一的,当然如果系统本身依赖ES这类存储介质,可以在插入前先查询ES,不过查询和写入ES对于实时性接口来说稍微有点重,没有直接查库表来得直接。假设某业务方分成了4个库4张表,总计16表,取货码的长度确定为8位,那如何在多库多表的Mysql中查询并保证全局唯一呢?遍历表的方式肯定不可取!</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.3578125" data-s="300,640" src="/upload/55c9649ee7784fe8f280c6ba2de72ce8.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">为解决上述的疑问,我们在设计的时候可以在取货码的编排上做点文章,如下步骤做具体详解:</strong></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">步骤①:</strong>&nbsp;可以将8位的取货码分成两个区域,<strong style="box-sizing: border-box;"><span style="text-decoration: underline;box-sizing: border-box;">“随机码区域”+“库表位置”</span></strong>,下图示例:</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.3578125" data-s="300,640" src="/upload/cddcdb35479c2da4326750ca96151736.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="text-align: left;margin-bottom: 0em;"><br></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">步骤②:</strong>&nbsp;随机码区域暂不介绍,我们来看下2位库表如何映射到4库4表组成的16张表中。</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">这里也有两套方案:</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【方案一】</strong>可以选择2位库表的首位作为库编号,末位作为表编号。好处是映射较为简单,但是容量不够大,如果分的库或表&gt;9,扩展就会有点麻烦。如下图,我们把末尾“12”逻辑映射到了“1库的编号为2的表”;</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.38294010889292196" data-s="300,640" src="/upload/9631cbac4ffa2eb80021244a4a7fbf76.jpg" data-type="jpeg" data-w="1102" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【方案二】</strong>将4库4表二维结构转成一维,以0为初始值进行递增,(0库, 0表)&nbsp;→ 00, &nbsp;(0库, 1表)&nbsp;→ 01... , &nbsp;(3库, 3表)&nbsp;→ 15。好处是容量变大了,最大支持99张表,不受库或表单一条件的限制,缺点就是映射逻辑写起来麻烦点,不过这不是问题。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.31953125" data-s="300,640" src="/upload/702ea56b59b3f7b886af1511ffdde96b.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">取货码经过简单编排,我们完成了取货码的到库表的映射逻辑,解决了取货码存取的问题。其实仔细想想,关于全局唯一的问题其实也解决掉了,我们只要保证前6位<strong style="box-sizing: border-box;">随机码</strong>在单表里保证唯一即可,理论上支持单表在未核销状态下范围为:000000 ~ 999999条记录,容量是足够的。关键我们把多库多表的查询就简化成了只跑一个SQL,效率大大提升。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="font-size: 16px;color: rgb(65, 95, 255);box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">3.4 方案落地遇到的问题</p> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">既然本篇是介绍SaaS化的完整方案,在落地的时候或多或少会遇到一些问题,这边介绍三个实际遇到的典型问题,并给出一些解决方案:</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">【问题一】</strong>使用Math.random()生成的6位随机码和表里的重复了,如何处理?</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">【解决】</strong>其实重复的情况有两种:</p> <ol class="list-paddingleft-1" style="list-style-type: decimal;box-sizing: border-box;"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">可能是表里已经存在数字相同未核销的取货码;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">另外一种情况就是别的事务在正在操作,正好有个分布式事务锁住了一样的数字码(概率很低,但是是有可能的)。</p></li> </ol> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">这两种情况的出现就需要我们进行优雅地重试了!大致思路如下伪代码:</p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="typescript"><code><span class="code-snippet_outer"><span class="code-snippet__comment">// step1 根据分库分表因子获取库表编号,userCode-用户编号、tenantId-租户编号</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">String</span> suffix = getCodeSuffix(userCode, tenantId);</span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">// step2 批量获取6位随机码</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> (int i=<span class="code-snippet__number">1</span>; i&lt;=<span class="code-snippet__number">5</span>; i++) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 批量获取随机数。每次重试,取2的指数级量进行过滤,相比暴力执行for循环,这种方式能减少和DB的交互</span></span></code><code><span class="code-snippet_outer"> List&lt;<span class="code-snippet__built_in">String</span>&gt; tempCodes = getRandomCodes(<span class="code-snippet__number">2</span> &lt;&lt; i);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 过滤掉分布式锁</span></span></code><code><span class="code-snippet_outer"> filterDistributeLock(tempCodes);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 过滤掉数据库存在的随机码</span></span></code><code><span class="code-snippet_outer"> filterExistsCodes(tempCodes);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> tempCodes;</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">// step3 处理随机码,随机码入库</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> (<span class="code-snippet__built_in">String</span> code : codes) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 加锁,判断加锁是否成功。推荐使用Redis分布式锁</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">boolean</span> hasLockd = isLocked(code);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">try</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 执行入库</span></span></code><code><span class="code-snippet_outer"> insert(object);</span></code><code><span class="code-snippet_outer"> } <span class="code-snippet__keyword">finally</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 解锁</span></span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">// step4 执行后置二维码图片等逻辑</span></span></code></pre> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br></p> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【注意】</strong></p> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <ol class="list-paddingleft-1" style="list-style-type: decimal;box-sizing: border-box;" powered-by="xiumi.us"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">推荐使用指数级重试的方式(2 &lt;&lt; i),逐次递增random的数量,减少和DB的交互;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">建议数字码生成完毕后加锁并执行INSERT,生成图片地址等耗时严重的动作可以后置UPDATE上去。</p></li> </ol> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">【问题二】</strong>项目中使用了分库分表的组件(比如:ShardingSphere-JDBC),怎么动态修改数据源?也就是同时支持分库分表因子(比如:member_id、open_id等)以及根据取货码计算的库表动态查询。</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【解决】</strong>我们以ShardingSphere-JDBC作为为案例来给出一些配置及伪代码,具体可以参考:《<a target="_blank" href="https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/special-api/sharding/hint/" textvalue="强制路由::ShardingSphere" linktype="text" imgurl="" tab="outerlink" data-linktype="2">强制路由::ShardingSphere</a>》,其他开源的分库分表组件或者自研产品不做赘述,可以自己手动写个插件,别怕,即使再难,也要相信有光!</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;">配置及伪代码</p> </section> </section> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="properties"><code><span class="code-snippet_outer"><span class="code-snippet__meta">//</span> <span class="code-snippet__string">ShardingSphere-JDBC依赖的配置文件jdbc-sharding.yaml</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">...</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">shardingRule</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">tables</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">...</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"> # 取货码表</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">order_code</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">actualDataNodes</span>: <span class="code-snippet__string">DS00$-&gt;{0..3}.order_pick_up_0$-&gt;{0..3}</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"> # 配置库的计算逻辑</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">databaseStrategy</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">hint</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">algorithmClassName</span>: <span class="code-snippet__string">com.xxx.xxxxx.xxx.service.impl.DbHintShardingAlgorithm</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"> # 配偶之表的计算逻辑</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">tableStrategy</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">hint</span>:<span class="code-snippet__string"></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">algorithmClassName</span>: <span class="code-snippet__string">com.xxx.xxxxx.xxx.service.impl.DbHintShardingAlgorithm</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">...</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">//</span> <span class="code-snippet__string">java代码</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">try</span> <span class="code-snippet__string">(HintManager hintManager = HintManager.getInstance()) {</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__meta">hintManager.addDatabaseShardingValue("order_code"/**</span> <span class="code-snippet__string">取货码表 */, DbHintShardingAlgorithm.calDbShardingValue(tenantId, code));</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__meta">hintManager.addTableShardingValue("order_code"/**</span> <span class="code-snippet__string">取货码表 */, DbHintShardingAlgorithm.calTabShardingValue(tenantId, code));</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"> <span class="code-snippet__attr">Object</span> <span class="code-snippet__string">xxx = xxxMapper.selectOne(queryDTO);</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">}</span></span></code></pre> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【注意】</strong></p> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: transparent;padding: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <ol class="list-paddingleft-1" style="list-style-type: decimal;box-sizing: border-box;" powered-by="xiumi.us"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">这里介绍一种编程式的解决方案,好处是配置简单、比较灵活,缺点就是代码稍微多一点。其实ShardingSphere还支持注解的方式,可以自己研究下;</p></li> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">第一条说了比较灵活,体现在自己实现的 “DbHintShardingAlgorithm.calDbShardingValue(tenantId, code)” 方法上,这个方法可以自己定义,所以我们的入参可以是通用的分库分表因子,也可以是自定义的取货码的“库表位置”字段,非常灵活。</p></li> </ol> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin: 10px 0% 8px;text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(219, 219, 219);border-bottom-left-radius: 0px;padding: 0px 0px 0px 8px;align-self: flex-start;flex: 0 0 auto;box-sizing: border-box;"> <section style="color: rgba(0, 0, 0, 0.5);text-align: justify;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;">【问题三】</strong>如何做到更强的扩展性,适用SaaS平台以及不同的业务场景?</p> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><strong style="box-sizing: border-box;">【解决】</strong>细心的小伙伴应该注意到了 "tenantId" 这个字段,这是个租户的编码,在实际编码会进行透传。我们可以利用这个字段针对不同的租户(或叫业务方)来做不同的配置,比如:取货码的长度、取货码编排的方式、取货码映射库表位置的策略等等做成可配,只要把主干逻辑进一步抽象,并使用策略模式进行个性化编码。</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 1px solid rgb(65, 94, 255);font-size: 17px;color: rgb(65, 94, 255);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">四、总结</p> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us">实现取货码逻辑的时候,发现网上券码这块的方案、技术文章比较少,当时萌生了写篇文章抛砖引玉做个分享的想法。事实上,我相信大多数公司可能或多或少也是这么做的,哪怕采取了别的方案也能殊途同归。本篇文章整体只是介绍了一个思路,而这个思路类似一个简化版的订单分库分表,但这就是神奇所在,事实上我们还可以将一些常用的技术方案落地到不同的应用场景,大胆地做一些尝试,多走一些未曾设想过的道路!</p> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: top;width: 40%;box-sizing: border-box;"> <section style="margin: 0.5em 0px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-top: 1px dotted rgb(160, 160, 160);box-sizing: border-box;"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> <section style="display: inline-block;vertical-align: top;width: 20%;box-sizing: border-box;"> <section style="text-align: center;color: rgb(160, 160, 160);font-size: 11px;box-sizing: border-box;" powered-by="xiumi.us"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">END</p> </section> </section> <section style="display: inline-block;vertical-align: top;width: 40%;box-sizing: border-box;"> <section style="margin: 0.5em 0px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-top: 1px dotted rgb(160, 160, 160);box-sizing: border-box;"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> </section> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;" powered-by="xiumi.us"><br style="box-sizing: border-box;"></p> <section style="margin-top: 10px;margin-bottom: 10px;text-align: left;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-left: 1em;padding-right: 1em;display: inline-block;text-align: center;box-sizing: border-box;"> <span style="display: inline-block;padding: 0.3em 0.5em;border-radius: 0.5em;background-color: rgb(65, 94, 255);color: rgb(255, 255, 255);box-sizing: border-box;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:91.title1"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">猜你喜欢</p></span> </section> <section style="border-width: 1px;border-style: solid;border-color: transparent;margin-top: -1em;padding: 20px 10px 10px;background-color: rgb(239, 239, 239);text-align: center;box-sizing: border-box;"> <section style="font-size: 14px;text-align: left;box-sizing: border-box;" powered-by="xiumi.us"> <ul class="list-paddingleft-1" style="list-style-type: disc;box-sizing: border-box;"> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247493253&amp;idx=2&amp;sn=e82aad1dee7132e61b0553068c764857&amp;chksm=ebdb9617dcac1f0130dab997e97be879b24dcd2deccafdfbdafa0684fc8a68d8e015bee5f8d4&amp;scene=21#wechat_redirect" textvalue="vivo全球商城全球化演进之路—多语言解决方案" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo全球商城全球化演进之路—多语言解决方案</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247492304&amp;idx=1&amp;sn=4f2a666cd60ce0297db5c20a763cb4b9&amp;chksm=ebdb9242dcac1b54e234786ee3b2d60a873f304ee5c562410e95fbc4ef21f969c0113c7189e0&amp;scene=21#wechat_redirect" textvalue="vivo 全球商城:商品系统架构设计与实践" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo 全球商城:商品系统架构设计与实践</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247491988&amp;idx=1&amp;sn=d1f28063c64ce619251d3af175a9e8ed&amp;chksm=ebdb9106dcac181074e664617a2f336a307636768f24f5f39d66fed25c33eaf3a3d75c209772&amp;scene=21#wechat_redirect" textvalue="vivo全球商城-营销价格监控方案的探索" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo全球商城-营销价格监控方案的探索</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247491631&amp;idx=1&amp;sn=b53c69df13a80c6bf37531e0c3788188&amp;chksm=ebdb90bddcac19ab3dae9eb635089644d6032dfc4394c3f9bcfedf837060eaeb8c5a4d70c532&amp;scene=21#wechat_redirect" textvalue="vivo 全球商城:优惠券系统架构设计与实践" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo 全球商城:优惠券系统架构设计与实践</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247488750&amp;idx=1&amp;sn=b27f527b67a6f1e3c4fec388628c4cde&amp;chksm=ebd8647cdcafed6a5fbaa7457f6a9700a7c57c7a5f4aa33d02ef643b27e6afab8d538e8cd5ba&amp;scene=21#wechat_redirect" textvalue="vivo 全球商城:订单中心架构设计与实践" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo 全球商城:订单中心架构设计与实践</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247488642&amp;idx=1&amp;sn=10de80af856ff83c8e1c83f94b0edd0d&amp;chksm=ebd86410dcafed068ce11101ffda73488e28d0db3fab2d77756f5891ee637d7935dbe5a3b969&amp;scene=21#wechat_redirect" textvalue="vivo 全球商城:从 0 到 1 代销业务的融合之路" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo 全球商城:从 0 到 1 代销业务的融合之路</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&amp;mid=2247488600&amp;idx=1&amp;sn=3d97f0a90469c4ed76a387d14c6c385b&amp;chksm=ebd864cadcafeddcd2f00ecf0da396b486f678b7effa7453dc70e6a96ebbf3b3ffa2f0b0e77c&amp;scene=21#wechat_redirect" textvalue="vivo 全球商城:架构演进之路" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">vivo 全球商城:架构演进之路</a></p></li> </ul> </section> </section> </section> </section>

面试官问:select......for update会锁表还是锁行?

作者:微信小助手

<section style="line-height: 1.75em;"> <span style="font-size: 15px;">select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">那么它加的是行锁还是表锁,这就要看是不是用了索引/主键。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">没用索引/主键的话就是表锁,否则就是是行锁。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 0, 0);"><strong><span style="color: rgb(255, 0, 0);font-size: 15px;">验证:</span></strong></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">建表sql</span> </section> <section style="text-align: center;margin-bottom: 0em;line-height: 1.75em;"> <img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.38422818791946306" data-s="300,640" src="/upload/c768783488b6aaf041d48113f00bfbb7.png" data-type="png" data-w="1192" style=""> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">需要关闭自动提交,通过set @@autocommit=0;&nbsp; &nbsp;设置为手动提交。0代表手动提交,1代表自动提交。</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.577922077922078" src="/upload/19a80d1948f0cbe35e2c403d50bd9fa8.png" data-type="png" data-w="616"> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;">结合一下实例验证<br></span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 0, 0);"><strong><span style="color: rgb(255, 0, 0);font-size: 15px;">实例1:</span></strong></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">使用主键id为条件去查询,然后开启另一个事务去更新数据,更新被阻塞,加锁了,锁定要查询的id为1的行数据。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;">&nbsp;图一为第一个事务,并且没有提交事务<br></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">&nbsp;图二为第二个事务,去更新数据,被阻塞了</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">&nbsp;图三为第二个事务,长时间拿不到锁报错。</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.28493150684931506" src="/upload/9d61917dca559bb7c8055f7cfede843b.png" data-type="png" data-w="730"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.358356940509915" src="/upload/d36684915898f83fc8fcb789aafe13a.png" data-type="png" data-w="706"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.33008356545961004" src="/upload/bc05cc450c0b89e0f45573e68c28897.png" data-type="png" data-w="718"> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 0, 0);"><strong><span style="color: rgb(255, 0, 0);font-size: 15px;">实例2:</span></strong></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">我们在开启一个事务对另一条id为2的数据进行更新,</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.23825136612021858" src="/upload/ef6d3b0ba4a5d3687b2b1cb84b47cb7.png" data-type="png" data-w="915"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.2712082262210797" src="/upload/d052fe2829302d9a3d23c6b96027eac8.png" data-type="png" data-w="778"> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(255, 0, 0);">实例3(索引):</span></strong> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">&nbsp;一开始的创建表就age创建了唯一索引。</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.19591346153846154" src="/upload/962d1a6da16abe17f45c6cc4c6d1016e.png" data-type="png" data-w="832"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.31181619256017507" src="/upload/c301aed679a09605f6e0ab41c39114ab.png" data-type="png" data-w="914"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.29362880886426596" src="/upload/17295152c8342d560a1a402e0901125d.png" data-type="png" data-w="722"> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 0, 0);"><strong><span style="color: rgb(255, 0, 0);font-size: 15px;">实例4:</span></strong></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">&nbsp;使用普通的字段code去操作</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.32192846034214617" src="/upload/53232617d8f13e58cb93fe4405613218.png" data-type="png" data-w="643"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.3333333333333333" src="/upload/ad4fb7372615a0f48e18794b5847b2f.png" data-type="png" data-w="771"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.2708333333333333" src="/upload/b980ca91a37926d3872ad1dcc7578388.png" data-type="png" data-w="816"> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">另一个事务我去更新另外一条数据,如果我更新成功了,就是锁行,失败了就是锁表。</span> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.2148876404494382" src="/upload/4ab4d0e6547300336ac544d71e75e771.png" data-type="png" data-w="712"> </section> <section style="line-height: 1.75em;"> <img class="rich_pages wxw-img" data-ratio="0.2948207171314741" src="/upload/556e7179a93456f512a6d5271eb4e585.png" data-type="png" data-w="753"> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 0, 0);"><strong><span style="color: rgb(255, 0, 0);font-size: 15px;">结果:</span></strong></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">如果查询条件用了索引/主键,那么select ..... for update就会进行行锁。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">如果是普通字段(没有索引/主键),那么select ..... for update就会进行锁表。</span> </section>

DevOps整合Jenkins+k8s+CICD

作者:微信小助手

<section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-bottom: 24px;" 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: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"> <h3 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">一、DevOps介绍</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">软件开发最开始是由两个团队组成:</p> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.8em;color: rgb(102, 102, 102);border-left-width: 6px;border-left-color: rgb(33, 152, 99);background: rgb(247, 247, 247);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="font-size: inherit;color: inherit;line-height: inherit;">开发计划由开发团队从头开始设计和整体系统的构建。需要系统不停的迭代更新。<br>运维团队将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。<br>这看似两个目标不同的团队需要协同完成一个软件的开发。<br>在开发团队指定好计划并完成coding后,需要提供到运维团队。<br>运维团队向开发团队反馈需要修复的BUG以及一些需要返工的任务。<br>这时开发团队需要经常等待运维团队的反馈。这无疑延长了事件并推迟了整个软件开发的周期。<br>会有一种方式,在开发团队等待的时候,让开发团队转移到下一个项目中。等待运维团队为之前的代码提供反馈。<br>可是这样就意味着一个完整的项目需要一个更长的周期才可以开发出最终代码。</p> <hr style="font-size: inherit;color: inherit;line-height: inherit;height: 1px;margin-top: 1.5rem;margin-bottom: 1.5rem;border-right: none;border-bottom: none;border-left: none;border-top-style: dashed;border-top-color: rgb(165, 165, 165);"> <p style="font-size: inherit;color: inherit;line-height: inherit;">基于现在的互联网现状,更推崇敏捷式开发,这样就导致项目的迭代速度更快,但是由于开发团队与运维团队的沟通问题,会导致新版本上线的时间成本很高。这又违背的敏捷式开发的最初的目的。<br>那么如果让开发团队和运维团队整合到成一个团队,协同应对一套软件呢?这就被称为DevOps。<br>DevOps,字面意思是Development &amp;Operations的缩写,也就是开发&amp;运维。<br>然字面意思只涉及到了开发团队和运维团队,其实QA测试团队也是参与其中的。<br>网上可以查看到DevOps的符号类似于一个无穷大的符号</p> </blockquote> <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.46926713947990545" src="/upload/1caf90da7a560dac65500c6bb838f24.png" data-type="png" data-w="846"></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">这表明DevOps是一个不断提高效率并且持续不断工作的过程</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">DevOps的方式可以让公司能够更快地应对更新和市场发展变化,开发可以快速交付,部署也更加稳定。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">核心就在于简化Dev和Ops团队之间的流程,使整体软件开发过程更快速。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">整体的软件开发流程包括:</p> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.8em;color: rgb(102, 102, 102);border-left-width: 6px;border-left-color: rgb(33, 152, 99);background: rgb(247, 247, 247);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="font-size: inherit;color: inherit;line-height: inherit;">PLAN:开发团队根据客户的目标制定开发计划<br>CODE:根据PLAN开始编码过程,需要将不同版本的代码存储在一个库中。<br>BUILD:编码完成后,需要将代码构建并且运行。<br>TEST:成功构建项目后,需要测试代码是否存在BUG或错误。<br>DEPLOY:代码经过手动测试和自动化测试后,认定代码已经准备好部署并且交给运维团队。<br>OPERATE:运维团队将代码部署到生产环境中。<br>MONITOR:项目部署上线后,需要持续的监控产品。<br>INTEGRATE:然后将监控阶段收到的反馈发送回PLAN阶段,整体反复的流程就是DevOps的核心,即持续集成、持续部署。</p> </blockquote> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">为了保证整体流程可以高效的完成,各个阶段都有比较常见的工具,如下图:</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.5092272202998847" src="/upload/881257c2f16669e578690f941021c723.png" data-type="png" data-w="1734"></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">最终可以给DevOps下一个定义:DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">自动化的工具协作和沟通来完成软件的生命周期管理</p> <h3 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">二、安装git工具</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">serverA主机安装</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在code阶段,我们需要将不同版本的代码存储到一个仓库中,常见的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">2.1 Git安装</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;">https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//git-scm.com/(傻瓜式安装)</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">2.2 GitLab安装</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">单独准备服务器,采用Docker安装</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">查看GitLab镜像</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(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">docker</span>&nbsp;search&nbsp;gitlab<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">拉取GitLab镜像</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(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">docker</span>&nbsp;pull&nbsp;gitlab/gitlab-ce<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">准备docker-compose.yml文件</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(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">mkdir</span>&nbsp;-p&nbsp;/data/git<br>vim&nbsp;/data/git/docker-compose.yml<br><br>version:&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'3.1'</span><br>services:<br>&nbsp;&nbsp;gitlab:<br>&nbsp;&nbsp;&nbsp;&nbsp;image:&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'gitlab/gitlab-ce:latest'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;container_name:&nbsp;gitlab<br>&nbsp;&nbsp;&nbsp;&nbsp;restart:&nbsp;always<br>&nbsp;&nbsp;&nbsp;&nbsp;environment:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GITLAB_OMNIBUS_CONFIG:&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;external_url&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'http://10.1.100.225:8929'</span><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#自己安装git的服务器IP</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gitlab_rails[<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'gitlab_shell_ssh_port'</span>]&nbsp;=&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">2224</span><br>&nbsp;&nbsp;&nbsp;&nbsp;ports:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'8929:8929'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'2224:2224'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;volumes:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'./config:/etc/gitlab'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'./logs:/var/log/gitlab'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'./data:/var/opt/gitlab'</span><br><br>启动容器(需要稍等一小会……)<br><br>docker-compose&nbsp;up&nbsp;-d<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">访问GitLab首页</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;">http:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//10.1.100.225:8929</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">查看root用户初始密码</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;">docker&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">exec</span>&nbsp;-it&nbsp;gitlab&nbsp;cat&nbsp;/etc/gitlab/initial_root_password<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">第一次登录后需要修改密码</p> <h3 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;"><img class="rich_pages wxw-img" data-ratio="0.3630843958712811" src="/upload/4b1c7880bf9428bc9309e0d0f0bdbf0a.png" data-type="png" data-w="1647"></span></h3> <h3 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">三、安装jdk 、maven、Jenkins</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">1.安装jdk 和maven</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">JDK包下载地址:Java Downloads | Oracle<br>MAven下载地址:Maven – Download Apache Maven</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:

为什么 Spring 和 IDEA 都不推荐使用 @Autowired 注解?

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;margin-bottom: 0px;" 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;">大家在使用IDEA开发的时候有没有注意到过一个提示,在字段上使用Spring的依赖注入注解<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired</code>后会出现如下警告</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">Field injection is not recommended (字段注入是不被推荐的)</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">但是使用<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Resource</code>却不会出现此提示</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> <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);">Spring常见的DI方式</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">构造器注入</span>:利用构造方法的参数注入依赖 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">Setter注入</span>:调用Setter的方法注入依赖 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">字段注入</span>:在字段上使用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired/Resource</code>注解 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;"><span style="color: rgb(248, 57, 41);">@Autowired VS @Resource</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">事实上,他们的基本功能都是通过注解实现<span style="font-weight: 700;color: rgb(248, 57, 41);">依赖注入</span>,只不过<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired</code>是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">Spring</code>定义的,而<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Resource</code>是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">JSR-250</code>定义的。大致功能基本相同,但是还有一些细节不同:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">依赖识别方式</span>: <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired</code>默认是 <span style="font-weight: 700;color: rgb(248, 57, 41);">byType</span>可以使用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Qualifier</code>指定Name, <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Resource</code> <span style="font-weight: 700;color: rgb(248, 57, 41);">默认ByName</span>如果 <span style="font-weight: 700;color: rgb(248, 57, 41);">找不到则ByType</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">适用对象</span>: <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired</code>可以对 <span style="font-weight: 700;color: rgb(248, 57, 41);">构造器、方法、参数、字段</span>使用, <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Resource</code>只能对 <span style="font-weight: 700;color: rgb(248, 57, 41);">方法、字段</span>使用 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">提供方</span>: <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Autowired</code>是 <span style="font-weight: 700;color: rgb(248, 57, 41);">Spring</span>提供的, <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Resource</code>是 <span style="font-weight: 700;color: rgb(248, 57, 41);">JSR-250</span>提供的 </section></li> </ul> <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);">各种DI方式的优缺点</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;">参考Spring官方文档,建议了如下的使用场景:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <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>(各依赖不会经常变动) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">Setter注入</span>: <span style="font-weight: 700;color: rgb(248, 57, 41);">可选</span>(没有此依赖也可以工作), <span style="font-weight: 700;color: rgb(248, 57, 41);">可变</span>(依赖会经常变动) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">Field注入</span>:大多数情况下尽量 <span style="font-weight: 700;color: rgb(248, 57, 41);">少使用</span>字段注入,一定要使用的话, <span style="font-weight: 700;color: rgb(248, 57, 41);">@Resource相对@Autowired</span>对IoC容器的 <span style="font-weight: 700;color: rgb(248, 57, 41);">耦合更低</span> </section></li> </ul> <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);">Field注入的缺点</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">不能像构造器那样注入不可变的对象</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">依赖对外部不可见</span>,外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 会导致 <span style="font-weight: 700;color: rgb(248, 57, 41);">组件与IoC容器紧耦合</span>(这是最重要的原因,离开了IoC容器去使用组件,在注入依赖时就会十分困难) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 导致 <span style="font-weight: 700;color: rgb(248, 57, 41);">单元测试也必须使用IoC容器</span>,原因同上 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">依赖过多时不够明显</span>,比如我需要10个依赖,用构造器注入就会显得庞大,这时候应该考虑一下此组件是不是 <span style="font-weight: 700;color: rgb(248, 57, 41);">违反了单一职责原则</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;"><span style="color: rgb(248, 57, 41);">为什么IDEA只对@Autowired警告</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Field注入虽然有很多缺点,但它的好处也不可忽略:那就是<span style="font-weight: 700;color: rgb(248, 57, 41);">太方便了</span>。使用构造器或者setter注入需要写更多业务无关的代码,十分麻烦,而字段注入大幅简化了它们。并且绝大多数情况下业务代码和框架就是强绑定的,完全松耦合只是一件理想上的事,牺牲了敏捷度去过度追求松耦合反而得不偿失。</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">那么问题来了,为什么IDEA只对@Autowired警告,却对@Resource视而不见呢?</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">个人认为</span>,就像我们前面提到过的:@Autowired<span style="font-weight: 700;color: rgb(248, 57, 41);">是</span>Spring<span style="font-weight: 700;color: rgb(248, 57, 41);">提供的,它是</span>特定IoC提供的特定注解<span style="font-weight: 700;color: rgb(248, 57, 41);">,这就导致了应用与框架的</span>强绑定<span style="font-weight: 700;color: rgb(248, 57, 41);">,一旦换用了其他的IoC框架,是</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: 0.8em;margin-bottom: 0.8em;">而 是提供的,它是,我们使用的IoC容器应当去兼容它,这样即使更换容器,也可以正常工作。</p> </section>

MySQL 上亿大表如何优化?

作者:微信小助手

<fieldset style="margin: 0.8em 33.5px 0.3em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;max-width: 100%;box-sizing: border-box;min-width: 0px;line-height: 25.6px;border-width: initial;border-style: initial;border-color: currentcolor;text-align: center;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg4NjYyODc4OA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/J4jTHmo8Xh6qM32ASOtVbXNoiaegrI26qLRw6r6FTI7dZw6TMT7vecvnjd1O8xSsM5MiajIuQZicxSC6KFK8TMpbg/0?wx_fmt=png" data-nickname="java突击队" data-alias="" data-signature="技术经验分享" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> </fieldset> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="z-index: 1;display: flex;justify-content: center;align-items: center;height: 36px;border-width: 1px 0px;border-top-style: dotted;border-bottom-style: dotted;border-top-color: rgb(193, 205, 249);border-bottom-color: rgb(193, 205, 249);border-left-style: initial;border-left-color: initial;border-right-style: initial;border-right-color: initial;" data-mid="" mpa-from-tpl="t"> <section style="padding: 0px 12px;text-align: center;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #4468F8;line-height: 22px;" data-mid="" mpa-is-content="t">背景</p> </section> <section style="width: 7px;height: 9px;transform: rotate(180deg);" data-mid="" mpa-from-tpl="t"> <img data-ratio="1.2857142857142858" data-w="14" src="/upload/528d6047c1f8fc974a14ee4f59de28c0.png" style="display: block;"> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="color: rgb(89, 89, 89);letter-spacing: 1px;font-size: 16px;">XX 实例(一主一从)xxx 告警中每天凌晨在报 SLA 报警,该报警的意思是存在一定的主从延迟。(若在此时发生主从切换,需要长时间才可以完成切换,要追延迟来保证主从数据的一致性)</span> </section> <p style="line-height: normal;"><br></p> <p><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="color: rgb(89, 89, 89);letter-spacing: 1px;font-size: 16px;">XX 实例的慢查询数量最多(执行时间超过 1s 的 SQL 会被记录),XX 应用那方每天晚上在做删除一个月前数据的任务。</span> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="letter-spacing: 1px;color: rgb(89, 89, 89);font-size: 20px;"><br mpa-from-tpl="t"></span> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="z-index: 1;display: flex;justify-content: center;align-items: center;height: 36px;border-width: 1px 0px;border-top-style: dotted;border-bottom-style: dotted;border-top-color: rgb(193, 205, 249);border-bottom-color: rgb(193, 205, 249);border-left-style: initial;border-left-color: initial;border-right-style: initial;border-right-color: initial;" data-mid="" mpa-from-tpl="t"> <section style="width: 7px;height: 9px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1.2857142857142858" data-w="14" src="/upload/528d6047c1f8fc974a14ee4f59de28c0.png" style="display: block;"> </section> <section style="padding: 0px 12px;text-align: center;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #4468F8;line-height: 22px;" data-mid="" mpa-is-content="t">分析</p> </section> <section style="width: 7px;height: 9px;transform: rotate(180deg);" data-mid="" mpa-from-tpl="t"> <img data-ratio="1.2857142857142858" data-w="14" src="/upload/528d6047c1f8fc974a14ee4f59de28c0.png" style="display: block;"> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <br> </section> <p><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;font-size: 16px;">使用 pt-query-digest 工具分析最近一周的 mysql-slow.log:</span></p> <p><br></p> <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;"> <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;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">pt-query-digest&nbsp;--since=<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">148</span>h&nbsp;mysql-slow.<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span>&nbsp;|&nbsp;less<br></code></pre> </section> <p><br></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="letter-spacing: 1px;color: rgb(0, 82, 255);font-size: 16px;">结果第一部分:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages wxw-img" data-ratio="0.31118493909191586" data-type="png" data-w="903" src="/upload/5cf6d329705e9ae5a3d6221c607ba1f8.png" style="border-width: 0px;border-style: initial;border-color: initial;box-sizing: border-box !important;word-wrap: break-word !important;wi