文章列表

记一次拐弯阁僚的接口耗时异常排查过程

作者:微信小助手

<p style="white-space: normal;" data-mpa-powered-by="yiban.io"><strong style="font-size: 16px;text-align: left;"><span style="font-size: 15px;text-align: justify;color: rgb(171, 25, 66);">1 现象</span></strong></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;">某后端系统,处于整个调用链路偏后的位置,对接口性能有着比较严格的要求。因此对外承诺的三个 9 响应时间为 200 多毫秒。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;">然而,从某天开始一到上午流量高峰,服务耗时就报警。随机从集群内的某些机器上报了出来,过了流量高峰就好很多……</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;"><br></span></p> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><strong><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;text-align: justify;color: rgb(171, 25, 66);">2 问题排查</span></strong></h2> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;">一般排查接口耗时,基本都习惯从外部流量、相关内部接口、逻辑块耗时、底层存储耗时等接口层面来观察。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;">如果能在接口层面就找到了瓶颈是最理想的情况,否则就要从 JVM 层面来排查。比如线程运行异常、GC 异常等,势必要耗费更多精力了。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;"><br></span></p> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><strong><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;text-align: justify;color: rgb(171, 25, 66);">2.1 服务器性能、流量分配等外在因素</span></strong></h3> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;">虽然这类问题发生的概率比较小,但是看到几十台机器中只有几台在报。感觉还是有必要排查一下。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &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;text-align: justify;"><br></span></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="white-space: normal;text-align: left;"> <li style="white-space: normal;text-align: le

聊聊分布式任务调度系统

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;overflow-wrap: break-word;text-align: left;font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;padding-left: 5px;padding-right: 5px;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"> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);border-left-width: 2px;padding: 8px 10px 8px 15px;background: rgb(255, 249, 249);border-left-color: rgb(239, 112, 96);margin-top: 0px;margin-bottom: 20px;letter-spacing: 0.5444px;"> <p style="text-align: justify;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;font-size: 16px;margin-bottom: 10px;color: rgb(74, 74, 74);line-height: 30px;letter-spacing: 0.5444px;">我看过那么多所谓的教程,大部分都是教“如何使用工具”的,没有多少是教“如何制作工具”的,能教“如何仿制工具”的都已经是凤毛麟角,中国 软件行业,缺的是真正可以“制作工具”的程序员,而绝对不缺那些“使用工具”的程序员!...... &nbsp;”这个业界最不需要的就是“会使用XX工具的工程师”,而是“有创造力的软件工程师”!业界所有的饭碗,本质就是“有创造力的软件工程师”提供出来的啊!</p> </blockquote> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;letter-spacing: 0.5444px;margin-bottom: 20px;">写这篇文章,想和大家从头到脚说说任务调度,希望大家读完之后,能够理解实现一个任务调度系统的核心逻辑。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;padding: 0px 0.5em;"> <img class="rich_pages wxw-img" data-ratio="1.2636363636363637" src="/upload/c810c4ee85120e5544ce90fd96c41fc6.png" data-type="png" data-w="880" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"> </figure> <h1 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 24px;margin-top: 35px;margin-bottom: 20px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">1 Quartz</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;letter-spacing: 0.5444px;margin-bottom: 20px;">Quartz是一款Java开源任务调度框架,也是很多Java工程师接触任务调度的起点。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;letter-spacing: 0.5444px;margin-bottom: 20px;padding: 0px 0.5em;">下图显示了任务调度的整体流程:<img class="rich_pages wxw-img" data-ratio="0.9397590361445783" src="/upload/dbd36010de3388f3d9f0afe3187b02b7.png" data-type="png" data-w="1162" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;letter-spacing: 0.5444px;margin-bottom: 20px;">Quartz的核心是三个组件。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;color: black;list-style-type: square;padding-left: 1.2em;margin-bottom: 20px;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 任务:Job 用于表示被调度的任务; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 触发器:Trigger 定义调度时间的元素,即按照什么时间规则去执行任务。一个Job可以被多个Trigger关联,但是一个Trigger 只能关联一个Job; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: &quot;Avenir, -apple-system-font, 微软雅黑, sans-serif&quot;;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 调度器 :工厂类创建Scheduler,根据触发器定义的时间规则调度任务。 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direc

SpringBoot 参数校验,高级特性,非常实用!

作者:微信小助手

<section style="font-size: 16px;"> <section style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;visibility: visible;margin-left: 0px;margin-right: 0px;"> 之前也写过一篇关于 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Spring Validation</code>使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Spring Validation</code>。 </section> <section style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;visibility: visible;margin-left: 0px;margin-right: 0px;"> 本文会详细介绍 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Spring Validation</code>各种场景下的最佳实践及其实现原理,死磕到底! </section> <h2 data-tool="mdnice编辑器" style="margin: 30px 0px 15px;outline: 0px;font-weight: bold;font-size: 22px;visibility: visible;">简单使用</h2> <section style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;visibility: visible;margin-left: 0px;margin-right: 0px;"> <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Java API</code>规范 ( <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">JSR303</code>) 定义了 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Bean</code>校验的标准 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">validation-api</code>,但没有提供实现。 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">hibernate validation</code>是对这个规范的实现,并增加了校验注解如 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">@Email</code>、 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">@Length</code>等。 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Spring Validation</code>是对 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">hibernate validation</code>的二次封装,用于支持 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">spring mvc</code>参数自动校验。接下来,我们以 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">spring-boot</code>项目为例,介绍 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">Spring Validation</code>的使用。 </section> <h3 data-tool="mdnice编辑器" style="margin: 30px 0px 15px;outline: 0px;font-weight: bold;font-size: 20px;visibility: visible;">引入依赖</h3> <section style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;visibility: visible;margin-left: 0px;margin-right: 0px;"> 如果 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">spring-boot</code>版本小于 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">2.3.x</code>, <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">spring-boot-starter-web</code>会自动传入 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">hibernate-validator</code>依赖。如果 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">spring-boot</code>版本大于 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.047);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;visibility: visible;">2.3.x</code>,则需要手动引入依赖: </section> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;visibility: visible;"> <section style="padding: 16px;outline: 0px;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;visibility: visible;margin-left: 0px;margin-right: 0px;"> <span style="outline: 0px;color: rgb(249, 38, 114);line-height: 26px;visibility: visible;">&lt;<span style="outline: 0px;line-height: 26px;visibility: visible;">dependency</span>&gt;</span>&nbsp;&nbsp; <br style="outline: 0px;visibility: visible;">&nbsp;&nbsp;&nbsp;&nbsp; <span style="outline: 0px;color: rgb(249, 38, 114);line-height: 26px;visibility: visible;">&lt;<span style="outline: 0px;line-height: 26px;visibility: visible;">groupId</span>&gt;</span>org.hibernate <span style="outline: 0px;color: rgb(249, 38, 114);line-height: 26px;visibility: visible;">&lt;/<span style="outline: 0px;line-height: 26px;visibility: visible;">groupId</span>&gt;</span>&nbsp;&nbsp; <br style="outline: 0px;visibility: visible;">&nbs

