作者:微信小助手
<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(74, 74, 74);letter-spacing: 0.5444px;padding-left: 5px;padding-right: 5px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 24px;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务消息是 RocketMQ 的高级特性之一 。这篇文章,笔者会从<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">应用场景</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">功能原理</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">实战例子</strong>三个模块慢慢为你揭开事务消息的神秘面纱。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">1 应用场景</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">举一个电商场景的例子:用户购物车结算时,系统会创建支付订单。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">用户支付成功后支付订单的状态会由未支付修改为支付成功,然后系统给用户增加积分。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">通常我们会使用普通消费方案,该方案能够发挥 MQ 的优势:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">异步</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">解耦</strong> , 同时架构设计非常简单。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.13226744186046513" src="/upload/6930a8f4822872bf21097d82e7d5d77a.png" data-type="png" data-w="688" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 用户购物车结算时,系统创建支付订单; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 支付成功后,更新订单的状态从未支付修改为支付成功; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 发送一条普通消息到消息队列服务端; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 积分服务消费消息,添加积分记录。 </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">但该方案有个非常直观的缺点:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">容易出现不一致的现象</strong>。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先发送消息,后修改订单状态,消息发送成功,订单没有执行成功,需要回滚整个事务(订单数据事务回滚,积分服务消费时,需要先反查事务状态,若事务提交,才能插入积分记录)。</p> </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先修改订单状态,后发送消息,订单状态修改成功,但消息发送失败,需要补偿操作才能保持最终一致。</p> </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先修改订单,后发送消息,订单状态修改成功,但消息发送超时,此时无法判断需要回滚订单还是提交订单变更。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">我们看到,为了完善普通消费方案,业务层还需要做到两点:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">补偿机制</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提供事务状态查询接口</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">要做到这两点,难不难呢?</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">不难,但是业务层代码会比较混乱,更优的方案还是得从中间件层面解决。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">2 功能原理</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">RocketMQ 事务消息是支持在分布式场景下<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">保障消息生产和本地事务的最终一致性</strong>。交互流程如下图所示:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.2116527942925089" src="/upload/dd621af132498190f8e6adece97871f6.png" data-type="png" data-w="841" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">1、生产者将消息发送至 Broker 。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">2、Broker 将消息持久化成功之后,向生产者返回 Ack 确认消息已经发送成功,此时消息被标记为"<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">暂不能投递</strong>",这种状态下的消息即为<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">半事务消息</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">3、生产者开始<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务逻辑</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">4、生产者根据本地事务执行结果向服务端<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提交二次确认结果</strong>( Commit 或是 Rollback ),Broker 收到确认结果后处理逻辑如下:</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: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Commit :Broker 将半事务消息标记为可投递,并投递给消费者。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Rollback :Broker 将回滚事务,不会将半事务消息投递给消费者。 </section></li> </ul> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">5、在断网或者是生产者应用重启的特殊情况下,若 Broker 未收到发送者提交的二次确认结果,或 Broker 收到的二次确认结果为 Unknown 未知状态,经过固定时间后,服务端将对消息生产者即生产者集群中任一生产者实例发起<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消息回查</strong>。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 生产者收到消息回查后,需要检查对应消息的本地事务执行的最终结果。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 生产者根据检查到的本地事务的最终状态 <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">再次提交二次确认</strong>,服务端仍按照步骤4对半事务消息进行处理。 </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">笔者认为事务消息的精髓在于:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">本地事务执行成功,消费者才能消费事务消息</strong>; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 消息回查本身就是补偿机制的实现,事务生产者需提供了事务状态查询接口。 </section></li> </ol> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">3 实战例子</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">为了便于大家理解事务消息 ,笔者新建一个工程用于模拟<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">支付订单创建</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">支付成功</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">赠送积分</strong>的流程。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">首先,我们创建一个真实的订单主题:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">order-topic</strong> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6231721034870641" src="/upload/2fcef02672332fb1ceb444d460c368e8.png" data-type="png" data-w="889" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">然后在数据库中创建三张表 <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">订单表</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务日志表</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">积分表</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8853118712273642" src="/upload/76c29e03a3c3192b3f10848555629eab.png" data-type="png" data-w="497" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">最后我们创建一个 Demo 工程,生产者模块用于创建支付订单、修改支付订单成功,消费者模块用于新增积分记录。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7722222222222223" src="/upload/b840329e931bcd302a2f25bed9a47397.png" data-type="png" data-w="360" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">接下来,我们展示事务消息的实现流程。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">1、创建支付订单</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">调用订单生产者服务创建订单接口 ,在 t_order 表中插入一条支付订单记录。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5" src="/upload/71509a5b75328ddcb3fd4a6ebca09785.png" data-type="png" data-w="474" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">2、调用生产者服务修改订单状态接口</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">接口的逻辑就是执行事务生产者的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> sendMessageInTransaction</code> 方法。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.47523427041499333" src="/upload/a3da3fa62c3e280c8a6084f35947b684.png" data-type="png" data-w="747" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">生产者端需要配置<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务生产者</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务监听器</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8753351206434317" src="/upload/1f7006c3aa15f83e514a1162011eb428.png" data-type="png" data-w="746" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";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;"> <img class="rich_pages wxw-img" data-ratio="1.3319502074688796" src="/upload/d37621ddc0db5ccf9b358e77b54f2459.png" data-type="png" data-w="241" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务生产者首先<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">发送半事务消息</strong>,发送成功后,生产者才开始<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务逻辑</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务监听器实现了两个功能:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">供 Broker 回查事务状态</strong> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="1.1437908496732025" src="/upload/709611931ded04602e6f082100a2fb24.png" data-type="png" data-w="765" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">执行本地事务的逻辑内部就是执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> orderService.updateOrder</code> 方法。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">方法执行成功则返回 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);">LocalTransactionState.COMMIT_MESSAGE</code> , 若执行失败则返回 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> LocalTransactionState.ROLLBACK_MESSAGE</code> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.45515394912985274" src="/upload/2fbf38095b5cb9c528f07d34fbefb482.png" data-type="png" data-w="747" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">需要注意的是:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> orderService.updateOrder</code> 方法添加了事务注解,并将修改订单状态和插入事务日志表放进一个事务内,避免订单状态和事务日志表的数据不一致。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">最后,生产者根据本地事务执行结果向 Broker <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提交二次确认结果</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">Broker 收到生产者确认结果后处理逻辑如下:</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: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Commit :Broker 将半事务消息标记为可投递,并投递给消费者。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Rollback :Broker 将回滚事务,不会将半事务消息投递给消费者。 </section></li> </ul> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">3、积分消费者消费消息,添加积分记录</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">当 Broker 将半事务消息标记为可投递时,积分消费者就可以开始消费主题 order-topic 的消息了。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5225" src="/upload/44cf0591ac5e0bf0769fd842784a9082.png" data-type="png" data-w="800" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">积分消费者服务,我们定义了<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消费者组名</strong>,以及<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">订阅主题</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消费监听器</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8415614236509759" src="/upload/5b493477404df84dd856e75ec4911407.png" data-type="png" data-w="871" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">在消费监听器逻辑里,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);">幂等非常重要</code> 。当收到订单信息后,首先判断该订单是否有积分记录,若没有记录,才插入积分记录。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">而且我们在创建积分表时,订单编号也是唯一键,数据库中也必然不会存在相同订单的多条积分记录。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">4 总结</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">RocketMQ 事务消息是支持在分布式场景下<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">保障消息生产和本地事务的最终一致性</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">编写一个实战例子并不复杂,但使用事务消息时需要注意如下三点:</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">1、事务生产者和消费者共同协作才能保证业务数据的最终一致性;</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">2、事务生产者需要实现事务监听器,并且保存事务的执行结果(比如事务日志表) ;</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">3、消费者要保证幂等。消费失败时,通过、等手段保证消费结果正确。</p> </section>
作者:微信小助手
<p style="white-space: normal;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;">今天给大家分享一位小伙伴在面试中所遇到的一道面试题:</span><strong style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;">一个 SpringBoot 项目能同时处理多少请求?</strong><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">不知道小伙伴看到这个问题有没有什么思路呢?<br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(136, 136, 136);font-size: 14px;">下面是原文内容(文中"我"指原文作者):</span><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我大概知道他要问的是哪个方向,但是对于这种只有一句话的面试题,我的第一反应是:会不会有坑?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">所以并不会贸然答题,先追问一些消息,比如:这个项目具体是干什么的?项目大概进行了哪些参数配置?使用的 web 容器是什么?部署的服务器配置如何?有哪些接口?接口响应平均时间大概是多少?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">这样,在几个问题的拉扯之后,至少在面试题考察的方向方面能基本和面试官达成了一致。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">比如前面的面试问题,经过几次拉扯之后,面试官可能会修改为:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;font-size: 14px;color: rgb(136, 136, 136);">一个 SpringBoot 项目,未进行任何特殊配置,全部采用默认设置,这个项目同一时刻,最多能同时处理多少请求?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">能处理多少呢?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我也不知道,但是当问题变成上面这样之后,我找到了探索答案的角度。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">既然“未进行任何特殊配置”,那我自己搞个 Demo 出来,压一把不就完事了吗?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">坐稳扶好,准备发车。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6072607260726073" src="/upload/53d8da898d6a711c75c5ab5895355a6c.png" data-type="png" data-w="606" style="margin-right: auto;margin-left: auto;display: block;"> </figure> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">Demo</span></strong></span></h2> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">小手一抖,先搞个 Demo 出来。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">这个 Demo 非常的简单,就是通过 idea 创建一个全新的 SpringBoot 项目就行。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我的 SpringBoot 版本使用的是 2.7.13。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">整个项目只有这两个依赖:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5925925925925926" src="/upload/99a19bac2c7f601c3be1d804fdc7bbe5.png" data-type="png" data-w="459" style="white-space: normal;text-align: left;margin-bottom: 0px;"> </figure> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">整个项目也只有两个类,要得就是一个空空如也,一清二白。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7553516819571865" src="/upload/26a500ee79122a56cb871b745ee25413.png" data-type="png" data-w="327" style="white-space: normal;text-align: left;margin-bottom: 0px;"> </figure> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">项目中的 TestController,里面只有一个 getTest 方法,用来测试,方法里面接受到请求之后直接 sleep 一小时。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">目的就是直接把当前请求线程占着,这样我们才能知道项目中一共有多少个线程可以使用:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="java"><code><span class="code-snippet_outer"><span class="code-snippet__meta">@Slf</span>4j</span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">@RestController</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> <span class="code-snippet__class"><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">TestController</span> </span>{</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__meta">@GetMapping</span>(<span class="code-snippet__string">"/getTest"</span>)</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__function"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">void</span> <span class="code-snippet__title">getTest</span><span class="code-snippet__params">(<span class="code-snippet__keyword">int</span> num)</span> <span class="code-snippet__keyword">throws</span> Exception </span>{</span></code><code><span class="code-snippet_outer"> log.info(<span class="code-snippet__string">"{} 接受到请求:num={}"</span>, Thread.currentThread().getName(), num);</span></code><code><span class="code-snippet_outer"> TimeUnit.HOURS.sleep(<span class="code-snippet__number">1</span>);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">项目中的 application.properties 文件也是空的:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6324549237170597" src="/upload/9d807c570c10b37b56c96f27fd6b37d7.png" data-type="png" data-w="721" style="white-space: normal;text-align: left;margin-bottom: 0px;"> </figure> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">这样,一个“未进行任何特殊配置”的 SpringBoot 不就有了吗?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">基于这个 Demo,前面的面试题就要变成了:我短时间内不断的调用这个 Demo 的 getTest 方法,最多能调用多少次?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">问题是不是又变得更加简单了一点?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">那么前面这个“短时间内不断的调用”,用代码怎么表示呢?</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">很简单,就是在循环中不断的进行接口调用就行了。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">class</span> <span class="code-snippet__title">MainTest</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__function"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">static</span> <span class="code-snippet__keyword">void</span> <span class="code-snippet__title">main</span>(<span class="code-snippet__params">String[] args</span>)</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">for</span> (<span class="code-snippet__keyword">int</span> i = <span class="code-snippet__number">0</span>; i < <span class="code-snippet__number">1000</span>; i++) {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> finalI = i;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">new</span> Thread(() -> {</span></code><code><span class="code-snippet_outer"> HttpUtil.<span class="code-snippet__keyword">get</span>(<span class="code-snippet__string">"127.0.0.1:8080/getTest?num="</span> + finalI);</span></code><code><span class="code-snippet_outer"> }).start();</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">//阻塞主线程</span></span></code><code><span class="code-snippet_outer"> Thread.<span class="code-snippet__keyword">yield</span>();</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">当然了,这个地方你用一些压测工具,比如 jmeter 啥的,会显得逼格更高,更专业。我这里就偷个懒,直接上代码了。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">答案</span></strong></span><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"></span></h2> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">经过前面的准备工作,Demo 和测试代码都就绪了。</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">接下来就是先把 Demo 跑起来:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microso
作者:微信小助手
<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section style="display: flex;justify-content: flex-start;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;padding: 0px 0px 0px 38px;" data-mid="" mpa-from-tpl="t"> <section style="width: 29px;height: 13px;display: flex;justify-content: center;align-items: center;align-self: flex-end;z-index: 1;margin-bottom: -11.1px;margin-right: -29.1px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="0.4482758620689655" src="/upload/b0d8b1572187101911aeca609319e9c8.png" data-type="png" data-w="58"> </section> <section style="text-align: left;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Medium, PingFang SC;font-weight: bold;color: #8B6C4E;line-height: 22px;letter-spacing: 1px;" data-mid="">点击上方<span style="padding: 0px 5px;font-size: 16px;font-family: PingFangSC-Medium, PingFang SC;font-weight: bold;color: #8B6C4E;line-height: 22px;letter-spacing: 1px;" data-mid="">蓝字</span>关注我们</p> </section> <section style="width: 29px;height: 13px;display: flex;justify-content: center;align-items: center;align-self: flex-start;z-index: 1;margin-top: -11.1px;margin-left: -29.1px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="0.4482758620689655" src="/upload/aa7a9467ee3d5a66924f46a720450658.png" data-type="png" data-w="58"> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;flex-direction: column;background: #E66C4A;" data-mid="" mpa-from-tpl="t"> <section style="height: 8px;width: 100%;display: flex;justify-content: flex-start;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="align-self: flex-end;margin-left: 26.5px;margin-bottom: 3px;width: 8px;height: 6px;border-radius: 0px 0px 12px 12px;background: #fff;border-top: 0;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="display: flex;justify-content: space-between;align-items: center;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <br> </section> <section style="display: flex;justify-content: space-between;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="border-right: 1px dashed #fff;padding: 0px 6px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #FFFFFF;line-height: 22px;letter-spacing: 1px;" data-mid="">01</p> </section> <section style="padding: 0px 8px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #FFFFFF;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">前言</span></p> </section> </section> <section data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="height: 8px;width: 100%;display: flex;justify-content: flex-start;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="align-self: flex-end;margin-left: 26.5px;margin-bottom: -1px;width: 8px;height: 6px;border-radius: 12px 12px 0px 0px;background: #fff;border-bottom: 0;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">最近和朋友闲聊,他说他遇到一个问题,他引用了第三方公司私有API包,他在本地项目启动没问题,打包运行却找不到这个API包,于是我就问他怎么引用这个jar。</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">他工程项目第三jar存放的位置类似如下</p> <p><img data-ratio="0.7557077625570776" src="/upload/db5886ca66d8484262c95a519c6f2bed.png" data-type="png" data-w="438"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">在pom做如下引用</span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">dependency</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span>org.example<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 45px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span>demo-api<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">version</span>></span>1.0-SNAPSHOT<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">version</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">scope</span>></span>system<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 53px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">scope</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">systemPath</span>></span>${project.basedir}/lib/demo-api.jar<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">systemPath</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">dependency</span>></span></code></pre> </section> <p><br></p> <p><span style="background-color: rgb(255, 255, 255);color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;">pom打包插件用springboot自带的插件</span></p> <p><span style="background-color: rgb(255, 255, 255);color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;"><br mpa-from-tpl="t"></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">build</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">plugins</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 53px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">plugin</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 45px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span>org.springframework.boot<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span>spring-boot-maven-plugin<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 84px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">executions</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">execution</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">goals</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">goal</span>></span>repackage<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">goal</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 53px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">goals</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">execution</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 84px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">executions</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">plugin</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">plugins</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 52px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">build</span>></span></code></pre> </section> <p><br mpa-from-tpl="t"></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">看到这个插件,大概就知道问题所在了,springboot默认的打包插件是不会把systemscope的jar打进springboot项目的BOOT-INF/lib/。</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong>注:</strong> springboot项目默认会引用BOOT-INF/lib/里面的jar</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">于是我就跟朋友说,不要用systemscope了,直接搭建maven私仓,然后把第三方jar上传到私仓中,pom做如下引用</p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">dependency</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span>org.example<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 45px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">groupId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span>demo-api<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">artifactId</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">version</span>></span>1.0-SNAPSHOT<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">version</span>></span><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></<span style="color: rgb(224, 108, 117);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(224, 108, 117);font-weight: 400;font-style: normal;">dependency</span>></span></code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">朋友给回复是公司没有私仓,我一脸懵逼,我就问他应该不至于吧,再次确认,得到他同样的回复后。后边就提供了下边的几种方案,让他参考选择</span></p> <p style="text-align: justify;"><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;flex-direction: column;background: #E66C4A;" data-mid="" mpa-from-tpl="t"> <section style="height: 8px;width: 100%;display: flex;justify-content: flex-start;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="align-self: flex-end;margin-left: 26.5px;margin-bottom: 3px;width: 8px;height: 6px;border-radius: 0px 0px 12px 12px;background: #fff;border-top: 0;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="display: flex;justify-content: space-between;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: space-between;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="border-right: 1px dashed rgb(255, 255, 255);padding-right: 6px;padding-left: 6px;" data-mid="" mpa-from-tpl="t"> <p style="font-s
作者:微信小助手
<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section style="width: 100%;display: flex;justify-content: center;align-items: center;justify-content: flex-start;padding-left: 18px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="width: 14px;height: 5px;margin-bottom: -3px;background: #fff;z-index: 1;" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="0.35714285714285715" src="/upload/141c0958e26f315fd6ebddf3ae6b0eb1.png" data-type="png" data-w="28" style="display: block;"> </section> <section style="width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 12.38px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="2.9166666666666665" src="/upload/eb0f0a42b3adfb474dc48e1ecee25ebc.png" data-type="png" data-w="24" style="display: block;"> </section> <section style="height: 34.6px;border-width: 1px 0px;border-top-style: solid;border-bottom-style: solid;border-top-color: rgb(103, 158, 98);border-bottom-color: rgb(103, 158, 98);border-left-style: initial;border-left-color: initial;border-right-style: initial;border-right-color: initial;text-align: center;padding: 0px 6px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #080405;line-height: 34.6px;" data-mid="">点击上方<span style="color: #209030;padding: 0px 4px;" data-mid="">蓝字</span>关注我们</p> </section> <section style="width: 12.38px;transform: rotatey(180deg);" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="2.9166666666666665" src="/upload/eb0f0a42b3adfb474dc48e1ecee25ebc.png" data-type="png" data-w="24" style="display: block;"> </section> </section> <section style="width: 14px;height: 5px;transform: rotate(180deg);margin-top: -2.5px;z-index: 1;background-color: #fff;" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="0.35714285714285715" src="/upload/141c0958e26f315fd6ebddf3ae6b0eb1.png" data-type="png" data-w="28" style="display: block;"> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;z-index: 3;margin-bottom: -16.5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 36px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 50px;letter-spacing: 2px;-webkit-text-stroke: 2px rgb(151, 216, 191);" data-mid="">01</h1> </section> </section> <section style="margin-bottom: 5px;width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;height: 1px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="margin: 0 9px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #333333;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">前言</span></p> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">在我们日常开发过程中,有时候因为对索引列进行函数调用,导致索引失效。举个例子,比如我们要按月查询记录,而当我们 表中只存时间,如果我们使用如下语句,其中create_time为索引列</span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">select</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">count</span>(*) <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">from</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">user</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">where</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">MONTH</span>(create_time) = <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">5</span></code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">虽然可能查到正确的结果,但通过explain我们会发现没走索引。因此我们为了能确保使用索引,我们可能会改成</span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">select</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">count</span>(*) <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">from</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">user</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">where</span> create_time <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">BETWEEN</span> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">'2022-05-01'</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AND</span> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">'2022-06-01'</span>;</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">或者干脆在数据库表中冗余一个月份的列字段,并对这个月份创建索引。如果我们使用的mysql是5.7版本,我们则可以使用mysql5.7版本提供的一个新特性--</span><strong style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">虚拟列</strong><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">来达到上述效果</span></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;z-index: 3;margin-bottom: -16.5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 36px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 50px;letter-spacing: 2px;-webkit-text-stroke: 2px rgb(151, 216, 191);" data-mid="">02</h1> </section> </section> <section style="margin-bottom: 5px;width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;height: 1px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="margin-right: 9px;margin-left: 9px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">虚拟列</span></p> </section> </section> </section> </section> </section> <p><br></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">在mysql5.7支持2种虚拟列virtual columns 和 stored columns 。两者的区别是virtual 只是在读行的时候计算结果,但在物理上是不存储,因此不占存储空间,且仅在InnoDB引擎上建二级索引,而stored 则是当行数据进行插入或更新时计算并存储的,是需要占用物理空间的,支持在MyISAM和InnoDB引擎创建索引</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong>mysql5.7 默认的虚拟列类型为virtual columns</strong></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">01</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #333333;line-height: 18px;" data-mid="">创建虚拟列语法</p> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALTER</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">TABLE</span> 表名称 <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">add</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">column</span> 虚拟列名称 虚拟列类型 [<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">GENERATED</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALWAYS</span>] <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">as</span> (表达式) [<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 47px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">VIRTUAL</span> | <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">STORED</span>];</code></pre> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">02</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">使用虚拟列注意事项</p> </section> </section> </section> </section> <p><br></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">a、衍生列的定义可以修改,但virtual和stored之间不能相互转换,必要时需要删除重建</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">b、虚拟列字段只读,不支持 INSRET 和 UPDATE</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">c、只能引用本表的非 generated column 字段,不可以引用其它表的字段</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">d、使用的表达式和操作符必须是 Immutable 属性,比如不能使用 CONNECTION_ID(), CURRENT_USER(), NOW()</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">e、可以将已存在的普通列转化为stored类型的衍生列,但virtual类型不行;同样的,可以将stored类型的衍生列转化为普通列,但virtual类型的不行</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">f、虚拟列定义不允许使用自增 (AUTO_INCREMENT),也不允许使用自增基列</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">g、虚拟列允许修改表达式,但不允许修改存储方式(只能通过删除重新创建来修改)</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">h、如果虚拟列用作索引,会有一个缺点值会存储两次。一次用作虚拟列的值,一次用作索引中的值</p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">03</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">虚拟列的使用场景</p> </section> </section> </section> </section> <p><br></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">a、虚拟列可以简化和统一查询,将复杂条件定义为生成的列,可以在查询时直接使用虚拟列(代替视图)</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">b、存储虚拟列可以用作实例化缓存,以用于动态计算成本高昂的复杂条件</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">c、虚拟列可以模拟功能索引,并且可以使用索引,这对与无法直接使用索引的列(JSON 列)非常有用</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;z-index: 3;margin-bottom: -16.5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 36px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 50px;letter-spacing: 2px;-webkit-text-stroke: 2px rgb(151, 216, 191);" data-mid="">03</h1> </section> </section> <section style="margin-bottom: 5px;width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;height: 1px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="margin-right: 9px;margin-left: 9px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">示例</span></p> </section> </section> </section> </section> </section> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">因为mysql5.7也支持json列,因此本示例就以json和虚拟列为例子演示一下示例</span></p> <p><br></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #A2E9CD;line-height: 20px;-webkit-text-stroke: 2px #333333;" data-mid="">01</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #333333;line-height: 18px;" data-mid="">创建示例表</p> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">CREATE</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">TABLE</span> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 86px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">`t_user_json`</span> (<br mpa-from-tpl="t"> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">`id`</span> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">int</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">NOT</span> <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">NULL</span> AUTO_INCREMENT,<br mpa-from-tpl="t"> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 73px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">`user_info`</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">json</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">DEFAULT</span> <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">NULL</span>,<br mpa-from-tpl="t"> <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 86px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">`create_time`</span> datetime <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">DEFAULT</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 113px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">CURRENT_TIMESTAMP</span>,<br mpa-from-tpl="t"> PRIMARY <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">KEY</span> (<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">`id`</span>)<br mpa-from-tpl="t">) <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ENGINE</span>=<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">InnoDB</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">DEFAULT</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">CHARSET</span>=utf8mb4;</code></pre> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">02</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">创建虚拟列</p> </section> </section> </section> </section> <p><br></p> <p><strong style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">注:</strong><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"> 虚拟列可以在建表语句时候,直接创建即可。本示例是为了突出虚拟列语法</span></p> <p><br></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALTER</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">TABLE</span> t_user_json <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ADD</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">COLUMN</span> v_user_name <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">VARCHAR</span>(<span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">50</span>) <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">GENERATED</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALWAYS</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AS</span> (JSON_UNQUOTE(json_extract(user_info,<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">'$.username'</span>)));</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">正常我们的json语句如下</span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;">{<span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">"age"</span>: <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">23</span>, <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 47px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">"email"</span>: <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 113px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"likairui@qq.com"</span>, <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 53px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">"mobile"</span>: <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"89136682644"</span>, <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">"fullname"</span>: <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 49px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"李凯瑞"</span>, <span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">"username"</span>: <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"likairui"</span>}</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">我们通过JSON_UNQUOTE来去除双引号,否则到时候生成的虚拟列v_user_name 的值会变成"likairui",而实际我们需要的字段值应该likairui</p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">因为mysql5.7的json不是本文的重点,本文就不论述了,如果对mysql5.7 json语法函数感兴趣的朋友可以查看如下链接</p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="width: 100%;display: flex;justify-content: center;align-items: center;padding: 0px 12px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 38px;height: 38px;background: #EEFBDB;border-radius: 50%;align-self: flex-start;margin-left: -8px;margin-bottom: -26px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 100%;border-width: 1px;border-style: solid;border-color: rgb(123, 202, 112);padding: 14px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 14px;font-family: PingFangSC-Regular, PingFang SC;color: #333333;line-height: 20px;letter-spacing: 1px;" data-mid="">https://dev.mysql.com/doc/refman/5.7/en/json-functions.html</p> </section> </section> <section style="width: 70px;height: 10px;margin-right: 38px;margin-top: -5px;align-self: flex-end;background: #fff;padding: 0px 4px;" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="0.14285714285714285" src="/upload/91f5014ce3d8c98b70f085b1f1e26a5c.png" data-type="png" data-w="140" style="display: block;"> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">03</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">为虚拟列创建索引</p> </section> </section> </section> </section> <p><br></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALTER</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">TABLE</span> t_user_json <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ADD</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">INDEX</span> idx_v_user_name(v_user_name);</code></pre> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">04</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">查看生成的表数据</p> </section> </section> </section> </section> <p><br></p> <p><img class="rich_pages wxw-img" data-ratio="0.17706576728499157" src="/upload/7552ed37e8607abee66ca3d04cd9c6a7.png" data-type="png" data-w="1186"></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid #333333;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">05</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">查看是否使用了索引</p> </section> </section> </section> </section> <p><br></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 47px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">EXPLAIN</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">SELECT</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">id</span>,user_info,create_time,v_user_name <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AS</span> username,v_date_month <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AS</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">MONTH</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">FROM</span> t_user_json <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">WHERE</span> (v_user_name = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">'likairui'</span>)</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><img class="rich_pages wxw-img" data-ratio="0.0692249811888638" src="/upload/5b39c2da84b02185d967bf14cb55b44f.png" data-type="png" data-w="1329"></p> <p><br></p> <p><strong style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">注:</strong><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"> 在mysql8.0版本可以使用EXPLAIN ANALYZE,他可以查看sql的耗时情况</span></p> <p><br></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 47px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">EXPLAIN</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ANALYZE</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">SELECT</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">id</span>,user_info,create_time,v_user_name <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AS</span> username,v_date_month <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">AS</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">MONTH</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">FROM</span> t_user_json <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">WHERE</span> (v_user_name = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">'cengwen'</span>)</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><img class="rich_pages wxw-img" data-ratio="0.06711915535444947" src="/upload/e1ecac9f822edd1ead170d18a922c0f0.png" data-type="png" data-w="1326"></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;border-bottom: 2px solid rgb(51, 51, 51);" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 32px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(162, 233, 205);line-height: 20px;-webkit-text-stroke: 2px rgb(51, 51, 51);" data-mid="">06</h1> </section> <section style="margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 18px;" data-mid="">代码层面的小细节</p> </section> </section> </section> </section> <p><br></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">因为虚拟列是不能进行插入和更新的,因此使用orm框架的时候,要特别注意这点。比如使用mybatis-plus时,要记得在实体的虚拟列的映射字段上加上如下注解</span></p> <p><br></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 73px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">@TableField</span>(value = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 86px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"v_user_name"</span>,insertStrategy = FieldStrategy.NEVER,updateStrategy = FieldStrategy.NEVER)<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span> username;</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">加上这个注解后,虚拟列字段就不会进行更新或者插入</span></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;z-index: 3;margin-bottom: -16.5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 36px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 50px;letter-spacing: 2px;-webkit-text-stroke: 2px rgb(151, 216, 191);" data-mid="">04</h1> </section> </section> <section style="margin-bottom: 5px;width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;height: 1px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="margin-right: 9px;margin-left: 9px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">总结</span></p> </section> </section> </section> </section> </section> <p><br></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">本文基于mysql5.7大体介绍了一下虚拟列,如果是使用mysql8.0.13以上的版本,可以函数索引,他的实现方式本质也是基于虚拟列实现。所谓的函数索引就是在创建索引的时候,支持使用函数表达式。比如</span></p> <p><br></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ALTER</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">TABLE</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">user</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">ADD</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">INDEX</span>((<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">MONTH</span>(create_time)));</code></pre> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">通过函数索引也可以很方便提高我们的查询效率。具体使用可以查看如下链接</span></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="width: 100%;display: flex;justify-content: center;align-items: center;padding-right: 12px;padding-left: 12px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 38px;height: 38px;background: #EEFBDB;border-radius: 50%;align-self: flex-start;margin-left: -8px;margin-bottom: -26px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 100%;border-width: 1px;border-style: solid;border-color: rgb(123, 202, 112);padding: 14px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 14px;font-family: PingFangSC-Regular, "PingFang SC";line-height: 20px;letter-spacing: 1px;" data-mid="">https://dev.mysql.com/doc/refman/8.0/en/create-index.html</p> </section> </section> <section style="width: 70px;height: 10px;margin-right: 38px;margin-top: -5px;align-self: flex-end;background: rgb(255, 255, 255);padding-right: 4px;padding-left: 4px;" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="0.14285714285714285" src="/upload/91f5014ce3d8c98b70f085b1f1e26a5c.png" data-type="png" data-w="140" style="display: block;"> </section> </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;z-index: 3;margin-bottom: -16.5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <h1 style="font-size: 36px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 50px;letter-spacing: 2px;-webkit-text-stroke: 2px rgb(151, 216, 191);" data-mid="">05</h1> </section> </section> <section style="margin-bottom: 5px;width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;height: 1px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 20px;height: 3px;background: #A2E9CD;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="margin-right: 9px;margin-left: 9px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">demo链接</span></p> </section> </section> </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="width: 100%;display: flex;justify-content: center;align-items: center;padding-right: 12px;padding-left: 12px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 38px;height: 38px;background: #EEFBDB;border-radius: 50%;align-self: flex-start;margin-left: -8px;margin-bottom: -26px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 100%;border-width: 1px;border-style: solid;border-color: rgb(123, 202, 112);padding: 14px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 14px;font-family: PingFangSC-Regular, "PingFang SC";line-height: 20px;letter-spacing: 1px;" data-mid="">https://github.com/lyb-geek/springboot-learning/tree/master/springboot-mysql-virtual-column</p> </section> </section> <section style="width: 70px;height: 10px;margin-right: 38px;margin-top: -5px;align-self: flex-end;background: rgb(255, 255, 255);padding-right: 4px;padding-left: 4px;" data-mid="" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-ratio="0.14285714285714285" src="/upload/91f5014ce3d8c98b70f085b1f1e26a5c.png" data-type="png" data-w="140" style="display: block;"> </section> </section> </section> </section> <p><br></p>
作者:微信小助手
<p style="text-align: center;"><img class="rich_pages" data-ratio="0.1" src="/upload/9590f97c97ca7d1695fcafa708580ed2.png" data-type="gif" data-w="500" style=""></p> <h2 style="box-sizing: border-box;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 24px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">前言</h2> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">在介绍springboot如何与prometheus整合监控之前,先介绍几个待会整合会用到的工具。</p> <h3 style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">prometheus</h3> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">1、什么是prometheus</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是Google BorgMon监控系统的开源版本</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">2、prometheus的特点</p> </blockquote> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">多维度数据模型</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">灵活的查询语言</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">不依赖分布式存储,单个服务器节点是自主的</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">通过基于HTTP的pull方式采集时序数据</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">可以通过中间网关进行时序列数据推送</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">通过服务发现或者静态配置来发现目标服务对象</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">支持多种多样的图表和界面展示,比如Grafana等</p></li> </ul> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">3、prometheus集成的组件</p> </blockquote> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>prometheus server</strong>:主要用于抓取数据和存储时序数据,另外还提供查询和 Alert Rule 配置管理</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>client libraries</strong>:用于对接 Prometheus Server, 可以查询和上报数据</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>push gateway</strong>:用于批量,短期的监控数据的汇总节点,主要用于业务数据汇报等</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>exporters</strong>:各种汇报exporter,例如node<span style="box-sizing: border-box;">exporter,mysql</span>exporter,mongodb_exporter</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>alertmanager</strong>:告警通知管理</p></li> </ul> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">4、prometheus架构图</p> </blockquote> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6002960769800149" data-s="300,640" src="/upload/f81340e8322b06dc5d636ff6d6664eed.png" data-type="png" data-w="1351" style=""></p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">5、prometheus适用场景</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">prometheus在记录纯数字时间序列方面表现非常好。它既适用于面向服务器等硬件指标的监控,也适用于高动态的面向服务架构的监控。对于现在流行的微服务,prometheus的多维度数据收集和数据筛选查询语言也是非常的强大。prometheus是为服务的可靠性而设计的,当服务出现故障时,它可以使你快速定位和诊断问题。它的搭建过程对硬件和服务没有很强的依赖关系。</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">6、prometheus不适用场景</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><span style="color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;text-align: start;white-space: pre-line;">p</span><span style="color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;text-align: start;white-space: pre-line;">rometheus</span>重视可靠性。即使在故障情况下,您也始终可以查看有关系统的可用统计信息。如果您需要100%的准确性(例如按请求计费),则prometheus并不是一个不错的选择,因为所收集的数据可能不会足够详细和完整。在这种情况下,最好使用其他系统来收集和分析计费数据,并使用prometheus进行其余的监视。</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">7、prometheus安装</p> </blockquote> <p style="text-align: left;"><span style="font-size: 16px;">可以查看之前我的一篇文章:</span><span style="font-size: 16px;"><a href="http://mp.weixin.qq.com/s?__biz=MzI1MTY1Njk4NQ==&mid=2247487225&idx=2&sn=eaeaac1742de4b2bcb36d93ba3461688&chksm=e9eee08fde996999c1dae61c53a86606d5634f4e2864a8dfdfecdc2c4f0f012b4cabdd2abf1f&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 16px;" data-linktype="2">运维监控之Prometheus入门安装篇</a></span></p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">8、prometheus监控告警</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">prometheus的警报分为两个部分。prometheus服务器中的警报规则将警报发送到Alertmanager。然后,警报管理器通过电子邮件,通话通知系统和聊天平台等方法管理这些警报,包括静默,禁止,聚合和发出通知。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">设置警报和通知的主要步骤是:</p> <ol class=" list-paddingleft-2" style="list-style-type: decimal;"> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">设置和配置Alertmanager</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">配置prometheus与Alertmanager对话</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">在prometheus中创建警报规则</p></li> </ol> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">9、prometheus安装Alertmanager集成</p> </blockquote> <p style="box-sizing: border-box;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">因为篇幅关系,prometheus 安装Alertmanager集成可以参考如下链接进行安装</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">https://www.cnblogs.com/xiangsikai/p/11289757.html</p> </blockquote> <h3 style="box-sizing: border-box;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">Grafana</h3> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">1、什么是Grafana</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">Grafana是一款用Go语言开发的开源数据可视化工具,可以做数据监控和数据统计,带有告警功能。Grafana允许您查询,可视化,警报和了解指标,无论它们存储在哪里</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">2、Grafana的特点</p> </blockquote> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>可视化</strong>:快速和灵活的客户端图形具有多种选项。面板插件为许多不同的方式可视化指标和日志。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>报警</strong>:可视化地为最重要的指标定义警报规则。Grafana将持续评估它们,并发送通知。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>通知</strong>:警报更改状态时,它会发出通知。接收电子邮件通知。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>动态仪表盘</strong>:使用模板变量创建动态和可重用的仪表板,这些模板变量作为下拉菜单出现在仪表板顶部。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>混合数据源</strong>:在同一个图中混合不同的数据源!可以根据每个查询指定数据源。这甚至适用于自定义数据源。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>注释</strong>:注释来自不同数据源图表。将鼠标悬停在事件上可以显示完整的事件元数据和标记。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><strong>过滤器</strong>:过滤器允许您动态创建新的键/值过滤器,这些过滤器将自动应用于使用该数据源的所有查询。</p></li> </ul> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">3、Grafana安装</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">Grafana官网有提供很详细的安装教程,安装可以查看如下链接,本文就不再论述</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">https://grafana.com/docs/installation/rpm/</p> </blockquote> <h3 style="box-sizing: border-box;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">micrometer</h3> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">1、什么是micrometer</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">micrometer号称监控界的SLF4J,主要用来以极低极低的消耗来给Java程序提供对指标的监控。micrometer为 Java平台上的性能数据收集提供了一个通用的 API,应用程序只需要使用 Micrometer 的通用 API 来收集性能指标即可。micrometer会负责完成与不同监控系统的适配工作。这就使得切换监控系统变得很容易。micrometer还支持推送数据到多个不同的监控系统。</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">2、micrometer的核心组成模块</p> </blockquote> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">包含数据收集 SPI 和基于内存的实现的核心模块 micrometer-core。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">针对不同监控系统的实现模块,如针对 Prometheus 的 micrometer-registry-prometheus。</p></li> <li><p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">与测试相关的模块 micrometer-test。</p></li> </ul> <h2 style="box-sizing: border-box;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 24px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">正文</h2> <h3 style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">springboot整合prometheus</h3> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">1、整合的前置条件</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">服务器上已经安装了prometheus、grafana、alertmanager(可选)。本文的安装使用docker-compose来构建相关服务,具体的安装过程可以参考如下文章</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">https://blog.51cto.com/msiyuetian/2369130</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">如果懒得看,也可以拿我已经准备好的脚本,扔到服务器上执行吧,相关的脚本可以查看如下链接</p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">http://1t.click/beth</p> </blockquote> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">2、pom.xml</p> </blockquote> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;padding-top: 8px;padding-bottom: 6px;background: rgb(29, 31, 33);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei"!important;border-width: 1px !important;border-style: solid !important;border-color: rgb(226, 226, 226) !important;"> <ol class="linenums list-paddingleft-2" style="list-style-type: none;"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependencies</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependency</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">groupId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">org</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">springframework</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">boot</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">groupId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">artifactId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">spring</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">boot</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">starter</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">actuator</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">artifactId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependency</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><br></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependency</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">groupId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">io</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">micrometer</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">groupId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">artifactId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">micrometer</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">registry</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">prometheus</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">artifactId</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependency</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">dependencies</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span></code></span></span></p></li> </ol></pre> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">3、application.yml</p> </blockquote> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;padding-top: 8px;padding-bottom: 6px;background: rgb(29, 31, 33);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei"!important;border-width: 1px !important;border-style: solid !important;border-color: rgb(226, 226, 226) !important;"> <ol class="linenums list-paddingleft-2" style="list-style-type: none;"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">management</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> endpoints</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> web</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> exposure</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> include</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">'*'</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">spring</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> application</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> name</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> springboot_prometheus</span></code></span></span></p></li> </ol></pre> <p style="box-sizing: border-box;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><br></p> <blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">4、prometheus.yml中配置需要采集的服务</p> </blockquote> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;padding-top: 8px;padding-bottom: 6px;background: rgb(29, 31, 33);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei"!important;border-width: 1px !important;border-style: solid !important;border-color: rgb(226, 226, 226) !important;"> <ol class="linenums list-paddingleft-2" style="list-style-type: none;"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">scrape_configs</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">#</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="typ" style="box-sizing: border-box;color: rgb(129, 162, 190);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">The</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> job name is added as a label </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">`</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">job</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=<</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">job_name</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">>`</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> to any timeseries scraped from </span><span class="kwd" style="box-sizing: border-box;color: rgb(178, 148, 187);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">this</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> config</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">-</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> job_name</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">'prometheus'</span></code></span></span></p></li> <li><p><br></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="box-sizing: border-box;line-height: 22px;display: block;word-break: inherit !important;"><code class="javascript language-javascript" style="box-sizing: border-box;margin-left: -20px;display: flex;overflow: initial;line-height: 12px;word-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">#</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> metrics_path defaults to </span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">'/metrics'</span></code></span></span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74)
作者:微信小助手
<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section data-role="outer" style="font-size:16px;" mpa-from-tpl="t"> <section data-id="92322" style="border-width: 0px;border-style: none;border-color: initial;" mpa-from-tpl="t"> <section data-role="paragraph" style="border-width: 0px;border-style: none;border-color: initial;" mpa-from-tpl="t"> <section style="width: 100%;margin-right: auto;margin-left: auto;text-align: center;" data-width="100%" mpa-from-tpl="t"> <section style="display: inline-block;width: auto;margin-right: auto;margin-left: auto;" mpa-from-tpl="t"> <section style="display: flex;display: -webkit-flex;align-items: center;-webkit-align-items: center;overflow: hidden;" mpa-from-tpl="t"> <section style="width:40px;" mpa-from-tpl="t"> <section style="width:40px;" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/f5ec3ab4c06d0447d88bcec082c8a274.png" data-type="gif" data-w="90" data-width="100%" style="display: block;width: 100%;"> </section> </section> <section style="display: inline-block;padding-right: 10px;padding-left: 10px;height: 50px;line-height: 50px;text-shadow: rgb(250, 232, 232) 2px 0px 5px;color: rgb(254, 191, 191);" mpa-from-tpl="t"> <p data-brushtype="text">点击蓝字之后,我们就是好朋友了啦</p> </section> <section style="width:40px;" mpa-from-tpl="t"> <section style="width:40px;" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/6a37cb5f0ff32144cf79154e81687174.png" data-type="gif" data-w="90" data-width="100%" style="display: block;width: 100%;"> </section> </section> </section> </section> </section> <p style="display:none;">15</p> </section> </section> <p><br></p> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="margin-left: 10px;display: flex;justify-content: center;align-items: flex-end;padding-bottom: 5px;border-bottom: 2px solid rgb(75, 83, 247);" data-mid="" mpa-from-tpl="t"> <section style="transform: translateX(-3px);margin-right: 7px;width: 29px;height: 29px;background: #FF9BA7;display: flex;justify-content: center;align-items: center;box-shadow: 3px 3px #4b53f7;" data-mid="" mpa-from-tpl="t"> <span style="transform: translateY(1px);font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 22px;letter-spacing: 2px;-webkit-text-stroke: 1px rgb(255, 255, 255);" data-mid="">01</span> </section> <section style="transform: translateY(2px);" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #333333;line-height: 22px;" data-mid=""><span style="font-size: 18px;">前言</span></p> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;text-align: start;background-color: rgb(255, 255, 255);font-size: 15px;">最近和朋友聊天,他接了个外包项目,他问我有没有办法让自己的源码不被反编译破解,我就跟他说可以对代码进行混淆和加密。今天我们就来聊聊如何通过对代码进行加密实现代码防反编译,至于混淆因为可以直接利用proguard-maven-plugin进行配置实现,相对比较简单,就不在本文论述</span></p> <p><br></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="width: 289px;height: 27px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="0.09342560553633218" src="/upload/cf2eabe94311ecc67699af1a33f75bfd.png" data-type="png" data-w=""> </section> </section> </section> </section> <p><br></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;text-align: start;background-color: rgb(255, 255, 255);font-size: 15px;"><br></span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="margin-left: 10px;display: flex;justify-content: center;align-items: flex-end;padding-bottom: 5px;border-bottom: 2px solid rgb(75, 83, 247);" data-mid="" mpa-from-tpl="t"> <section style="transform: translateX(-3px);margin-right: 7px;width: 29px;height: 29px;background: #FF9BA7;display: flex;justify-content: center;align-items: center;box-shadow: 3px 3px #4b53f7;" data-mid="" mpa-from-tpl="t"> <span style="transform: translateY(1px);font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(255, 255, 255);line-height: 22px;letter-spacing: 2px;-webkit-text-stroke: 1px rgb(255, 255, 255);" data-mid="">02</span> </section> <section style="transform: translateY(2px);" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #333333;line-height: 22px;" data-mid=""><span style="font-size: 18px;">代码防编译整体套路</span></p> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-id="86516" style="border-width: 0px;border-style: none;border-color: initial;" mpa-from-tpl="t"> <section style="border-bottom: 1px solid rgb(221, 221, 221);margin-right: auto;margin-bottom: 10px;margin-left: auto;" mpa-from-tpl="t"> <p data-brushtype="text" style="padding-right: 5px;padding-bottom: 6px;padding-left: 5px;border-bottom: 2px solid rgb(239, 112, 96);display: inline-block;margin-bottom: -1px;line-height: 1.1;font-size: 18px;"><span style="font-size: 16px;">1、编写加密工具类</span></p> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;">@Slf4j<br mpa-from-tpl="t"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">EncryptUtils</span> {<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> String secretKey = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 131px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"test123456lyb-geek"</span>+System.currentTimeMillis();<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 145px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">EncryptUtils</span>()</span>{}<br mpa-from-tpl="t"><br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 508px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">encrypt</span>(<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 317px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">String classFileSrcPath,String classFileDestPath</span>) </span>{<br mpa-from-tpl="t"> System.<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">out</span>.println(secretKey);<br mpa-from-tpl="t"> FileInputStream fis = <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">null</span>;<br mpa-from-tpl="t"> FileOutputStream fos = <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">null</span>;<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">try</span> {<br mpa-from-tpl="t"> fis = <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> FileInputStream(classFileSrcPath);<br mpa-from-tpl="t"> fos = <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> FileOutputStream(classFileDestPath);<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">int</span> len;<br mpa-from-tpl="t"> String[] arrs = secretKey.split(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"lyb-geek"</span>);<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">long</span> key = Long.valueOf(arrs[<span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">1</span>]);<br mpa-from-tpl="t"> System.<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">out</span>.println(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"key:"</span>+key);<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">while</span>((len = fis.read())!=<span style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">-1</span>){<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">byte</span> data = (<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">byte</span>)(len + key + secretKey.length());<br mpa-from-tpl="t"> fos.write(data);<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"> } <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">catch</span> (Exception e) {<br mpa-from-tpl="t"> log.error(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 99px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"encrypt fail:"</span>+e.getMessage(),e);<br mpa-from-tpl="t"> }<span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">finally</span> {<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span>(fis != <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">null</span>){<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">try</span> {<br mpa-from-tpl="t"> fis.close();<br mpa-from-tpl="t"> } <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">catch</span> (IOException e) {<br mpa-from-tpl="t"> e.printStackTrace();<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span>(fos != <span style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(86, 182, 194);font-weight: 400;font-style: normal;">null</span>){<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">try</span> {<br mpa-from-tpl="t"> fos.close();<br mpa-from-tpl="t"> } <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">catch</span> (IOException e) {<br mpa-from-tpl="t"> e.printStackTrace();<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t">}</code></pre> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-id="86516" style="border-width: 0px;border-style: none;border-color: initial;" mpa-from-tpl="t"> <section style="border-bottom: 1px solid rgb(221, 221, 221);margin-right: auto;margin-bottom: 10px;margin-left: auto;" mpa-from-tpl="t"> <p data-brushtype="text" style="padding-right: 5px;padding-bottom: 6px;padding-left: 5px;border-bottom: 2px solid rgb(239, 112, 96);display: inline-block;margin-bottom: -1px;line-height: 1.1;font-size: 18px;"><span style="font-size: 16px;">2、对需要防止被反编译代码加密</span></p> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">void</span> main(<span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span>[] args) {<br mpa-from-tpl="t"> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span> classFileSrcPath = classFileSrcPath(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 112px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"UserServiceImpl"</span>);<br mpa-from-tpl="t"> System.out.println(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 152px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"classFileSrcPath:--->"</span>+classFileSrcPath);<br mpa-from-tpl="t"> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span> classFileDestDir = ServiceGenerate.class.getClassLoader().getResource(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 132px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"META-INF/services/"</span>).getPath();<br mpa-from-tpl="t"> System.out.println(<span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 152px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"classFileDestDir:--->"</span>+classFileDestDir);<br mpa-from-tpl="t"> <span style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span> classFileDestPath = classFileDestDir + <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 383px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"com.github.lybgeek.user.service.impl.UserServiceImpl.lyb"</span>;<br mpa-from-tpl="t"> EncryptUtils.encrypt(classFileSrcPath,classFileDestPath);<br mpa-from-tpl="t"> }</code></pre> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-id="86516" style="border-width: 0px;border-style: none;border-color: initial;" mpa-from-tpl="t"> <section style="border-bottom: 1px solid rgb(221, 221, 221);margin-right: auto;margin-bottom: 10px;margin-left: auto;" mpa-from-tpl="t"> <p data-brushtype="text" style="padding-right: 5px;padding-bottom: 6px;padding-left: 5px;border-bottom: 2px solid rgb(239, 112, 96);display: inline-block;margin-bottom: -1px;line-height: 1.1;font-size: 18px;"><span style="font-size: 16px;">3、对加密代码进行反编译验证</span></p> </section> </section> </section> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">打开反编译工具jd-gui,把加密的代码拖入jd-gui</span></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><img data-ratio="0.17586206896551723" src="/upload/60fb7aa18adecd8e7947cdf32e1090d2.png" data-type="png" data-w="580" style="border-width: initial;border-style: none;border-color: initial;margin-top: 20px;margin-bottom: 20px;max-width: 650px;"><br><span style="font-size: 15px;">打不开,至少说明不能用jd-gui来反编译加密过的代码。</span></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">我们打开正常的编译的class文件,其内容形如下</span><br><img data-ratio="0.06075268817204301" src="/upload/33875834f3ab6c5c5f63b17e183f84c4.png" data-type="png" data-w="1860" style="border-width: initial;border-style: none;border-color: initial;margin-top: 20px;margin-bottom: 20px;max-width: 650px;"><br><span style="font-size: 15px;">从内容我们大概还是能看出一些东西,比如包名啥的。而打开加密后的文件,其内容如下</span><br><img data-ratio="0.3293010752688172" src="/upload/761792242bddd84bedf57dcb517a752a.png" data-type="png" data-w="744" style="border-width: initial;border-style: none;border-color: initial;margin-top: 20px;margin-bottom: 20px;max-width: 650px;"><br><span style="font-size: 15px;">内容宛若天书</span></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><br></span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="padding:1px 5px;font-size:14px;white-space:normal;" mpa-from-tpl="t"> <h2 style="border-left: 5px solid rgb(0, 122, 170);font-weight: bold;line-height: 32px;color: rgb(0, 122, 170);padding-right: 10px;padding-left: 10px;margin: 5px;border-top-color: rgb(0, 122, 170);border-bottom-color: rgb(0, 122, 170);border-right-color: rgb(0, 122, 170);"><p>思考一:代码都被加密了,那jvm如何识别?</p></h2> </section> </section> <p><br mpa-from-tpl="t"></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><strong>答案</strong>:既然有加密,自然可以通过解密来使用。那这个解密得存放在什么地方进行解密?</span></p> <p style="margin: 10px auto;list-style-type: none;list-style-image: none;color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">如果对类加载有一定了解的朋友,就会知道java的class文件是通过类加载器把class加载入jvm内存中,因此我们可以考虑把解密放在类加载器中。常用的类加载有启动类加载器、扩展类加载器、系统类加载。我们正常classpath路径下的类都是通过系统类加载器进行加载。而不巧这三个jdk提供的加载器没法满足我们的需求。因此我们只能自己实现我们的类加载器。其自定义加载器代码如下</span></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;">@Slf4j<br mpa-from-tpl="t"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 112px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">CustomClassLoader</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 47px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">extends</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 73px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">ClassLoader</span>{<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 82px;text-decoration: none solid rgb(92, 99, 112);font-weight: 400;font-style: italic;">/**<br mpa-from-tpl="t"> * 授权码<br mpa-from-tpl="t"> */</span><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> String secretKey;<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> String SECRETKEY_PREFIX = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"lyb-geek"</span>;<br mpa-from-tpl="t"><br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 151px;text-decoration: none solid rgb(92, 99, 112);font-weight: 400;font-style: italic;">/**<br mpa-from-tpl="t"> * class文件的根目录<br mpa-from-tpl="t"> */</span><br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> String classRootDir = <span style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 132px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"META-INF/services/"</span>;<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 284px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 113px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">CustomClassLoader</span>(<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 106px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">String secretKey</span>) </span>{<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">this</span>.secretKey = secretKey;<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 211px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> String <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 99px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">getClassRootDir</span>(<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 0px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"></span>) </span>{<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">return</span> classRootDir;<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 324px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 99px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">setClassRootDir</span>(<span style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 125px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">String classRootDir</span>) </span>{<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">this</span>.classRootDir = classRootDir;<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> @Override<br mpa-from-tpl="t"> <span style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 60px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">protected</span> Class<?> findClass(String name) throws ClassNotFoundException {<br mpa-from-tpl="t"><br mpa-from-tpl="t"> &n
作者:微信小助手
<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;justify-content: flex-start;padding-left: 18px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;justify-content: space-between;width: 100%;height: 0px;z-index: 1;" data-mid="" mpa-from-tpl="t"> <section style="width: 6px;height: 6px;margin-left: 2px;margin-bottom: -10px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/692d2f326f96507dec125c043a7196c8.png" data-type="png" data-w="12" style="display: block;"> </section> <section style="width: 6px;height: 6px;margin-right: 6px;margin-bottom: -10px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/692d2f326f96507dec125c043a7196c8.png" data-type="png" data-w="12" style="display: block;"> </section> </section> <section style="background: rgb(255, 219, 107);border-width: 1px;border-style: solid;border-color: rgb(1, 71, 182);" data-mid="" mpa-from-tpl="t"> <section style="height: 34px;background: rgb(255, 255, 255);border-width: 1px;border-style: solid;border-color: rgb(1, 71, 182);text-align: center;transform: translate(-2px, -2px);padding: 0px 8px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Medium, PingFang SC;font-weight: bold;color: #0147B6;line-height: 34px;letter-spacing: 1px;" data-mid="">点击上方<span style="color: #333333FF;padding: 0px 4px;" data-mid="">蓝字</span>关注我们</p> </section> </section> <section style="display: flex;justify-content: center;align-items: center;justify-content: space-between;width: 100%;height: 0px;z-index: 1;" data-mid="" mpa-from-tpl="t"> <section style="width: 6px;height: 6px;margin-left: 2px;margin-top: -17px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/692d2f326f96507dec125c043a7196c8.png" data-type="png" data-w="12" style="display: block;"> </section> <section style="width: 6px;height: 6px;margin-right: 6px;margin-top: -17px;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1" src="/upload/692d2f326f96507dec125c043a7196c8.png" data-type="png" data-w="12" style="display: block;"> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="width: 18px;height: 18px;border-radius: 50%;border-width: 1px;border-style: solid;border-color: rgb(7, 248, 5);align-self: flex-end;margin-right: -9.1px;margin-bottom: -10.1px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="margin-bottom: 8px;display: flex;justify-content: flex-start;align-items: center;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section style="width: 37px;height: 38px;background: rgb(28, 46, 255);" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="text-align: center;margin-top: -30.1px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: bold;color: #FFFFFF;line-height: 22px;letter-spacing: 1px;" data-mid="">01</p> </section> </section> <section style="text-align: center;padding: 8px 15px 6px;border-width: 1px;border-style: solid;border-color: rgb(28, 46, 255);margin-left: 2px;" data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, "PingFang SC";font-weight: bold;color: rgb(28, 46, 255);line-height: 22px;letter-spacing: 1px;" data-mid=""><span style="font-size: 20px;">前言</span></p> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;width: 100%;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;flex-direction: column;width: 100%;padding: 0px 8px;" data-mid="" mpa-from-tpl="t"> <section style="width: 20px;height: 20px;background: #96FA90;border-radius: 50%;align-self: flex-start;margin-left: 7px;margin-bottom: -28.1px;margin-top: 10px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 100%;text-align: left;padding: 13px 7px 15px 15px;border-width: 1px;border-style: solid;border-color: rgb(25, 33, 236);" data-mid="" mpa-from-tpl="t"> <p style="font-size: 14px;font-family: PingFangSC-Medium, PingFang SC;font-weight: bold;color: #1921EC;line-height: 22px;" data-mid=""><span style="font-size: 18px;">什么是代码混淆</span><br></p> </section> <section style="align-self: flex-end;z-index: 1;display: flex;justify-content: center;align-items: center;margin-top: -1px;background: rgb(255, 255, 255);margin-right: 21px;" data-mid="" mpa-from-tpl="t"> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 5px;height: 1px;border-top: 1px solid #1921ec;margin-left: 1.5px;margin-right: 1.5px;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p><span style="color: rgb(68, 68, 68);font-family: Tahoma, Arial, Helvetica, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);">代码混淆,是指将计算�
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;text-align: left;font-family: "PingFang SC", "Microsoft YaHei", sans-serif;word-break: break-all;margin-bottom: 0px;" 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);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">生活中所受的苦,终会以一种形式回归!</p> </blockquote> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-size: 1.7em;border-bottom: 2px solid rgb(92, 157, 255);"><span style="display: none;"></span></h1> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg4NjYyODc4OA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/J4jTHmo8Xh6qM32ASOtVbXNoiaegrI26qLRw6r6FTI7dZw6TMT7vecvnjd1O8xSsM5MiajIuQZicxSC6KFK8TMpbg/0?wx_fmt=png" data-nickname="java突击队" data-alias="" data-signature="技术经验分享" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-size: 1.7em;border-bottom: 2px solid rgb(92, 157, 255);"><span style="background: hsl(216, 100%, 68%);color: white;padding: 3px 10px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">前言</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">因此,一般来说都是通过集群主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力进行部署与实施</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">总结MySQL主从集群带来的作用是:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提高数据库负载能力,主库执行读写任务(增删改),备库仅做查询。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提高系统读写性能、可扩展性和高可用性。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 数据备份与容灾,备库在异地,主库不存在了,备库可以立即接管,无须恢复时间。 </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;"> <img class="rich_pages wxw-img" data-ratio="0.5342592592592592" src="/upload/578d733e0f3b446b69c80c4619d9daa1.png" data-type="png" data-w="1080" style="display: block;width: 90%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">说到主从同步,离不开binlog这个东西,先介绍下binlog吧</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-size: 1.7em;border-bottom: 2px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="background: hsl(216, 100%, 68%);color: white;padding: 3px 10px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">binlog</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">binlog是什么?有什么作用?</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。可以简单理解为记录的就是sql语句</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">binlog 是 mysql 的逻辑日志,并且由 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">Server</code>层进行记录,使用任何存储引擎的 mysql 数据库都会记录 binlog 日志</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在实际应用中, binlog 的主要使用场景有两个:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">用于主从复制,在主从结构中,binlog 作为操作记录从 master 被发送到 slave,slave服务器从 master 接收到的日志保存到 relay log 中。</p> </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">用于数据备份,在数据库备份文件生成后,binlog保存了数据库备份后的详细信息,以便下一次备份能从备份点开始。</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">日志格式</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">binlog 日志有三种格式,分别为 STATMENT 、 ROW 和 MIXED</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在 MySQL 5.7.7 之前,默认的格式是 STATEMENT , MySQL 5.7.7 之后,默认值是 ROW</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">日志格式通过 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">binlog-format</code> 指定。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> STATMENT :基于 SQL 语句的复制,每一条会修改数据的sql语句会记录到 binlog 中 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ROW :基于行的复制 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> MIXED :基于 STATMENT 和 ROW 两种模式的混合复制,比如一般的数据操作使用 row 格式保存,有些表结构的变更语句,使用 statement 来记录 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">我们还可以通过mysql提供的查看工具mysqlbinlog查看文件中的内容,例如</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eHEMOF2hOeml8KfWjeCa2NaC3j4HgzsDUXrJopbBdYlQOVScTzrhzTwEF954vpjlkDmRhQg86SppibUO2AkH4ZOY48PMjtBvD/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">mysqlbinlog mysql-bin.00001 | more<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">binlog文件大小和个数会不断的增加,后缀名会按序号递增,例如<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">mysql-bin.00002</code>等。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-size: 1.7em;border-bottom: 2px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="background: hsl(216, 100%, 68%);color: white;padding: 3px 10px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">主从复制原理</span></h1> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.2796296296296296" src="/upload/928cd6e906ac2e475dafc772dc091d00.png" data-type="png" data-w="1080" style="display: block;width: 90%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">可以看到mysql主从复制需要三个线程:<strong style="color: rgb(22, 94, 202);">master(binlog dump thread)、slave(I/O thread 、SQL thread)</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">binlog dump线程:</strong> 主库中有数据更新时,根据设置的binlog格式,将更新的事件类型写入到主库的binlog文件中,并创建log dump线程通知slave有数据更新。当I/O线程请求日志内容时,将此时的binlog名称和当前更新的位置同时传给slave的I/O线程。</p> </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">I/O线程:</strong> 该线程会连接到master,向log dump线程请求一份指定binlog文件位置的副本,并将请求回来的binlog存到本地的relay log中。</p> </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">SQL线程:</strong> 该线程检测到relay log有更新后,会读取并在本地做redo操作,将发生在主库的事件在本地重新执行一遍,来保证主从数据同步。</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">基本过程总结</strong></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 主库写入数据并且生成binlog文件。该过程中MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 在事件写入二进制日志完成后,master通知存储引擎提交事务。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库服务器上的IO线程连接Master服务器,请求从执行binlog日志文件中的指定位置开始读取binlog至从库。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 主库接收到从库的IO线程请求后,其上复制的IO线程会根据Slave的请求信息分批读取binlog文件然后返回给从库的IO线程。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件的最末端,并将新的binlog文件名和位置记录到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">master-info</code>文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库服务器的SQL线程会实时监测到本地Relay Log中新增了日志内容,然后把RelayLog中的日志翻译成SQL并且按照顺序执行SQL来更新从库的数据。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库在 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">relay-log.info</code>中记录当前应用中继日志的文件名和位置点以便下一次数据复制。 </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;color: rgb(51, 51, 51);font-size: 1.4em;border-bottom: 1px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="border-bottom: 1px solid hsl(216, 100%, 68%);">并行复制</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在MySQL 5.6版本之前,Slave服务器上有两个线程I/O线程和SQL线程。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">I/O线程负责接收二进制日志,SQL线程进行回放二进制日志。如果在MySQL 5.6版本开启并行复制功能,那么SQL线程就变为了coordinator线程,coordinator线程主要负责以前两部分的内容</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5138888888888888" src="/upload/4bd9320a3a4b6cf4e40f8ba41e14c8af.png" data-type="png" data-w="1080" style="display: block;width: 90%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">上图的红色框框部分就是实现并行复制的关键所在</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">这意味着coordinator线程并不是仅将日志发送给worker线程,自己也可以回放日志,但是所有可以并行的操作交付由worker线程完成。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">coordinator线程与worker是典型的生产者与消费者模型。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4425925925925926" src="/upload/8f8e308814e58b5c5f5bf0c4f4396579.png" data-type="png" data-w="1080" style="display: block;width: 90%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">不过到MySQL 5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">slave-parallel-type</code>,其可以配置的值有:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> DATABASE:默认值,基于库的并行复制方式 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> LOGICAL_CLOCK:基于组提交的并行复制方式 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">下面分别介绍下两种并行复制方式</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">按库并行</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">每个 worker 线程对应一个 hash 表,用于保存当前正在这个worker的执行队列里的事务所涉及到的库。其中hash表里的key是数据库名,用于决定分发策略。该策略的优点是构建hash值快,只需要库名,同时对于binlog的格式没有要求。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">但这个策略的效果,只有在主库上存在多个DB,且各个DB的压力均衡的情况下,这个策略效果好。因此,对于主库上的表都放在同一个DB或者不同DB的热点不同,则起不到多大效果</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6" src="/upload/9c4be47f50273e3ba93c697ce6bca0b5.png" data-type="png" data-w="1080" style="display: block;width: 90%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">组提交优化</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">该特性如下:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">能够同一组里提交的事务,定不会修改同一行;</p> </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">主库上可以并行执行的事务,从库上也一定可以并行执行。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">具体是如何实现的:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在同一组里面一起提交的事务,会有一个相同的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">commit_id</code>,下一组为<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">commit_id+1</code>,该<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">commit_id</code>会直接写到binlog中;</p> </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">在从库使用时,相同<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">commit_id</code>的事务会被分发到多个worker并行执行,直到这一组相同的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">commit_id</code>执行结束后,coordinator再取下一批。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">更详细内容可以去官网看看:https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7777777777777778" src="/upload/76f8d0dcf632a1a5322a28d8098d4b90.png" data-type="png" data-w="216" style="display: block;width: 46%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;height: auto !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">下面开始介绍主从延时</strong></p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-size: 1.7em;border-bottom: 2px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="background: hsl(216, 100%, 68%);color: white;padding: 3px 10px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">主从延迟</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">主从延迟是怎么回事?</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">根据前面主从复制的原理可以看出,两者之间是存在一定时间的数据不一致,也就是所谓的主从延迟。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">我们来看下导致主从延迟的时间点:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 主库 A 执行完成一个事务,写入 binlog,该时刻记为T1. </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 传给从库B,从库接受完这个binlog的时刻记为T2. </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库B执行完这个事务,该时刻记为T3. </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">那么所谓主从延迟,就是同一个事务,从库执行完成的时间和主库执行完成的时间之间的差值,即T3-T1。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">我们也可以通过在从库执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">show slave status</code>,返回结果会显示<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">seconds_behind_master</code>,表示当前从库延迟了多少秒。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">seconds_behind_master如何计算的?</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 每一个事务的binlog都有一个时间字段,用于记录主库上写入的时间 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库取出当前正在执行的事务的时间字段,跟当前系统的时间进行相减,得到的就是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">seconds_behind_master</code>,也就是前面所描述的T3-T1。 </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;"> <img class="rich_pages wxw-img" data-ratio="1" src="/upload/acdbd9f4500ea4af5b6d32a614bddce9.png" data-type="png" data-w="250" style="display: block;width: 35%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;height: auto !important;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;color: rgb(51, 51, 51);font-size: 1.4em;border-bottom: 1px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="border-bottom: 1px solid hsl(216, 100%, 68%);">主从延迟原因</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);"><strong style="color: rgb(22, 94, 202);">为什么会主从延迟?</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">正常情况下,如果网络不延迟,那么日志从主库传给从库的时间是相当短,所以T2-T1可以基本忽略。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">最直接的影响就是从库消费中转日志(relaylog)的时间段,而造成原因一般是以下几种:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">1、从库的机器性能比主库要差</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">比如将20台主库放在4台机器,把从库放在一台机器。这个时候进行更新操作,由于更新时会触发大量读操作,导致从库机器上的多个从库争夺资源,导致主从延迟。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">不过,目前大部分部署都是采取主从使用相同规格的机器部署。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">2、从库的压力大</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">按照正常的策略,读写分离,主库提供写能力,从库提供读能力。将进行大量查询放在从库上,结果导致从库上耗费了大量的CPU资源,进而影响了同步速度,造成主从延迟。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">对于这种情况,可以通过一主多从,分担读压力;也可以采取binlog输出到外部系统,比如Hadoop,让外部系统提供查询能力。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">3、大事务的执行</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">一旦执行大事务,那么主库必须要等到事务完成之后才会写入binlog。</p> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">比如主库执行了一条insert … select非常大的插入操作,该操作产生了近几百G的binlog文件传输到只读节点,进而导致了只读节点出现应用binlog延迟。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">因此,DBA经常会提醒开发,不要一次性地试用delete语句删除大量数据,尽可能控制数量,分批进行。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">4、主库的DDL(alter、drop、create)</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">1、只读节点与主库的DDL同步是串行进行,如果DDL操作在主库执行时间很长,那么从库也会消耗同样的时间,比如在主库对一张500W的表添加一个字段耗费了10分钟,那么从节点上也会耗费10分钟。</p> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">2、从节点上有一个执行时间非常长的的查询正在执行,那么这个查询会堵塞来自主库的DDL,表被锁,直到查询结束为止,进而导致了从节点的数据延迟。</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="1" src="/upload/5d12f1b2781d94f4694ea7039cef340f.jpg" data-type="jpeg" data-w="198" style="display: block;width: 35%;margin-right: auto;margin-left: auto;box-shadow: rgb(204, 204, 204) 0px 10px 15px;height: auto !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">5、锁冲突</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">锁冲突问题也可能导致从节点的SQL线程执行慢,比如从机上有一些select .... for update的SQL,或者使用了MyISAM引擎等。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">6、从库的复制能力</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;background: rgb(249, 249, 249);border-left-color: rgb(92, 157, 255);"> <p style="font-size: 16px;line-height: 26px;color: rgb(153, 153, 153);padding-top: 3px;padding-bottom: 3px;">一般场景中,因偶然情况导致从库延迟了几分钟,都会在从库恢复之后追上主库。但若是从库执行速度低于主库,且主库持续具有压力,就会导致长时间主从延迟,很有可能就是从库复制能力的问题。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">从库上的执行,即<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">sql_thread</code>更新逻辑,在5.6版本之前,是只支持单线程,那么在主库并发高、TPS高时,就会出现较大的主从延迟。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">因此,MySQL自5.7版本后就已经支持并行复制了。可以在从服务上设置 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">slave_parallel_workers</code>为一个大于0的数,然后把<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">slave_parallel_type</code>参数设置为<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(92, 157, 255);">LOGICAL_CLOCK</code>,这就可以了</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eHEMOF2hOeml8KfWjeCa2NaC3j4HgzsDUXrJopbBdYlQOVScTzrhzTwEF954vpjlkDmRhQg86SppibUO2AkH4ZOY48PMjtBvD/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">mysql> <span style="color: #c678dd;line-height: 26px;">show</span> <span style="color: #c678dd;line-height: 26px;">variables</span> <span style="color: #c678dd;line-height: 26px;">like</span> <span style="color: #98c379;line-height: 26px;">'slave_parallel%'</span>;<br>+<span style="color: #5c6370;font-style: italic;line-height: 26px;">------------------------+----------+</span><br>| Variable_name | Value |<br>+<span style="color: #5c6370;font-style: italic;line-height: 26px;">------------------------+----------+</span><br>| slave_parallel_type | DATABASE |<br>| slave_parallel_workers | 0 |<br>+<span style="color: #5c6370;font-style: italic;line-height: 26px;">------------------------+----------+</span><br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;color: rgb(51, 51, 51);font-size: 1.4em;border-bottom: 1px solid rgb(92, 157, 255);"><span style="display: none;"></span><span style="border-bottom: 1px solid hsl(216, 100%, 68%);">怎么减少主从延迟</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(102, 102, 102);">主从同步问题永远都是一致性和性能的权衡,得看实际的应用场景,若想要减少主从延迟的时间,可以采取下面的办法:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 2em;" class="list-paddingleft-1"> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 降低多线程大事务并发的概率,优化业务逻辑 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 优化SQL,避免慢SQL,减少批量操作,建议写脚本以update-sleep这样的形式完成。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提高从库机器的配置,减少主库写binlog和从库读binlog的效率差。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 尽量采用短的链路,也就是主库和从库服务器的距离尽量要短,提升端口带宽,减少binlog传输的网络延时。 </section></li> <li style="color: #666;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 实时性要求的业务读强制走主库,从库只做灾备,备份。 </section></li> </ol> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">大家好呀,我是楼仔。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">技术是什么?就是拿来玩的,边玩边学,才能成长得更快。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">之前已经给大家讲解了 MySQL 同步 ES 的几种方案,下面就教大家如何通过 Canal,将 MySQL 同步到 ES,文章内容绝对妥妥干货!</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">本文会先讲解需要用到的基础知识,然后再是软件安装,最后就是实战部分。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">不 BB,上文章目录:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.2416666666666667" src="/upload/b9e0355cc0f18b9d30174a04b130611f.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;"><span style="display: none;"></span>01 基础知识</h1> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">1.1 主从复制原理</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">MySQL 的主从复制是依赖于 binlog,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘上二进制日志文件。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">主从复制就是将 binlog 中的数据从主库传输到从库上,一般这个过程是异步的,即主库上的操作不会等待 binlog 同步地完成。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5276476101218369" src="/upload/b09c5ba12bbe2761e1b2980128858464.png" data-type="png" data-w="1067" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">详细流程如下:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 主库写 binlog:主库的更新 SQL(update、insert、delete) 被写到 binlog; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 主库发送 binlog:主库创建一个 log dump 线程来发送 binlog 给从库; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库写 relay log:从库在连接到主节点时会创建一个 IO 线程,以请求主库更新的 binlog,并且把接收到的 binlog 信息写入一个叫做 relay log 的日志文件; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 从库回放:从库还会创建一个 SQL 线程读取 relay log 中的内容,并且在从库中做回放,最终实现主从的一致性。 </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">1.2 Cannel 基础</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Canel 是一款常用的数据同步工具,其原理是基于 Binlog 订阅的方式实现,<strong>模拟一个 MySQL Slave 订阅 Binlog 日志,从而实现 CDC</strong>(Change Data Capture),将已提交的更改发送到下游。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">主要流程如下:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Canal 服务端向 MySQL 的 master 节点传输 dump 协议; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> MySQL 的 master 节点接收到 dump 请求后推送 Binlog 日志给 Canal 服务端,解析 Binlog 对象(原始为 byte 流)转成 Json 格式; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Canal 客户端通过 TCP 协议或 MQ 形式监听 Canal 服务端,同步数据到 ES。 </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5409836065573771" src="/upload/f548c5fbc01bb0965f1cb3a5c955abe7.png" data-type="png" data-w="976" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">下面是 Cannel 执行的核心流程,其中 Binlog Parser 主要负责 Binlog 的提取、解析和推送,EventSink 负责数据的过滤 、路由和加工,仅作了解即可。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.8713858424725822" src="/upload/155964c65e95d4b8234c0b7bfe73e0b2.png" data-type="png" data-w="1003" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;"><span style="display: none;"></span>02 软件下载安装</h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我的电脑是 Macos-x64,所以后面的软件安装,都是基于这个。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.1 Java JDK</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 官网:https://www.oracle.com/java/technologies/downloads/ </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> JDK 版本:11.0.19 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">由于 Canal 和 ES 的安装,都强依赖 JDK,所以这里有必要先说明。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5796296296296296" src="/upload/c361a96b10a326de8f20a8b247a5c69f.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>前方高能,这里有坑!!!</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如果你选的版本不对,ES 安装可能会失败,然后 Canal 同步数据到 ES 时,也会出现很多诡异的问题。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.2 MySQL</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">MySQL 大家应该都安装了,这里需要打开 MySQL 的 BinLog。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我是 Mac,主要新建一个 my.cnf 文件,然后再重启 MySQL。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.21021611001964635" src="/upload/d35938b8e5d8fbb8c319e0de9b6c6829.png" data-type="png" data-w="509" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.2899786780383795" src="/upload/8ea6a80cf1d5cab47d048d26c63c5bed.png" data-type="png" data-w="469" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里重启 MySQL,我搞了半天,BinLog 开启后,会看到 BinLog 日志。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.8324420677361853" src="/upload/44afd44511a12c3a3de298c887c91292.png" data-type="png" data-w="561" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">然后需要创建一个账号,账号和密码都是 Cannal,给后面 Canal 使用。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO <span style="color: #98c379;line-height: 26px;">'canal'</span>@<span style="color: #98c379;line-height: 26px;">'localhost'</span> IDENTIFIED BY <span style="color: #98c379;line-height: 26px;">'canal'</span> ;<br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.3 Canal</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 官网:https://github.com/alibaba/canal/releases </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 版本:v1.1.6 </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;"> <img data-ratio="0.35783783783783785" src="/upload/7eecbd48dc35ada4ee6a624842e58abb.png" data-type="png" data-w="925" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">下载 canal.adapter 和 canal.deployer 两个就可以:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> canal.deployer:相当于 canal 的服务端,启动它才可以在客户端接收数据库变更信息。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> canal.adapter:增加客户端数据落地的适配及启动功能(当 deployer 接收到消息后,会根据不同的目标源做适配,比如是 es 目标源适配和 hbase 适配等等)。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">备注:canal.admin 为 canal提供整体配置管理、节点运维等面向运维的功能,提供相对友好的 WebUI 操作界面,方便更多用户快速和安全的操作,我这边使用的是单机的,因此就没有下载安装,大家也可以拉 source code 源码去研究下。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.4 ES</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ES 官网:https://www.elastic.co/cn/downloads/elasticsearch </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ES 版本:7.17.4 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Mac 安装 ES 非常简单:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">brew install elasticsearch<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">安装细节不赘述,安装成功后,输入以下网址:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">http://localhost:9200/?pretty<br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.8423566878980892" src="/upload/3c19f5906ba87e8d7c79ea2a401650cb.png" data-type="png" data-w="628" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.5 Kibana</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 下载网址:https://www.elastic.co/cn/downloads/past-releases#kibana </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 版本:7.14.0 </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;"> <img data-ratio="0.13425925925925927" src="/upload/549ccbff8b8200d28d74e3479327b837.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">它是 ES 的界面化操作工具,安装细节不赘述,安装成功后,输入以下网址:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">http://localhost:5601/app/dev_tools<span style="color: #5c6370;font-style: italic;line-height: 26px;">#/console</span><br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4444444444444444" src="/upload/f277ac1574a152bbb651c343c8826ff2.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.6 IK 分词器</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 下载网址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.17.2 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 版本:v7.17.2 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">它是 ES 的分词器,安装细节不赘述,安装成功后,可以验证一下分词效果。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.7574074074074074" src="/upload/371193b838e91f1f86cecc5c1d8ec26d.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">2.7 小节</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">MySQL 开启 BinLog,这个不难,主要观察是否有 BinLog 日志。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Canal 的安装是最复杂的,涉及到很多配置修改,后面会讲解。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最后是 ES + Kibana + IK 分词器,这个其实也不难,主要关注 ES 绑定的 JDK 版本,三款软件的安装可以参考这篇:https://blog.csdn.net/weixin_46049028/article/details/129956485</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;"><span style="display: none;"></span>03 Canal 配置</h1> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">3.1 canal.deployer 配置</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">修改 conf—>example 文件夹的 instance.properties 监听的数据库配置。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.23703703703703705" src="/upload/b4309f680aaad4c7211b446da11a1256.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里主要修改的监听 MySQL 的 URL、用户名和密码。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.0223776223776224" src="/upload/9fc762472aa83d6653d427f653338d0c.png" data-type="png" data-w="715" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里默认的账号密码就是 canal,前面已经教大家如何创建了。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">3.2 canal.deployer 启动</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在 canal.deployer 中的 bin 文件下去启动命令 startup.sh</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.2814814814814815" src="/upload/d68a5e807c67659e05b0e30a021f95e8.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.3453333333333333" src="/upload/4f96cadeb1b6bb73850b305dddb94304.png" data-type="png" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这样就代表已经启动了,我们可以去看下启动日志。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.2064814814814815" src="/upload/5b9a1e02d55ac9b677d22f2b5b4b79a3.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4573333333333333" src="/upload/daa26306e0ac8a5ea219b89d252c0ef8.png" data-type="png" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上面 start successful 代表已经启动成功,并且已经监听我的 MySQL 数据库。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">3.3 canal.adapte 配置</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>Step1</strong>: 先把 adapter 下面的 bootstrap.yml,全部注释掉,否则会提示你 XX 表不存在,这里坑了我好惨。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.3425925925925926" src="/upload/9e2cf7d6eaf6b9349bfd85f0b6de7a66.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.21922626025791325" src="/upload/eaa7f0ac8d07ec496597f9f049659c5d.png" data-type="png" data-w="853" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>Step2</strong>: 再修改 adapter 的 application.yml 配置文件。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4759259259259259" src="/upload/4abf68c117fe93d82d89ac708391086e.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里的坑,一般就是 mysql 的账号密码不对,或者给的 es 链接,没有"http://"前缀,这些都是我过踩的坑。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>Step3</strong>: 修改我们在 application.yml 中配置的目标数据源 es7 文件夹内容。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4564814814814815" src="/upload/444b2d2dc27a98e5e8f855bc545c4445.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">由于我们这里是对表 article 进行去监听,因此我们在 es7 文件夹中去创建 article.yml 文件。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.3373333333333333" src="/upload/2324d307492ce22a3c9f596c2a6fe0cd.png" data-type="png" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">由于我们需要把技术派项目中的文章查询功能,改造成 ES 的查询方式,所以我们就把技术派的文章表 article,同步到 ES 中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">yml文件配置如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.3648148148148148" src="/upload/8664f9001c3ea564694c5708f2d82e0f.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">dataSourceKey: defaultDS # 源数据源的key, 对应上面配置的srcDataSources中的值<br>destination: example # canal的instance或者MQ的topic<br>groupId: g1 # 对应MQ模式下的groupId, 只会同步对应groupId的数据<br>esMapping:<br> _index: article # es 的索引名称<br> _id: _id # es 的_id, 如果不配置该项必须配置下面的pk项_id则会由es自动分配<br> sql: <span style="color: #98c379;line-height: 26px;">"SELECT t.id AS _id,t.id,t.user_id,t.article_type,t.title,t.short_title,t.picture,<br> t.summary,t.category_id,t.source,t.source_url,t.offical_stat,t.topping_stat,<br> t.cream_stat,t.`status`,t.deleted,t.create_time,t.update_time<br> FROM article t"</span> # sql映射<br> commitBatch: <span style="color: #d19a66;line-height: 26px;">1</span> # 提交批大小<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>Step4</strong>: 在 Kibana 中创建 ES 的 article 索引</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">代码如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">PUT /article<br>{<br> <span style="color: #98c379;line-height: 26px;">"mappings"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"properties"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"id"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"user_id"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"article_type"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"title"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"text"</span>,<br> <span style="color: #98c379;line-height: 26px;">"analyzer"</span>: <span style="color: #98c379;line-height: 26px;">"ik_max_word"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"short_title"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"text"</span>,<br> <span style="color: #98c379;line-height: 26px;">"analyzer"</span>: <span style="color: #98c379;line-height: 26px;">"ik_max_word"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"picture"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"text"</span>,<br> <span style="color: #98c379;line-height: 26px;">"analyzer"</span>: <span style="color: #98c379;line-height: 26px;">"ik_max_word"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"summary"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"text"</span>,<br> <span style="color: #98c379;line-height: 26px;">"analyzer"</span>: <span style="color: #98c379;line-height: 26px;">"ik_max_word"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"category_id"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"source"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"source_url"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"text"</span>,<br> <span style="color: #98c379;line-height: 26px;">"analyzer"</span>: <span style="color: #98c379;line-height: 26px;">"ik_max_word"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"offical_stat"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"topping_stat"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"cream_stat"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"status"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"deleted"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"integer"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"create_time"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"date"</span><br> },<br> <span style="color: #98c379;line-height: 26px;">"update_time"</span> : {<br> <span style="color: #98c379;line-height: 26px;">"type"</span> : <span style="color: #98c379;line-height: 26px;">"date"</span><br> }<br> }<br> }<br> }<br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">3.4 canal.adapte 启动</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.6986666666666667" src="/upload/64e9251884a1d4c447549638c7b31cdb.png" data-type="png" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我们看下启动日志:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5217391304347826" src="/upload/7b5bd64c0d647c9afa8076784160ff3.png" data-type="png" data-w="828" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上面没有任何报错,并且已经启动了 8081 端口,说明已经启动成功,此时我们就可以操作了。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;"><span style="display: none;"></span>04 数据同步实战</h1> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">4.1 全量同步</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在开始 adapter 之后,我们应该先来一把全量数据同步,在源码中提供了一个接口进行全量同步,命令如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">curl http://127.0.0.1:8081/etl/es7/article.yml -X POST<br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.2185430463576159" src="/upload/7d563e338267f9ddd592f7192459897.png" data-type="png" data-w="604" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上面就是执行同步成功后,提示已经导入 10 条。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4815983175604627" src="/upload/26621a20ef8634a322be3c408bcd23cc.png" data-type="png" data-w="951" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">4.2 增量同步</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">增量数据就是当我在 MySQL 中 update、delete 和 insert 时,那么 ES 中数据也会对应发生变化,我下面演示下修改:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.34814814814814815" src="/upload/18c4721d9d73b643acc07b84f17de7c.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">日志打印如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.45185185185185184" src="/upload/2fdb722ebb43be6b798bd37b06d4b342.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">ES查询结果如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.6694444444444444" src="/upload/5ee50fa1f01472957183f6754b48275f.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上面结果中说明 ES 已经更改成功。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;"><span style="display: none;"></span>05 总结</h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我们再回顾一下整体执行流程:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.2938388625592417" src="/upload/9de840234457a464af4c9a359b2d1a06.png" data-type="png" data-w="844" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">写到这里,就结束了,是不是满满的干货呢?基本是手把手教你如何将 MySQL 同步到 ES,,如果你的项目也需要用到该场景,基本可以直接照搬。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"></figure> </section>
作者:微信小助手
<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(74, 74, 74);letter-spacing: 0.5444px;padding-left: 5px;padding-right: 5px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 24px;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong>大家好呀,我是楼仔。</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务消息是 RocketMQ 的高级特性之一 。这篇文章,笔者会从<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">应用场景</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">功能原理</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">实战例子</strong>三个模块慢慢为你揭开事务消息的神秘面纱。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">1 应用场景</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">举一个电商场景的例子:用户购物车结算时,系统会创建支付订单。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">用户支付成功后支付订单的状态会由未支付修改为支付成功,然后系统给用户增加积分。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">通常我们会使用普通消费方案,该方案能够发挥 MQ 的优势:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">异步</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">解耦</strong> , 同时架构设计非常简单。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.13226744186046513" src="/upload/6930a8f4822872bf21097d82e7d5d77a.png" data-type="png" data-w="688" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 用户购物车结算时,系统创建支付订单; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 支付成功后,更新订单的状态从未支付修改为支付成功; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 发送一条普通消息到消息队列服务端; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 积分服务消费消息,添加积分记录。 </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">但该方案有个非常直观的缺点:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">容易出现不一致的现象</strong>。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先发送消息,后修改订单状态,消息发送成功,订单没有执行成功,需要回滚整个事务(订单数据事务回滚,积分服务消费时,需要先反查事务状态,若事务提交,才能插入积分记录)。</p> </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先修改订单状态,后发送消息,订单状态修改成功,但消息发送失败,需要补偿操作才能保持最终一致。</p> </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <p style="text-align: justify;line-height: 30px;font-size: 15px;letter-spacing: 0.5444px;margin-bottom: 20px;">假如先修改订单,后发送消息,订单状态修改成功,但消息发送超时,此时无法判断需要回滚订单还是提交订单变更。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">我们看到,为了完善普通消费方案,业务层还需要做到两点:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">补偿机制</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提供事务状态查询接口</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">要做到这两点,难不难呢?</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">不难,但是业务层代码会比较混乱,更优的方案还是得从中间件层面解决。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">2 功能原理</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">RocketMQ 事务消息是支持在分布式场景下<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">保障消息生产和本地事务的最终一致性</strong>。交互流程如下图所示:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.2116527942925089" src="/upload/dd621af132498190f8e6adece97871f6.png" data-type="png" data-w="841" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">1、生产者将消息发送至 Broker 。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">2、Broker 将消息持久化成功之后,向生产者返回 Ack 确认消息已经发送成功,此时消息被标记为"<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">暂不能投递</strong>",这种状态下的消息即为<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">半事务消息</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">3、生产者开始<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务逻辑</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">4、生产者根据本地事务执行结果向服务端<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提交二次确认结果</strong>( Commit 或是 Rollback ),Broker 收到确认结果后处理逻辑如下:</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: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Commit :Broker 将半事务消息标记为可投递,并投递给消费者。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Rollback :Broker 将回滚事务,不会将半事务消息投递给消费者。 </section></li> </ul> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">5、在断网或者是生产者应用重启的特殊情况下,若 Broker 未收到发送者提交的二次确认结果,或 Broker 收到的二次确认结果为 Unknown 未知状态,经过固定时间后,服务端将对消息生产者即生产者集群中任一生产者实例发起<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消息回查</strong>。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 生产者收到消息回查后,需要检查对应消息的本地事务执行的最终结果。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 生产者根据检查到的本地事务的最终状态 <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">再次提交二次确认</strong>,服务端仍按照步骤4对半事务消息进行处理。 </section></li> </ol> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">笔者认为事务消息的精髓在于:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">本地事务执行成功,消费者才能消费事务消息</strong>; </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 消息回查本身就是补偿机制的实现,事务生产者需提供了事务状态查询接口。 </section></li> </ol> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">3 实战例子</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">为了便于大家理解事务消息 ,笔者新建一个工程用于模拟<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">支付订单创建</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">支付成功</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">赠送积分</strong>的流程。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">首先,我们创建一个真实的订单主题:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">order-topic</strong> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6231721034870641" src="/upload/2fcef02672332fb1ceb444d460c368e8.png" data-type="png" data-w="889" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">然后在数据库中创建三张表 <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">订单表</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务日志表</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">积分表</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8853118712273642" src="/upload/76c29e03a3c3192b3f10848555629eab.png" data-type="png" data-w="497" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">最后我们创建一个 Demo 工程,生产者模块用于创建支付订单、修改支付订单成功,消费者模块用于新增积分记录。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7722222222222223" src="/upload/b840329e931bcd302a2f25bed9a47397.png" data-type="png" data-w="360" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">接下来,我们展示事务消息的实现流程。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">1、创建支付订单</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">调用订单生产者服务创建订单接口 ,在 t_order 表中插入一条支付订单记录。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5" src="/upload/71509a5b75328ddcb3fd4a6ebca09785.png" data-type="png" data-w="474" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">2、调用生产者服务修改订单状态接口</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">接口的逻辑就是执行事务生产者的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> sendMessageInTransaction</code> 方法。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.47523427041499333" src="/upload/a3da3fa62c3e280c8a6084f35947b684.png" data-type="png" data-w="747" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">生产者端需要配置<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务生产者</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">事务监听器</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8753351206434317" src="/upload/1f7006c3aa15f83e514a1162011eb428.png" data-type="png" data-w="746" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";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;"> <img class="rich_pages wxw-img" data-ratio="1.3319502074688796" src="/upload/d37621ddc0db5ccf9b358e77b54f2459.png" data-type="png" data-w="241" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务生产者首先<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">发送半事务消息</strong>,发送成功后,生产者才开始<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务逻辑</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">事务监听器实现了两个功能:<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">执行本地事务</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">供 Broker 回查事务状态</strong> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="1.1437908496732025" src="/upload/709611931ded04602e6f082100a2fb24.png" data-type="png" data-w="765" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">执行本地事务的逻辑内部就是执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> orderService.updateOrder</code> 方法。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">方法执行成功则返回 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);">LocalTransactionState.COMMIT_MESSAGE</code> , 若执行失败则返回 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> LocalTransactionState.ROLLBACK_MESSAGE</code> 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.45515394912985274" src="/upload/2fbf38095b5cb9c528f07d34fbefb482.png" data-type="png" data-w="747" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">需要注意的是:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);"> orderService.updateOrder</code> 方法添加了事务注解,并将修改订单状态和插入事务日志表放进一个事务内,避免订单状态和事务日志表的数据不一致。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">最后,生产者根据本地事务执行结果向 Broker <strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">提交二次确认结果</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">Broker 收到生产者确认结果后处理逻辑如下:</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: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Commit :Broker 将半事务消息标记为可投递,并投递给消费者。 </section></li> <li> <section style="margin-bottom: 10px;line-height: 25px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;color: rgb(74, 74, 74);letter-spacing: 0.5444px;"> 二次确认结果为 Rollback :Broker 将回滚事务,不会将半事务消息投递给消费者。 </section></li> </ul> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;"><strong style="letter-spacing: 0.5444px;line-height: inherit;color: black;">3、积分消费者消费消息,添加积分记录</strong></p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">当 Broker 将半事务消息标记为可投递时,积分消费者就可以开始消费主题 order-topic 的消息了。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5225" src="/upload/44cf0591ac5e0bf0769fd842784a9082.png" data-type="png" data-w="800" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">积分消费者服务,我们定义了<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消费者组名</strong>,以及<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">订阅主题</strong>和<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">消费监听器</strong>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8415614236509759" src="/upload/5b493477404df84dd856e75ec4911407.png" data-type="png" data-w="871" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">在消费监听器逻辑里,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(234, 84, 41);">幂等非常重要</code> 。当收到订单信息后,首先判断该订单是否有积分记录,若没有记录,才插入积分记录。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">而且我们在创建积分表时,订单编号也是唯一键,数据库中也必然不会存在相同订单的多条积分记录。</p> <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: 16px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);">4 总结</span></h1> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">RocketMQ 事务消息是支持在分布式场景下<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">保障消息生产和本地事务的最终一致性</strong>。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">编写一个实战例子并不复杂,但使用事务消息时需要注意如下三点:</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">1、事务生产者和消费者共同协作才能保证业务数据的最终一致性;</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">2、事务生产者需要实现事务监听器,并且保存事务的执行结果(比如事务日志表) ;</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">3、消费者要保证幂等。消费失败时,通过<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">重试</strong>、<strong style="color: rgb(34, 34, 34);letter-spacing: 0.5444px;">告警+人工介入</strong>等手段保证消费结果正确。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">本文涉及到的工程源码,笔者已上传到 Github ,感兴趣的同学可以了解一下,若有疑问直接加笔者好友,一起交流技术,一起成长。</p> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">笔者会在后续的文章里,详细解析事务消息的实现原理,敬请期待。</p> <hr data-tool="mdnice编辑器" style="height: 1px;border-right: none;border-bottom: none;border-left: none;border-top-style: solid;border-top-color: black;margin-top: 20px;margin-bottom: 20px;"> <p data-tool="mdnice编辑器" style="text-align: justify;line-height: 30px;font-family: "Avenir, -apple-system-font, 微软雅黑, sans-serif";letter-spacing: 0.5444px;margin-bottom: 20px;">实战代码地址:</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);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: "Avenir, -apple-system-font, 微软雅黑, sans-serif";font-size: 16px;margin-bottom: 10px;color: rgb(74, 74, 74);line-height: 30px;letter-spacing: 0.5444px;">https://github.com/makemyownlife/rocketmq4-learning</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.3995006242197253" src="/upload/705460cbb997a4a3978c5f71ed547846.png" data-type="png" data-w="801" style="display: block;margin-right: auto;margin-left: auto;margin-bottom: 15px;"> </figure> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <hr data-tool="mdnice编辑器" style="height: 1px;margin-top: 10px;margin-bottom: 10px;border-right: none;border-bottom: none;border-left: none;border-top-style: solid;border-top-color: black;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>最后,把楼仔的座右铭送给你</strong>:我从清晨走过,也拥抱夜晚的星辰,人生没有捷径,你我皆平凡,你好,陌生人,一起共勉。</p> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg3OTU5NzQ1Mw==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/sXFqMxQoVLFTdSvrrpJnCZ0Fp5Z1wKkhKFQBxTaFfxOpib3E2zgUu39BFbsBqqJbEpxicUvz3H6csoL2JQ9EP1yQ/0?wx_fmt=png" data-nickname="楼仔" data-alias="" data-signature="8 年一线大厂(百度小米美团)开发/架构/管理经验,专注硬核文章输出!" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>硬核推荐:<span style="display: none;"></span></h5> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495887&idx=1&sn=356883617e997b83151b5e994e7eeec4&chksm=cf00b22df8773b3b8c8c688fa1ab3c7ccb0e8a8ddb7a1aa07d37cb8152d3f2c7fab8a9f2ac53&token=1933785960&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">技术派中ES集成的实现姿势</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495862&idx=1&sn=b72a92c0333ea36572ccf8c031a814d4&chksm=cf00b254f8773b421856c4205747e1cd91e7968c0f2274a8e2a32ebebe23edd4da90b22aed40&token=1933785960&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">MySQL 同步 ES 实战,肝到爆!</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495667&idx=1&sn=db925845bb6a4dfc3ccc3ef844f01cbb&chksm=cf00ad11f8772407a6734fc38b5abbc62f6cdb07ffcf70da7a7f1537e211517ce2478fea1db3&token=1933785960&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">4 种 MySQL 同步 ES 方案,yyds!</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495653&idx=1&sn=93103ca6c3c47a1d92b7afbd9879be85&chksm=cf00ad07f8772411e66eabca9515596f037b7f7aeb1bb0e43395c7d817d1f74d2561bac49114&token=35480907&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">我用ChatGPT,给RabbitMQ加了个连接池</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495630&idx=1&sn=0bbab9b562359d100870c62f773baffa&chksm=cf00ad2cf877243a8e4781b456a057f420fbff59907483aa55416d2b7892f99878696dd68feb&token=407408896&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">从原理到实战,手把手教你在项目中使用RabbitMQ</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495609&idx=1&sn=3ebf0145c89ab44f128ee869f43dd203&chksm=cf00ad5bf877244d18523ace01a2912c6b965c6de9f48c52cfbc566a4e690eba3dfcfae215e8&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">技术派中的缓存一致性解决方案</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495588&idx=1&sn=d2b7c7da309b4ff38c8c99c28662ae27&chksm=cf00ad46f877245056a50b3e39a28614ad6e84732dade0f0351b01a7940e807f06ddbf986b0c&token=882597009&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">如何将技术派项目写入简历</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247495400&idx=1&sn=e783ca0eeb596469341c814850d5e66c&chksm=cf00ac0af877251cf45258a2de5d59e7da62c4b49d950547fa3f8d4731de6322c0373a128b08&token=882597009&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">对标大厂的技术派的详细方案设计</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247493903&idx=1&sn=01732a16ca4580edeef252ef2c37ed0b&chksm=cf00abedf87722fb991b79e835d27ea7c4013a21a2e5fb74f715bb55a298d8261240d996ea16&token=1495229386&lang=zh_CN&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">31岁,还可以拼一拼大厂么?</a> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <a href="https://mp.weixin.qq.com/s?__biz=Mzg3OTU5NzQ1Mw==&mid=2247493608&idx=1&sn=1006a75cdbe4f0537de1fe48c4111381&chksm=cf00a50af8772c1c4c1308df1f595347ccb1ed03244b5314d78c98748e079183304dfffe7ace&scene=21#wechat_redirect" style="font-weight: bold;color: rgb(239, 112, 96);border-bottom: 1px solid rgb(239, 112, 96);" data-linktype="2">4 个维度搞懂 Nacos 注册中心</a> </section></li> </ul> </section> </section> <p style="display: none;margin-bottom: 24px;"> <mp-style-type data-value="3"></mp-style-type></p>