bat复制文件到指定目录

作者:じ☆ve不哭

**copy.bat** ``` @echo off setlocal enabledelayedexpansion for /f "" %%i in (.\list.txt) do ( @set "name=%%i" rem @set "name=%name::=%" @set "name=!name::=!" echo f| xcopy %%i "D:\复制到这里\!name!" /A /Y ) ``` **list.txt** ``` F:\xxxxx\xxx\xxxx\xxxxxx.Jpeg E:\xxxxx\xxx\xxxx\xxxxxx.Jpeg D:\xxxxx\xxx\xxxx\xxxxxx.Jpeg ```

Redis 内存优化在 vivo 的探索与实践

作者:微信小助手

<section powered-by="xiumi.us" style="outline: 0px;max-width: 100%;box-sizing: border-box;color: rgb(34, 34, 34);font-family: -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-size: 15px;letter-spacing: 0.75px;white-space: normal;background-color: rgb(255, 255, 255);visibility: visible;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="outline: 0px;max-width: 100%;box-sizing: border-box;visibility: visible;overflow-wrap: break-word !important;"> <blockquote data-type="2" data-url="" data-author-name="" data-content-utf8-length="84" data-source-title="" style="color: rgba(0, 0, 0, 0.5);outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 作者:互联网服务器团队- Tang Wenjian </section> </section> </blockquote> </section> </section> <section style="font-size: 15px;line-height: 1.6;box-sizing: border-box;"> <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="box-sizing: border-box;"><br></p> <p style="box-sizing: border-box;">一、 背景</p> </section> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;">使用过 Redis 的同学应该都知道,它基于键值对(key-value)的内存数据库,所有数据存放在内存中,内存在 Redis 中扮演一个核心角色,所有的操作都是围绕它进行。</p> <p style="box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="box-sizing: border-box;">我们在实际维护过程中经常会被问到如下问题,比如数据怎么存储在 Redis 里面能节约成本、提升性能?Redis内存告警是什么原因导致?</p> <p style="box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="box-sizing: border-box;">本文主要是通过分析 Redis内存结构、介绍内存优化手段,同时结合生产案例,帮助大家在优化内存使用,快速定位 Redis 相关内存异常问题。</p> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> <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="box-sizing: border-box;">二、 Redis 内存管理</p> </section> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;box-sizing: border-box;">本章详细介绍 Redis 是怎么管理各内存结构的,然后主要介绍几个占用内存可能比较多的内存结构。首先我们看下Redis 的内存模型。</p> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;box-sizing: border-box;">内存模型如图:</p> <p style="white-space: normal;box-sizing: border-box;"><br></p> <p style="text-align: center;margin-bottom: 0em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.4941569282136895" data-s="300,640" src="/upload/558024c7dc437e544d61957e89a90c1f.png" data-type="png" data-w="1198" style=""></p> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;box-sizing: border-box;"><strong style="box-sizing: border-box;">【used_memory】</strong>:Redis内存占用中最主要的部分,Redis分配器分配的内存总量(单位是KB)(在编译时指定编译器,默认是jemalloc),主要包含自身内存(字典、元数据)、对象内存、缓存,lua内存。</p> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;box-sizing: border-box;"><strong style="box-sizing: border-box;">【自身内存】</strong>:自身维护的一些数据字典及元数据,一般占用内存很低。</p> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="white-space: normal;box-sizing: border-box;"><strong style="box-sizing: border-box;">【对象内存】</strong>:所有对象都是Key-Value型,Key对象都是字符串,Value对象则包括5种类(String,List,Hash,Set,Zset),5.0还支持stream类型。</p> <p style="white-space: normal;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> <p style="white-space: nor

解决Centos7断电后系统无法正常启动

作者:じ☆ve不哭

电脑突然蓝屏,随之就关机了。 开着的linux虚拟机躺枪 再次重启虚拟机 进入恢复模式 如下提示: ![1.png](/storage/thumbnails/_signature/1TAO6O6QCFBS5MFHD21J791IGR.png) 度娘一顿搜: 很有牌面: 整齐划一的解决方案 ``` xfs_repair -v -L /dev/dm-0 ``` 我的虚拟机无动于衷!!! 浏览器中一顿点点点: **终于等到你还好没放弃** ``` xfs_repair -v -L /dev/sda3 (3后面加个空格再回车) ``` ![2.png](/storage/thumbnails/_signature/VQ4CGRDP9B152PL3S4ITD5FP4.png) 完了重启虚拟机 ``` reboot ``` 第二次蓝屏关机,虚拟机又中了一枪… ![3.png](/storage/thumbnails/_signature/3MJ2RUMC9CJPUFDOHUNNO2FB1K.png) 出现这个红色叉号,,该怎么解决呢?? ``` 找到虚拟机安装位置,把上面的文件夹统统删了(物理删除的话,linux会误以为导入的其它window文件,使的虚拟机不好用) ``` ![4.png](/storage/thumbnails/_signature/2VJS38G1VUFR4HHPL4QAN5JKJF.png) 再正常打开虚拟机就okk了 转载自: 作者:waving at cars https://blog.csdn.net/weixin_46609492/article/details/120270264

MySQL InnoDB损坏修复innodb_force_recovery

作者:じ☆ve不哭

强制InnoDB恢复 为了研究数据库页损坏,你能用SELECT … INTO OUTFILE从数据库中转储表。通常,以这种方式获得的大部分数据是完整的。严重的损坏可能导致SELECT* FROM tbl_name语句或InnoDB的后台操作崩溃或断言,甚至造成InnoDB前滚恢复崩溃。 在这样的情况下,可以使用innodb_force_recovery选项强制InnoDB存储引擎启动同时阻止后台操作运行,这样你就能转储表了。例如,你可以在重新启动服务器之前添加以下行到选项文件的[mysqld]部分: ``` [mysqld] innodb_force_recovery = N ``` 只有在紧急情况下将innodb_force_recovery设为大于0的值,你才能启动InnoDB并转储表。在进行此操作之前,确保你有数据库的备份副本,以备需要重建它。4及以上的值可以永久破坏数据文件。只有在数据库的独立物理副本的成功地测试了设置,才能在生产服务器实例使用4及以上的innodb_force_recovery设置。当强制InnoDB恢复,你应该总是以innodb_force_recovery=1启动,且仅在需要时增加值。 innodb_force_recovery默认为0(没有强制恢复的正常启动)。对于innodb_force_recovery允许的非零值是1至6。较大值包括较小值的功能。例如,为3的值包括所有的值1和2的功能。 如果你能以innodb_force_recovery为3或更低值转储你的表,那么你是比较安全的,只有在损坏的个人页的一些数据会丢失。4或更大的值被认为是危险的,因为数据文件可以被永久地损坏。值6被认为是严重的,数据库页被留在一个陈旧的状态,这反过来又可能带给B-trees和其它数据库结构更多的损坏。 作为一个安全措施,InnoDB 在innodb_force_recovery大于0时阻止INSERT,UPDATE或DELETE操作。对于MySQL5.6.15,将innodb_force_recovery设为4或更高会让InnoDB处于只读模式。 **1 (SRV_FORCE_IGNORE_CORRUPT)** 即使服务器检测到损坏的页仍让它运行。试图使SELECT* FROM tbl_name跳过损坏的索引记录和页,这样有助于转储表。忽略检查到的 corrupt 页。尽管检测到了损坏的 page 仍强制服务运行。一般设置为该值即可,然后 dump 出库表进行重建。 **2 (SRV_FORCE_NO_BACKGROUND)** 阻止主线程和任何清除线程的运行。如果崩溃会在清除操作中发生,该恢复值会阻止它。如主线程需要执行 full purge 操作,会导致 crash。 阻止 master thread 和任何 purge thread 运行。若 crash 发生在 purge 环节则使用该值。 **3 (SRV_FORCE_NO_TRX_UNDO)** 不在崩溃恢复后运行事务回滚。 **4 (SRV_FORCE_NO_IBUF_MERGE)** 阻止插入缓冲合并操作。如果它们会导致崩溃,不要做这些。不计算表统计。这个值可以永久损坏数据文件。使用这个值后,准备好删除并重建所有辅助索引。在MySQL5.6.15中,设置InnoDB为只读。 **5 (SRV_FORCE_NO_UNDO_LOG_SCAN)** 在启动数据库时不查看撤消日志:InnoDB将即使未完成的事务也作为已提交。这个值可以永久损坏数据文件。在MySQL5.6.15中,设置InnoDB为只读。 **6 (SRV_FORCE_NO_LOG_REDO)** 不执行前滚的操作。恢复时不做 redo log roll-forward。这个值可能永久损坏数据文件。数据库页被留在一个陈旧的状态,这反过来又可能带给B-trees和其它数据库结构更多的损坏。在MySQL5.6.15中,设置InnoDB为只读。 参数使用建议: - 你可以从表中SELECT来转储它们。innodb_force_recovery的值为3或更低,你可以DROP或CREATE表。在MySQL 5.6.27中,DROP TABLE还受大于3的innodb_force_recovery值支持。 - 如果你知道一个给定表在回滚造成崩溃,你可以将其删除。如果遇到所造成失败的大规模导入的失控回滚或ALTER TABLE,你可以杀掉mysqld进程,并设置innodb_force_recovery为3使数据库启动而不回滚,然后DROP导致失控回滚的表。 - 如果表数据中的损坏阻止你转储整个表的内容,带ORDER BY primary_key DESC子句的查询能够转储损坏部分后的表的部分。 - 如果一个高innodb_force_recovery值需要启动InnoDB,可能有被破坏的数据结构,可能导致复杂查询(含有WHERE,ORDER BY或其他子句的查询)失败。在这种情况下,你可能只能运行基本的SELECT* FROM t查询。 - 将innodb_force_recovery参数设置大于0启动服务后,应通过修改端口或域名(VIP)指向来屏蔽应用访问。 - 将innodb_force_recovery参数设置大于0启动服务后,可以通过mysqlcheck命令来对表进行检查/分析/优化/修复。 - 使用force_recovery重启服务前,建议对数据库所有文件进行备份,避免修复过程中对数据进行二次损害。

java进程批量一键dump脚本

作者:じ☆ve不哭

> 有时候java进程会出现莫名其妙的问题,需要dump下来分析,那么这个脚本就派上用场了,一键dump所有java进程。不用再麻烦的敲命令的。 效果见具体参见下图: ![微信图片_20220506130643.png](/storage/thumbnails/_signature/26MV2QGFVBNTPEAT63VO68LPH6.png) ``` #!/bin/sh DUMP_PIDS=`ps --no-heading -C java -f --width 1000 |awk '{print $2}'` if [ -z "$DUMP_PIDS" ]; then echo "The server $HOST_NAME is not started!" exit 1; fi DUMP_ROOT=~/dump if [ ! -d $DUMP_ROOT ]; then mkdir $DUMP_ROOT fi DUMP_DATE=`date +%Y%m%d%H%M%S` DUMP_DIR=$DUMP_ROOT/dump-$DUMP_DATE if [ ! -d $DUMP_DIR ]; then mkdir $DUMP_DIR fi for PID in $DUMP_PIDS ; do #Full thread dump 用来查线程占用,死锁等问题 $JAVA_HOME/bin/jstack $PID > $DUMP_DIR/jstack-$PID.dump 2>&1 echo -e ".\c" #打印出一个给定的Java进程、Java core文件或远程Debug服务器的Java配置信息,具体包括Java系统属性和JVM命令行参数。 $JAVA_HOME/bin/jinfo $PID > $DUMP_DIR/jinfo-$PID.dump 2>&1 echo -e ".\c" #jstat能够动态打印jvm(Java Virtual Machine Statistics Monitoring Tool)的相关统计信息。如young gc执行的次数、full gc执行的次数,各个内存分区的空间大小和可使用量等信息。 $JAVA_HOME/bin/jstat -gcutil $PID > $DUMP_DIR/jstat-gcutil-$PID.dump 2>&1 echo -e ".\c" $JAVA_HOME/bin/jstat -gccapacity $PID > $DUMP_DIR/jstat-gccapacity-$PID.dump 2>&1 echo -e ".\c" #未指定选项时,jmap打印共享对象的映射。对每个目标VM加载的共享对象,其起始地址、映射大小及共享对象文件的完整路径将被打印出来, $JAVA_HOME/bin/jmap $PID > $DUMP_DIR/jmap-$PID.dump 2>&1 echo -e ".\c" #-heap打印堆情况的概要信息,包括堆配置,各堆空间的容量、已使用和空闲情况 $JAVA_HOME/bin/jmap -heap $PID > $DUMP_DIR/jmap-heap-$PID.dump 2>&1 echo -e ".\c" #-dump将jvm的堆中内存信息输出到一个文件中,然后可以通过eclipse memory analyzer进行分析 #注意:这个jmap使用的时候jvm是处在假死状态的,只能在服务瘫痪的时候为了解决问题来使用,否则会造成服务中断。 $JAVA_HOME/bin/jmap -dump:format=b,file=$DUMP_DIR/jmap-dump-$PID.dump $PID 2>&1 echo -e ".\c" #显示被进程打开的文件信息 if [ -r /usr/sbin/lsof ]; then /usr/sbin/lsof -p $PID > $DUMP_DIR/lsof-$PID.dump echo -e ".\c" fi done #主要负责收集、汇报与存储系统运行信息的。 if [ -r /usr/bin/sar ]; then /usr/bin/sar > $DUMP_DIR/sar.dump echo -e ".\c" fi #主要负责收集、汇报与存储系统运行信息的。 if [ -r /usr/bin/uptime ]; then /usr/bin/uptime > $DUMP_DIR/uptime.dump echo -e ".\c" fi #内存查看 if [ -r /usr/bin/free ]; then /usr/bin/free -t > $DUMP_DIR/free.dump echo -e ".\c" fi #可以得到关于进程、内存、内存分页、堵塞IO、traps及CPU活动的信息。 if [ -r /usr/bin/vmstat ]; then /usr/bin/vmstat > $DUMP_DIR/vmstat.dump echo -e ".\c" fi #报告与CPU相关的一些统计信息 if [ -r /usr/bin/mpstat ]; then /usr/bin/mpstat > $DUMP_DIR/mpstat.dump echo -e ".\c" fi #报告与IO相关的一些统计信息 if [ -r /usr/bin/iostat ]; then /usr/bin/iostat > $DUMP_DIR/iostat.dump echo -e ".\c" fi #报告与网络相关的一些统计信息 if [ -r /bin/netstat ]; then /bin/netstat > $DUMP_DIR/netstat.dump echo -e ".\c" fi echo "OK!" ``` 转载自:IT运维技术圈 原文地址:[https://mp.weixin.qq.com/s/eQuFUzEo2be3BrXn17pjXg](https://mp.weixin.qq.com/s/eQuFUzEo2be3BrXn17pjXg)

引入RabbitMQ后,你如何保证全链路数据100%不丢失?

作者:微信小助手

<p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">我们都知道,消息从生产端到消费端消费要经过3个步骤:</p> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;visibility: visible;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 生产端发送消息到RabbitMQ; </section></li> <li style="outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> RabbitMQ发送消息到消费端; </section></li> <li style="outline: 0px;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 消费端消费这条消息; </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 39.6771px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 608.354px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.46880907372400754" src="/upload/f12dba8fd0e26e21f6aba3f902f1edcc.png" data-type="png" data-w="529" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 517.094px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">这3个步骤中的每一步都有可能导致消息丢失,消息丢失不可怕,可怕的是丢失了我们还不知道,所以要有一些措施来保证系统的可靠性。这里的可靠并不是一定就100%不丢失了,磁盘损坏,机房爆炸等等都能导致数据丢失,当然这种都是极小概率发生,能做到99.999999%消息不丢失,就是可靠的了。下面来具体分析一下问题以及解决方案。</p> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><strong><span style="color: rgb(123, 12, 0);">生产端可靠性投递</span></strong></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">生产端可靠性投递,即生产端要确保将消息正确投递到RabbitMQ中。生产端投递的消息丢失的原因有很多,比如消息在网络传输的过程中发生网络故障消息丢失,或者消息投递到RabbitMQ时RabbitMQ挂了,那消息也可能丢失,而我们根本不知道发生了什么。针对以上情况,RabbitMQ本身提供了一些机制。</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;outline: 0px;border-width: initial;border-style: none;border-color: initial;color: rgb(14, 136, 235);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;overflow: auto;line-height: 1.8;border-radius: 0px 0px 10px 10px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;box-shadow: rgb(132, 161, 168) 0px 10px 15px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">基于 Spring Boot + MyBatis Plus + Vue &amp; Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。</p> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">项目地址:https://github.com/YunaiV/ruoyi-vue-pro</p> </blockquote> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><span style="color: rgb(123, 12, 0);"><strong>事务消息机制</strong></span></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">事务消息机制由于会严重降低性能,所以一般不采用这种方法,我就不介绍了,而采用另一种轻量级的解决方案——confirm消息确认机制。</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;outline: 0px;border-width: initial;border-style: none;border-color: initial;color: rgb(14, 136, 235);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;overflow: auto;line-height: 1.8;border-radius: 0px 0px 10px 10px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。</p> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">项目地址:https://github.com/YunaiV/onemall</p> </blockquote> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><span style="color: rgb(123, 12, 0);"><strong>confirm消息确认机制</strong></span></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">什么是confirm消息确认机制?顾名思义,就是生产端投递的消息一旦投递到RabbitMQ后,RabbitMQ就会发送一个确认消息给生产端,让生产端知道我已经收到消息了,否则这条消息就可能已经丢失了,需要生产端重新发送消息了。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 34.9583px 20px 34.9479px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 535.885px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.6330472103004292" src="/upload/81db13c60ddfbbfa004bc5a31ad06c82.png" data-type="png" data-w="466" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 455.5px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">通过下面这句代码来开启确认模式:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.confirmSelect();<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//&nbsp;开启发送方确认模式</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">然后异步监听确认和未确认的消息:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.addConfirmListener(<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">new</span>&nbsp;ConfirmListener()&nbsp;{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//消息正确到达broker</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Override</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span>&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">handleAck</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">(<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">long</span>&nbsp;deliveryTag,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">boolean</span>&nbsp;multiple)</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">throws</span>&nbsp;IOException&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="outline: 0px;max-width: 100%;color: rgb(214, 157, 133);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"已收到消息"</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//做一些其他处理</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//RabbitMQ因为自身内部错误导致消息丢失,就会发送一条nack消息</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(155, 155, 155);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Override</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span>&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">handleNack</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">(<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">long</span>&nbsp;deliveryTag,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">boolean</span>&nbsp;multiple)</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">throws</span>&nbsp;IOException&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="outline: 0px;max-width: 100%;color: rgb(214, 157, 133);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"未确认消息,标识:"</span>&nbsp;+&nbsp;deliveryTag);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//做一些其他处理,比如消息重发等</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">});<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">这样就可以让生产端感知到消息是否投递到RabbitMQ中了,当然这样还不够,稍后我会说一下极端情况。</p> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><span style="color: rgb(123, 12, 0);"><strong>消息持久化</strong></span></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">那消息持久化呢?我们知道,RabbitMQ收到消息后将这个消息暂时存在了内存中,那这就会有个问题,如果RabbitMQ挂了,那重启后数据就丢失了,所以相关的数据应该持久化到硬盘中,这样就算RabbitMQ重启后也可以到硬盘中取数据恢复。那如何持久化呢?</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">message消息到达RabbitMQ后先是到exchange交换机中,然后路由给queue队列,最后发送给消费端。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 41.8542px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 657px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.4131386861313869" src="/upload/480eaf2ad70ea2e60613a96584b81908.png" data-type="png" data-w="685" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 558.448px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有需要给exchange、queue和message都进行持久化:</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">exchange持久化:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//第三个参数true表示这个exchange持久化</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.exchangeDeclare(EXCHANGE_NAME,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(214, 157, 133);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"direct"</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">true</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">queue持久化:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//第二个参数true表示这个queue持久化</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.queueDeclare(QUEUE_NAME,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">true</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">false</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">false</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">null</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">message持久化:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//第三个参数MessageProperties.PERSISTENT_TEXT_PLAIN表示这条消息持久化</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.basicPublish(EXCHANGE_NAME,&nbsp;ROUTING_KEY,&nbsp;MessageProperties.PERSISTENT_TEXT_PLAIN,&nbsp;message.getBytes(StandardCharsets.UTF_8));<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">这样,如果RabbitMQ收到消息后挂了,重启后会自行恢复消息。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">到此,RabbitMQ提供的几种机制都介绍完了,但这样还不足以保证消息可靠性投递RabbitMQ中,上面我也提到了会有极端情况,比如RabbitMQ收到消息还没来得及将消息持久化到硬盘时,RabbitMQ挂了,这样消息还是丢失了,或者RabbitMQ在发送确认消息给生产端的过程中,由于网络故障而导致生产端没有收到确认消息,这样生产端就不知道RabbitMQ到底有没有收到消息,就不好做接下来的处理。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 41.8542px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 651.708px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.47007042253521125" src="/upload/e5304448c26747a0a5a9478d556f825d.png" data-type="png" data-w="568" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 553.948px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">所以除了RabbitMQ提供的一些机制外,我们自己也要做一些消息补偿机制,以应对一些极端情况。接下来我就介绍其中的一种解决方案——消息入库。</p> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><span style="color: rgb(123, 12, 0);"><strong>消息入库</strong></span></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">消息入库,顾名思义就是将要发送的消息保存到数据库中。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">首先发送消息前先将消息保存到数据库中,有一个状态字段status=0,表示生产端将消息发送给了RabbitMQ但还没收到确认;在生产端收到确认后将status设为1,表示RabbitMQ已收到消息。这里有可能会出现上面说的两种情况,所以生产端这边开一个定时器,定时检索消息表,将status=0并且超过固定时间后(可能消息刚发出去还没来得及确认这边定时器刚好检索到这条status=0的消息,所以给个时间)还没收到确认的消息取出重发(第二种情况下这里会造成消息重复,消费者端要做幂等性),可能重发还会失败,所以可以做一个最大重发次数,超过就做另外的处理。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 41.8542px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 657px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.5558343789209536" src="/upload/29e007fee85a77b2242c75a93e435fe.png" data-type="png" data-w="797" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 558.448px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">这样消息就可以可靠性投递到RabbitMQ中了,而生产端也可以感知到了。</p> <h2 data-tool="mdnice编辑器"><a href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" data-linktype="2" wah-hotarea="click"><span style="color: rgb(123, 12, 0);"><strong>消费端消息不丢失</strong></span></a></h2> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">既然已经可以让生产端100%可靠性投递到RabbitMQ了,那接下来就改看看消费端的了,如何让消费端不丢失消息。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">默认情况下,以下3种情况会导致消息丢失:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 在RabbitMQ将消息发出后,消费端还没接收到消息之前,发生网络故障,消费端与RabbitMQ断开连接,此时消息会丢失; </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 在RabbitMQ将消息发出后,消费端还没接收到消息之前,消费端挂了,此时消息会丢失; </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 消费端正确接收到消息,但在处理消息的过程中发生异常或宕机了,消息也会丢失。 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 41.8542px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 657px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.4109985528219971" src="/upload/fa576fc061a5b8ef523fab65637ddabf.png" data-type="png" data-w="691" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 558.448px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">其实,上述3中情况导致消息丢失归根结底是因为RabbitMQ的自动ack机制,即默认RabbitMQ在消息发出后就立即将这条消息删除,而不管消费端是否接收到,是否处理完,导致消费端消息丢失时RabbitMQ自己又没有这条消息了。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);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;text-align: left;white-space: normal;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&amp;mid=2247487551&amp;idx=1&amp;sn=18f64ba49f3f0f9d8be9d1fdef8857d9&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1" wah-hotarea="click" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="margin: 20px 37.125px;outline: 0px;max-width: 100%;line-height: 0;vertical-align: bottom;user-select: none;width: 569.25px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.6323232323232323" src="/upload/7e61e4b063bf72b5b076fc595e6a705e.png" data-type="png" data-w="495" style="outline: 0px;border-width: 0px;border-style: initial;border-color: initial;border-radius: 0px 0px 5px 5px;display: block;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 483.854px !important;"></span></a> </figure> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">所以就需要将自动ack机制改为手动ack机制。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">消费端手动确认消息:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wXJ5kSJT6ONMdYq9ExLicAvGeAJqWGOCkuicJXZAgsSbOX4ULHIwDThlVECxKnMT8kwIiapGTwZa8zDsnOlacRaDy08ZicyGgkKA/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(220, 220, 220);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(30, 30, 30);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;">DeliverCallback&nbsp;deliverCallback&nbsp;=&nbsp;(consumerTag,&nbsp;delivery)&nbsp;-&gt;&nbsp;{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">try</span>&nbsp;{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//接收到消息,做处理</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//手动确认</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;channel.basicAck(delivery.getEnvelope().getDeliveryTag(),&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">false</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">catch</span>&nbsp;(Exception&nbsp;e)&nbsp;{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//出错处理,这里可以让消息重回队列重新发送或直接丢弃消息</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">};<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(87, 166, 74);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//第二个参数autoAck设为false表示关闭自动确认机制,需手动确认</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">channel.basicConsume(QUEUE_NAME,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(86, 156, 214);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">false</span>,&nbsp;deliverCallback,&nbsp;consumerTag&nbsp;-&gt;&nbsp;{});<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">这样,当autoAck参数置为false,对于RabbitMQ服务端而言,队列中的消息分成了两个部分:一部分是等待投递给消费端的消息;一部分是已经投递给消费端,但是还没有收到消费端确认信号的消息。如果RabbitMQ一直没有收到消费端的确认信号,并且消费此消息的消费端已经断开连接或宕机(RabbitMQ会自己感知到),则RabbitMQ会安排该消息重新进入队列(放在队列头部),等待投递给下一个消费者,当然也有能还是原来的那个消费端,当然消费端也需要确保幂等性。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">好了,到此从生产端到RabbitMQ再到消费端的全链路,就可以保证数据的不丢失。</p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;white-space: normal;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">由于个人水平有限,有些地方可能理解错了或理解不到位的,请大家多多指出!Thanks</p> <blockquote style="white-space: normal;"> <p><span style="font-size: 14px;">转自:指尖凉</span></p> <p><span style="font-size: 14px;">链接<span style="color: rgb(154, 154, 154);font-size: 14px;">:https://blog.csdn.net/hsz2568952354/article/details/86559470</span></span></p> </blockquote>

架构揭秘:「京东白条」的数据架构进化之路

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &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: 0em;margin-bottom: 0em;">你好,我是悟空呀。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">最近小伙伴在讨论单体到微服务架构中数据这块如何演进,相信这篇能给大家带来启发。</p> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">来源:SphereEx<br>链接:https://segmentfault.com/a/1190000041107436<br>排版:悟空哥</p> </blockquote> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">京东白条的快速发展满足了当前人们日益增长的消费需求。在京东商城上用京东白条来支付,已经成为一大批用户的消费习惯,更是在某种意义上成为了京东对外的『标签』。而作为一家互联网金融消费平台,京东白条的后台技术团队更是不容忽视的存在。而其也正是支撑京东白条自 2014 年初上线伊始,至今服务数亿用户的最终根源所在。正是京东白条技术团队多年的努力,才造就了当前京东白条的『土生土长』,但具有京东白条特色的金融级数据库选型方法论。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">当京东白条的金融类业务启动时,现任京东白条研发负责人张栋芳,虽然预料到了其数据体量的大幅度增长,却没有想到这种增长将导致数据库选型方面的一系列变化,以及对数据库未来发展模式的启发。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">作为京东科技旗下的杀手级金融消费应用,今天的京东白条已经成长为服务数亿用户、日均产生巨额流量的庞大金融生态。在业务和数据量飞速增长的同时,京东白条后台的研发人员,也在紧张的焦头烂额中....</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这一点,完美契合了京东白条后台数据架构的成长过程。</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);">1、技术的保质期:从 MySQL 到 NoSQL 再到 DBRep</span></h2> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">对于技术人而言,没有永远正确的技术,只有最适合于当下的技术选型。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">京东白条业务诞生之初正是互联网金融与消费行业的高速发展期,经历这些年的发展,从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。京东白条的发展,正是一步步见证了国内互联网消费金融产业的快速迭代。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">同样,京东白条的技术选型历程,也可作为国内互联网消费金融产业发展过程的一个缩影。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">从技术架构的角度来看,并没有绝对的好与不好,需要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。只有架构演进的生命周期适时匹配好业务的生命周期,才能发挥最好的效果。</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;">2014~2015</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">Solr + HBase 的方案解决了核心、非核心业务系统对关键数据库的访问问题,Solr 作为被检索字段的索引,HBase 用作全量的数据存储。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 通过 Solr 集群分担部分读和写的业务,缓解核心库的压力; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Solr 扩展体验上欠佳,对业务也存在较大的入侵。 </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;">2015~2016</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">引入 NoSQL 方案,业务数据以月份进行分表存储在 MongoDB 集群中,阶段性满足了结算处理场景中海量数据导入导出的需求。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" 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> </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;">2016~2017</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">随着业务快速发展,数据量突破百亿大关,此时 MongoDB 面临着容量和性能的双重考验。京东白条大数据平台通过 DBRep 以 MySQL Slave 的形式采集变动信息并存储到消息中心,最后落盘到 ES 和 HBase 中。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" 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> </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);">2、为了让你能够更痛快的剁手,他们先『分解』了自己的后台架构</span></h2> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">网购,贵在手速,但也在于钱包的厚度。京东白条的诞生就是为了解决用户钱包的厚度问题。如今,京东白条也打起了“闪电战”。为了保证用户在消费过程中的体验,后台数据库的稳定性与规律性,就成为了京东白条技术侧亟待考虑和平衡的问题。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">为保证业务系统在数据激增情况下始终能保持高效运行,京东白条技术团队在设计初期使用了数据分片数据架构,发挥极致性能的同时也兼顾代码的可控性,采用基于应用框架的数据拆分方案完成了数据拆分工作。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">其实说来说去,本质上就是一个问题,即随着产品的升级迭代,早期的解决方案逐渐演变为了阻碍今天前进的绊脚石。通过业务框架实现的数据分片方案导致业务代码复杂度增加、维护成本不断攀升,紧耦合的弊端逐渐显露,应用每次升级都需要投入较多的精力对分片做相应调整,研发人员难以专注于业务本身。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">于是,解耦成了京东白条技术突围的唯一关键。在京东白条而言,主要从以下这四个方面开始解耦:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" 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);"> 业务关系解耦,需要让用户在使用过程中每个动作都不受影响,不另外产生新的学习成本,为系统提供良好的扩展能力,从容应对“618”和“11.11”等平台大促活动; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 研发流程解耦,解放后端研发生产力,减少业务代码的复杂度。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">因后台数据库与业务之间的耦合度过高,为整个业务的发展埋下了增速放缓的隐患。面对如上诉求,京东白条技术团队经权衡后开始考虑使用成熟的分库分表组件来承担这部分工作,让业务系统升级和架构调整不再复杂。但京东白条业务体量巨大,是名副其实的金融级高并发、海量数据的业务场景,因此在选择分库分表组件时应具备以下 4 个特点:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" 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>金融场景下的应用,对于数据响应、实时反馈等性能的要求非常高。尤其在交易这种敏感且特殊的场景下,对于性能的表现,一点也不能马虎; </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>京东白条需要处理海量的用户数据,尤其在“618”、“11.11”等大促节日下,面对蜂拥而至海量交易数据与请求,要能够在短时间内快速处理; </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>业务灵活多变是当前互联网产品的共性。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">对此,京东白条从多个方面考虑自研框架与成熟分库分表中间件 ShardingSphere 优劣性,性能对比图如下:</p> <section data-tool="mdnice编辑器" style="overflow-x: auto;"> <table> <thead> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);text-align: left;font-size: 16px;background-color: rgb(219, 217, 216);min-width: 85px;"><br></th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);text-align: left;font-size: 16px;background-color: rgb(219, 217, 216);min-width: 85px;">基于自研框架分片</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);text-align: left;font-size: 16px;background-color: rgb(219, 217, 216);min-width: 85px;">基于 ShardingSphere 分片</th> </tr> </thead> <tbody style="border-width: 0px;border-style: initial;border-color: initial;"> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">性能</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">高</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">高</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">代码耦合度</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">高</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">低</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">业务入侵程度</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">高</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">低</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">升级难度</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">高</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">低</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">扩展性</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">一般</td> <td style="border-color: rgb(204, 204, 204);font-size: 16px;color: rgb(100, 86, 71);min-width: 85px;">良好</td> </tr> </tbody> </table> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">最终,京东白条选择采用 Apache ShardingSphere 来进行金融级别的数据库分片任务。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">3、场景趋于融合,但数据库却无法相容:Apache ShardingSphere 解决方案</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">京东白条采用 Apache ShardingSphere-JDBC 解决方案处理在线应用。ShardingSphere-JDBC 是 Apache ShardingSphere 的第一款产品,它定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">ShardingSphere-JDBC 的以下特点能够很好地满足白条业务场景:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" 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> 微内核、轻量化的设计,性能损耗极小; </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> 支持原生的 JDBC 接口,研发工作量小; </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> 搭配使用迁移同步组件轻松实现数据扩展。 </section></li> </ul> <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.8379310344827586" src="/upload/4cdc11b573b8e89e048329f141e6d99d.png" data-type="png" data-w="580" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">经内部大量系统性验证之后,Apache ShardingSphere 成为了京东白条数据分片中间件的首选方案,2018 年底正式开始对接。</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> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">为全面支撑白条业务、提供更好的业务体验,Apache ShardingSphere 在京东白条业务落地过程中对产品的功能和性能方面进行了更多的支持和提升,产品再一次经历典型案例的打磨。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 升级 SQL 引擎 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">白条的业务逻辑非常复杂且庞大,多样化场景的需求对 SQL 的兼容程度有着较高要求,Apache ShardingSphere 重构了 SQL 解析模块,并支持了更多的 SQL。经两团队通力合作,京东白条业务与 Apache ShardingSphere 相结合的各项指标满足预期,性能与原生 JDBC 几乎一致。</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.773224043715847" src="/upload/29f2b339c3b1cb356567328db17e6100.png" data-type="png" data-w="732" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">关于对接过程中的问题详情及方案,请通过《Apache ShardingSphere 对接京东白条实战》一文来了解。</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> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">Apache ShardingSphere 使用定制化 HASH 策略对数据进行分片,有效避免了热点数据问题,<span style="font-weight: 700;color: rgb(248, 57, 41);">拆分后的数据节点数达近万个</span>,整个割接过程大约持续了 4 周左右的时间。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> DBRep 读取数据,通过 Apache ShardingSphere 将数据同步至目标数据库集群; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 两套集群并行运行,数据迁移后再使用自研工具对业务和数据进行校验。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">DBRep 是 ShardingSphere-Scaling 产品设计的基石,Scaling 具备的自动化能力为后续的迁移扩容工作提供了更多的便利。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">配好业务的生命周期,才能发挥最好的效果。</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);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 简化升级路径 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">通过架构解耦,业务系统升级所涉及技术栈得到有效缩短,研发团队不再需要关注分表设计,精力全部聚焦于业务本身,升级路径得到大幅度优化;</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 节省研发力量 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">引入成熟的 Apache ShardingSphere 无需重新开发分表组件,在简化业务升级路径的基础上节省了大量研发力量;</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 架构灵活扩展 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">搭配使用 Scaling 同步迁移组件从容面对“618”和“11.11”等大型活动,系统灵活扩容。</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);">4、面对新的不稳定业态,需要相对稳定的标准来应对</span></h2> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">如何理解不稳定,并平衡这种不稳定。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">随着数据的重要性日益凸显,以及终端场景领域的持续细化,业务线『开枝散叶』已是常态,市场上的数据库产品层出不穷。某种意义上,发展了许多年的京东白条,早已不再是当年的数据体量,其金融消费场景已经是一个相对稳定和成熟的场景而言,京东白条仍然是一个快速生长的互联网巨量头部产品,用户和数据体量还远没有达到接近天花板级别。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">这也意味着,随着业务数据量的增长,未来京东白条还需要经历多次具备『阵痛期』的架构转型。而每一次转型,无疑都是一次冒险,这对于追求稳定和体验的金融级产品而言,无疑是需要慎重考虑的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">而在现阶段通用的数据架构体系下,整个行业都在经历一种新的不稳定业态。面对这种不稳定的业态,京东白条需要一种相对稳定的标准和生态,来『对抗』这种不稳定的趋势。基于此,张栋芳提到了 Database Plus 的概念。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">2018 年,Apache ShardingSphere 作者张亮就曾提出过 Database Plus 的概念。彼时数据库已经呈现出碎片化的趋势,企业在后端数据库管理层面,已经开始产生不小的成本。如果能够在数据库上层重新建设起具备统一管理底层数据的中间层生态,对于企业以及工程师而言,都会极大提高研发与管理的效率。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">所以,Sharding-JDBC 在京东内部,正式升级为 ShardingSphere,<span style="font-weight: 700;color: rgb(248, 57, 41);">寓意打造一个新的生态,并在张亮和社区需求的引导下,逐步确立起了 Database Plus 的发展方向。伴随着近日 Apache ShardingSphere 5.0.0 正式版的更新,Database Plus 理念已正式在 Apache ShardingSphere 生态中得到践行。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">目前,Apache ShardingSphere 通过可插拔架构,已能够在数据库上层构建起一套全新的数据治理生态,如让传统关系型数据库同时具备水平扩展和数据加密的功能,或在传统关系型数据库的基础上单独打造分布式数据库解决方案等,而无需调整底层数据库架构。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">而这种技术,无疑是应对数据库碎片化趋势的最好方案之一。</span> 而对于未来数据库发展的理解,张栋芳认为,在多样化的数据库上层,构建起统一的数据管理平台,将数据库能力分布在中间层并实现可插拔化,追求功能与业务诉求的高度匹配,筛去冗余的能力,并能够在需要时进行快速变动,始终保证数据架构的整洁、专一。</p> <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);">5、事物终归需要回归到它的本质</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">从市场和用户规模来看,中国有着全球最广泛的互联网用户群体,产生着最大的数据体量,诞生了一系列成长最快速的互联网科技公司....但是与庞大需求所不匹配的是,国内数据服务市场却始终处于同质化竞争之下,没能有颠覆海外数据库巨头的产品出现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">张栋芳认为,各家厂商专注于各自的应用场景之下,缺少一个抬头环顾四周的过程。我们始终在谈新技术,始终在追求业务的最高效化。但对于一些需要实现“大象起舞”的金融、证券、制造、零售等领域而言,最新的技术不一定是最适合他们的,在现有技术基础上,提供增量能力的中间件,打造适配于当下业务场景的技术体系,而不是颠覆。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">“<span style="font-weight: 700;color: rgb(248, 57, 41);">事物需要回归它的本质。</span>”对于数据治理方式而言,同样如此。</p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="outline: 0px;color: rgb(53, 53, 53);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: 15px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;background-color: rgb(255, 255, 255);line-height: 1.6;word-break: break-word;border-radius: 16px;visibility: visible;"> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 1.75;">我今天跟大家的分享到这里。谢谢大家。</p> </section> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;outline: 0px;color: rgb(53, 53, 53);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: 15px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;background-color: rgb(255, 255, 255);line-height: 1.75;">我是悟空,期待与你一起打怪升级变强!</p> </section> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU3NzU5NTg5Mg==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/GfOyjHGwCoN5Ky9IZgsdyZgM3lbEC5Ixe3ZgxBu5MdzvjWFyC7uqrsffcyhtrD8r8t0qicxbGmNxKYr4l4mANKQ/0?wx_fmt=png" data-nickname="面试突击" data-alias="PassJava1" data-signature="大厂面试突击,专注分享面试题,如计算机基础、计算机网络、Java后端、前端Vue。" data-from="0"></mpprofile> <br> </section>