文章列表

k8s-服务网格实战-配置 Mesh(灰度发布)

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <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.4255555555555556" src="/upload/ed64cf7709d5f76e6ec0862e3473bc87.png" data-type="png" data-w="900" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> istio-02.png </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在上一篇 <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIyMzgyODkxMQ==&amp;mid=2247486477&amp;idx=1&amp;sn=1483687ccbc17887969df5ad3d2a364e&amp;chksm=e81902cddf6e8bdba9f501fc94fe2372f5da5cfe5b63d1fcb1fd16da87ce8f4096626015f972&amp;scene=21#wechat_redirect" textvalue="k8s-服务网‍格实战-入门Istio" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">k8s-服务网格实战-入门Istio</a>中分享了如何安装部署 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Istio</code>,同时可以利用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Istio</code> 实现 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">gRPC</code> 的负载均衡。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">今天我们更进一步,深入了解使用 Istio 的功能。<img class="rich_pages wxw-img" data-ratio="0.7527624309392266" src="/upload/d0f15a9914b333e0b1367aeb98114360.png" data-type="png" data-w="724" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;">从 Istio 的流量模型中可以看出:Istio 支持管理集群的出入口请求(gateway),同时也支持管理集群内的 mesh 流量,也就是集群内服务之间的请求。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">本次先讲解集群内部的请求,配合实现以下两个功能:</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);"> 灰度发布(对指定的请求分别路由到不同的 service 中) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 配置 service 的请求权重 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>灰度发布</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在开始之前会部署两个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">deployment</code> 和一个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service</code>,同时这两个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">deployment</code> 所关联的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Pod</code> 分别对应了两个不同的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">label</code>,由于在灰度的时候进行分组。<img class="rich_pages wxw-img" data-ratio="0.7447698744769874" src="/upload/f186501145bec6f041130c1b020c233f.png" data-type="png" data-w="478" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">使用这个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">yaml</code> 会部署所需要的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">deployment</code> 和 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.14437948823614244&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">kubectl&nbsp;apply&nbsp;-f&nbsp;https://raw.githubusercontent.com/crossoverJie/k8s-combat/main/deployment/istio-mesh.yaml&nbsp;<br></code></pre> <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;">首先设想下什么情况下我们需要灰度发布,一般是某个重大功能的测试,只对部分进入内测的用户开放入口。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">假设我们做的是一个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">App</code>,我们可以对拿到了内测包用户的所有请求头中加入一个版本号。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">比如 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">version=200</code> 表示新版本,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">version=100</code> 表示老版本。同时在服务端会将这个版本号打印出来,用于区分请求是否进入了预期的 Pod。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.28507124242920123&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;">//&nbsp;Client&nbsp;</span><br>version&nbsp;:=&nbsp;r.URL.Query().Get(<span style="color: #98c379;line-height: 26px;">"version"</span>)&nbsp;&nbsp;<br>name&nbsp;:=&nbsp;<span style="color: #98c379;line-height: 26px;">"world"</span>&nbsp;&nbsp;<br>ctx,&nbsp;cancel&nbsp;:=&nbsp;context.WithTimeout(context.Background(),&nbsp;time.Second)&nbsp;&nbsp;<br>md&nbsp;:=&nbsp;metadata.New(<span style="color: #c678dd;line-height: 26px;">map</span>[<span style="color: #c678dd;line-height: 26px;">string</span>]<span style="color: #c678dd;line-height: 26px;">string</span>{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">"version"</span>:&nbsp;version,&nbsp;&nbsp;<br>})&nbsp;&nbsp;<br>ctx&nbsp;=&nbsp;metadata.NewOutgoingContext(ctx,&nbsp;md)&nbsp;&nbsp;<br><span style="color: #c678dd;line-height: 26px;">defer</span>&nbsp;cancel()&nbsp;&nbsp;<br>g,&nbsp;err&nbsp;:=&nbsp;c.SayHello(ctx,&nbsp;&amp;pb.HelloRequest{Name:&nbsp;name})<br><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">//&nbsp;Server</span><br><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">func</span>&nbsp;<span style="line-height: 26px;">(s&nbsp;*server)</span>&nbsp;<span style="color: #61aeee;line-height: 26px;">SayHello</span><span style="line-height: 26px;">(ctx&nbsp;context.Context,&nbsp;in&nbsp;*pb.HelloRequest)</span>&nbsp;<span style="line-height: 26px;">(*pb.HelloReply,&nbsp;error)</span></span>&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;md,&nbsp;ok&nbsp;:=&nbsp;metadata.FromIncomingContext(ctx)&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">var</span>&nbsp;version&nbsp;<span style="color: #c678dd;line-height: 26px;">string</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">if</span>&nbsp;ok&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version&nbsp;=&nbsp;md.Get(<span style="color: #98c379;line-height: 26px;">"version"</span>)[<span style="color: #d19a66;line-height: 26px;">0</span>]&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;log.Printf(<span style="color: #98c379;line-height: 26px;">"Received:&nbsp;%v,&nbsp;version:&nbsp;%s"</span>,&nbsp;in.GetName(),&nbsp;version)&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;name,&nbsp;_&nbsp;:=&nbsp;os.Hostname()&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">return</span>&nbsp;&amp;pb.HelloReply{Message:&nbsp;fmt.Sprintf(<span style="color: #98c379;line-height: 26px;">"hostname:%s,&nbsp;in:%s,&nbsp;version:%s"</span>,&nbsp;name,&nbsp;in.Name,&nbsp;version)},&nbsp;<span style="color: #56b6c2;line-height: 26px;">nil</span>&nbsp;&nbsp;<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>对 service 分组<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">进行灰度测试时往往需要新增部署一个灰度服务,这里我们称为 v2(也就是上图中的 Pod2)。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">同时需要将 v1 和 v2 分组:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.23178283467547556&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">apiVersion:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">networking.istio.io/v1alpha3</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">kind:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">DestinationRule</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">metadata:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-ds</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">spec:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subsets:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">labels:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">app:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-v1</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v2</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">labels:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">app:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-v2</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里我们使用 Istio 的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">DestinationRule</code> 定义 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">subset</code>,也就是将我们的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service</code> 下的 Pod 分为 v1/v2。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">使用 标签 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">app</code> 进行分组</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">注意这里的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">host: k8s-combat-service-istio-mesh</code> 通常配置的是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.9967320619718949&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">apiVersion:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">kind:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">Service</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">metadata:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">spec:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">selector:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">appId:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">"12345"</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">type:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">ClusterIP</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">ports:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">port:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">8081</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">targetPort:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">8081</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">app</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">grpc</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">port:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">50051</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">targetPort:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">50051</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">也就是这里 service 的名称,同时也支持配置为 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">host: k8s-combat-service-istio-mesh.default.svc.cluster.local</code>,如果使用的简写<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Istio</code> 会根据当前指定的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">namespace</code> 进行解析。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">Istio 更推荐使用全限定名替代我们这里的简写,从而避免误操作。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当然我们也可以在 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">DestinationRule</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.24608480674351263&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">apiVersion:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">networking.istio.io/v1alpha3</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">kind:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">DestinationRule</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">metadata:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-ds</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">spec:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">trafficPolicy:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">loadBalancer:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">simple:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">ROUND_ROBIN</span>&nbsp;&nbsp;<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 class="rich_pages wxw-img" data-ratio="0.24067796610169492" src="/upload/afb1cfa96e033adf1bc846b0948b60ee.png" data-type="png" data-w="885" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> image.png </figcaption> </figure> <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;">这样我们就定义好了两个分组:</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);"> v1:app: k8s-combat-service-v1 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> v2:app: k8s-combat-service-v2 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">之后就可以配置路由规则将流量分别指定到两个不同的组中,这里我们使用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">VirtualService</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.5207345538672017&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">apiVersion:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">networking.istio.io/v1alpha3</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">kind:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">VirtualService</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">metadata:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-vs</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">spec:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">gateways:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #98c379;line-height: 26px;">mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">hosts:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;match&nbsp;this&nbsp;host</span><br><span style="color: #d19a66;line-height: 26px;">http:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">match:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">headers:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">version:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">exact:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'100'</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">route:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">destination:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subset:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v2</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">match:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">headers:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">version:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">exact:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'200'</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">route:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">destination:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subset:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v2</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">default</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">route:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">destination:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subset:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这个规则很简单,会检测 http 协议的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">header</code> 中的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">version</code> 字段值,如果为 100 这路由到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">subset=v1</code> 这个分组的 Pod 中,同理为 200 时则路由到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">subset=v2</code> 这个分组的 Pod 中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当没有匹配到 header 时则进入默认的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">subset:v1</code></p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">gRPC</code> 也是基于 http 协议,它的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">metadata</code> 也就对应了 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">http</code> 协议中的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">header</code>。</p> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>header=100<span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.8624931468288237&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">Greeting:&nbsp;hostname:k8s-combat-service-v1-5b998dc8c8-hkb72,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=100"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v1-5b998dc8c8-hkb72,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=100"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v1-5b998dc8c8-hkb72,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=100"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v1-5b998dc8c8-hkb72,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=100"</span><br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>header=200<span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.8929483579029969&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">根据以上的上面的测试请求来看,只要我们请求头里带上指定的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">version</code> 就会被路由到指定的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Pod</code> 中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">利用这个特性我们就可以在灰度验证的时候单独发一个灰度版本的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Deployment</code>,同时配合客户端指定版本就可以实现灰度功能了。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>配置权重</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">同样基于 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">VirtualService</code> 我们还可以对不同的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">subset</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.8932949141508217&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">apiVersion:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">networking.istio.io/v1alpha3</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">kind:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">VirtualService</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">metadata:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-vs</span>&nbsp;&nbsp;<br><span style="color: #d19a66;line-height: 26px;">spec:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">gateways:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #98c379;line-height: 26px;">mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">hosts:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;match&nbsp;this&nbsp;host&nbsp;&nbsp;</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">http:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">match:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">uri:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">exact:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">/helloworld.Greeter/SayHello</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">route:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">destination:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subset:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v1</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">weight:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">10</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">-</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">destination:</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">host:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">k8s-combat-service-istio-mesh</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">subset:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">v2</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">weight:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">90</span>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">timeout:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">5000ms</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里演示的是针对 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">SayHello</code> 接口进行权重配置(当然还有多种匹配规则),90% 的流量会进入 v2 这个 subset,也就是在 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">k8s-combat-service-istio-mesh</code> service 下的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">app: k8s-combat-service-v2</code> Pod。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/IJdPq631CVGbnku2DTfwNWvf8HiaJKGu99OHC9iciahHv4mBF4EuaaXqRHUIZjDQaITc4ZxTAoUQjMeO6mFCsPJ1QYCCQVib1hSr/640?wx_fmt=svg&amp;random=0.47102790728230604&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-**v1**-5b998dc8c8-hkb72,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$&nbsp;curl&nbsp;<span style="color: #98c379;line-height: 26px;">"http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&amp;version=200"</span><br>Greeting:&nbsp;hostname:k8s-combat-service-v2-5db566fb76-xj7j6,&nbsp;<span style="color: #c678dd;line-height: 26px;">in</span>:world,&nbsp;version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">经过测试会发现大部分的请求都会按照我们的预期进入 v2 这个分组。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当然除之外之外我们还可以:</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);"> 超时时间 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 故障注入 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 重试 具体的配置可以参考 Istio 官方文档: <img class="rich_pages wxw-img" data-ratio="0.9446952595936795" src="/upload/6cfb0127cb5304839024eb3a42cd87aa.png" data-type="png" data-w="886" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;">当然在一些云平台也提供了可视化的页面,可以更直观的使用。 <img class="rich_pages wxw-img" data-ratio="1.4907407407407407" src="/upload/3a36bb6189a1eaff3fb911096be68ba8.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"> </section></li> </ul> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">以上是 阿里云的截图</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">但他们的管理的资源都偏 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">kubernetes</code>,一般是由运维或者是 DevOps 来配置,不方便开发使用,所以还需要一个介于云厂商和开发者之间的管理发布平台,可以由开发者以项目维度管理维护这些功能。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">本文的所有源码在这里可以访问:https://github.com/crossoverJie/k8s-combat</p> </section>

听说你会架构设计?来,弄一个公交&地铁乘车系统

作者:微信小助手

<h1 cid="n0" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.7em;margin-right: auto;margin-left: auto;font-weight: bold;line-height: 1.2;cursor: text;text-align: left;color: rgb(89, 0, 9);white-space: pre-wrap;font-family: Vollkorn, Palatino, Times;letter-spacing: normal;" data-mpa-powered-by="yiban.io"><span style="color: rgb(0, 0, 0);font-family: Optima-Regular, PingFangTC-light;font-size: 17px;">大家好呀,我是楼仔。<br></span></h1> <h1 cid="n0" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.7em;margin-right: auto;margin-left: auto;font-weight: bold;line-height: 1.2;cursor: text;text-align: left;color: rgb(89, 0, 9);white-space: pre-wrap;font-family: Vollkorn, Palatino, Times;letter-spacing: normal;"><span style="font-size: 17px;color: rgb(0, 0, 0);font-family: Optima-Regular, PingFangTC-light;">今天教大家设计一个公交&amp;地铁乘车系统。</span><span style="font-size: 17px;color: rgb(0, 0, 0);font-family: Optima-Regular, PingFangTC-light;"></span><br><br></h1> <h1 cid="n0" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.7em;margin-right: auto;margin-left: auto;font-weight: bold;line-height: 1.2;cursor: text;text-align: center;color: rgb(89, 0, 9);white-space: pre-wrap;font-family: Vollkorn, Palatino, Times;letter-spacing: normal;">1. 引言</h1> <h2 cid="n2" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.5em;margin: 1em auto 1.4em;font-weight: bold;line-height: 1.4;cursor: text;border-bottom: 1px solid rgb(255, 127, 0);white-space: pre-wrap;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">1.1 上班通勤的日常</h2> <p cid="n3" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">“叮铃铃”,“叮铃铃”,早上七八点,你还在温暖的被窝里和闹钟“斗智斗勇”。</p> <p style="text-align: center;margin-bottom: 24px;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="1.1126760563380282" data-s="300,640" src="/upload/2a5ea9ce2ab28fcbcd68dd581af8da59.jpg" data-type="jpeg" data-w="213" style=""></p> <p cid="n4" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">突然,你意识到已经快迟到了,于是像个闪电侠一样冲进卫生间,速洗漱,急穿衣,左手抄起手机,右手拿起面包,边穿衣边啃早餐。</p> <p cid="n5" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">这个时候,通勤的老难题又摆在了你面前:要不要吃完这口面包、刷牙和洗脸,还是先冲出门赶车?</p> <p cid="n6" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">好不容易做出了一个艰难的决定——放下面包,快步冲出门。你拿出手机,点开了熟悉的地铁乘车 App 或公交地铁乘车码小程序。</p> <p cid="n7" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;"><strong style="padding: 0.1em;color: rgb(220, 53, 69);">然后,一张二维码在屏幕上亮了起来,这可是你每天通勤的“敲门砖”。</strong></p> <p style="text-align: center;margin-bottom: 24px;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.5671140939597316" data-s="300,640" src="/upload/77d47137c743aa672286df295ba2af7f.jpg" data-type="jpeg" data-w="298" style=""></p> <p cid="n7" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;"><br></p> <p cid="n8" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">你快步走到地铁站,将手机二维码扫描在闸机上,"嗖"的一声,闸机打开,你轻松通过,不再需要排队买票,不再被早高峰的拥挤闹心。</p> <p cid="n8" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">你走进地铁车厢,挤到了一个角落,拿出手机,开始计划一天的工作。</p> <p cid="n9" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;"><br></p> <h2 cid="n10" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.5em;margin: 1em auto 1.4em;font-weight: bold;line-height: 1.4;cursor: text;border-bottom: 1px solid rgb(255, 127, 0);white-space: pre-wrap;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">1.2 公交&amp;地铁乘车系统</h2> <p cid="n11" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">正如上文所说,人们只需要一台手机,一个二维码就可以完成上班通勤的所有事项。</p> <p cid="n12" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">那这个便捷的公交或地铁乘车系统是如何设计的呢?它背后的技术和架构是怎样支撑着你我每天的通勤生活呢?</p> <p cid="n13" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">今天让我们一起揭开这个现代<strong style="padding: 0.1em;color: rgb(220, 53, 69);">都市打工人通勤小能手</strong>的面纱,深入探讨<strong style="padding: 0.1em;color: rgb(220, 53, 69);">乘车系统的设计与实现</strong>。</p> <p cid="n14" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;">在这个文章中,楼仔将带你走进乘车系统的世界,一探究竟,看看它是如何在短短几年内从科幻电影中走出来,成为我们日常生活不可或缺的一部分。</p> <p cid="n15" mdtype="paragraph" style="line-height: 1.8rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;color: rgb(0, 0, 0);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;text-align: start;"><br></p> <h1 cid="n16" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;orphans: 4;font-size: 1.7em;margin-right: auto;margin-left: auto;font-weight: bold;line-height: 1.2;cursor: text;text-align: center;color: rgb(89, 0, 9);white-space: pre-wrap;font-family: Vollkorn, Palatino, Times;letter-spacing: normal;">2. 需求设计</h1> <h2 cid="n17" mdtype="he

组件更少,性能更高:Apache Doris 取代 ClickHouse、MySQL、Presto 和 HBase

作者:微信小助手

<p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;visibility: visible;">这篇文章是关于构建统一的 OLAP 平台。一家保险公司试图构建一个数据仓库,可以承担所有面向客户、分析师和管理层的数据分析工作负载。主要任务包括:</span></p> <ul class="list-paddingleft-1" style="list-style-type: disc;visibility: visible;"> <li style="visibility: visible;"><p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;font-weight: 700;visibility: visible;">保险合同自助查询</span><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;vertical-align: inherit;visibility: visible;">:保险客户通过合同 ID 查询明细。并且支持保险期限、保险类型和索赔金额等过滤器。</span></p></li> <li style="visibility: visible;"><p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;font-weight: 700;visibility: visible;">多维度分析</span><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;vertical-align: inherit;visibility: visible;">:分析师需要根据不同的数据维度开发报告,从而提取洞察以促进产品创新和反欺诈工作。</span></p></li> <li style="visibility: visible;"><p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;font-weight: 700;visibility: visible;">仪表板</span><span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;vertical-align: inherit;visibility: visible;">:为了创建保险销售趋势的可视化概述以及不同指标的水平和垂直比较。</span></p></li> </ul> <h1 data-selectable-paragraph="" style="box-sizing: inherit;font-family: sohne, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;color: rgb(36, 36, 36);line-height: 30px;letter-spacing: -0.016em;font-weight: 600;font-size: 24px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;visibility: visible;"><span style="font-size: 18px;visibility: visible;"><strong style="visibility: visible;"><span style="box-sizing: inherit;vertical-align: inherit;visibility: visible;">组件密集型数据架构</span></strong></span><span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;visibility: visible;"></span></h1> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;visibility: visible;">用户从 Lambda 架构入手,将数据管道拆分为批处理链路和流处理链路。对于实时数据流,他们应用 Flink CDC ;对于批量导入,他们结合了 Sqoop、Python 和 DataX 来构建自己的数据集成工具,名为 Hisen。</span></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"><span style="color: rgba(0, 0, 0, 0.8);font-family: medium-content-sans-serif-font, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif;font-size: medium;letter-spacing: normal;visibility: visible;"></span><img class="rich_pages wxw-img" data-ratio="0.5" src="/upload/2619bb28bdc4aa1d535ce403e2929465.png" data-type="png" data-w="1050" height="350" style="color: rgba(0, 0, 0, 0.8);font-family: medium-content-sans-serif-font, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif;font-size: medium;letter-spacing: normal;box-sizing: inherit;vertical-align: middle;visibility: visible !important;width: 677px !important;height: auto !important;" width="700"></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;visibility: visible;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;visibility: visible;">然后,实时数据和离线数据在数据仓库层会合,该层由五个组件组成。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;"><span style="color: rgb(36, 36, 36);font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 16px;letter-spacing: -0.06px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);">ClickHouse</span></span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">数据仓库采用扁平表设计,ClickHouse 在扁平表读取方面表现出色。但随着业务的发展,面临两个方面的挑战:</span> </section> <p><br></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="font-size: 16px;letter-spacing: -0.003em;">为了支持跨表连接和点查询,用户需要星型模式,这在 ClickHouse 中很难实现。</span> </section></li> <li> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="font-size: 16px;letter-spacing: -0.003em;">保险合同的变更需要在数据仓库中实时更新。</span> <span style="font-size: 16px;letter-spacing: -0.003em;">在 ClickHouse 中,通过重新创建一个平面表来覆盖旧表来完成,但速度不够快。</span> </section></li> </ul> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;">MySQL</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">计算完成后,数据指标存储在 MySQL 中。随着数据规模的增长,MySQL 开始陷入困境,出现执行时间延长、抛出错误等问题。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="font-size: 16px;box-sizing: inherit;font-weight: 700;">Apache&nbsp;Hive&nbsp;+ Presto</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Hive是批处理环节中的主要执行者。可以转换、聚合、查询离线数据。Presto 是 Hive 的补充,用于交互式分析。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;">Apache HBase</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">HBase 承担主键查询。它从 MySQL 和 Hive 读取客户状态,包括客户信用、承保期限和保险金额。由于 HBase 本身不支持二级索引,因此读取非主键列的能力有限,但可以通过开源Phoenix组件或“通过hbase协处理器把二级索引自动同步至elasticsearch”来实现二级索引的功能。另外,作为 NoSQL 数据库,HBase 不支持 SQL 语句,对SQL语句的支持可以通过开源Phoenix组件或“HBase SDK 3.0.0发布,让HBase的使用变得更简捷”:https://github.com/CCweixiao/hbase-sdk或https://gitee.com/weixiaotome/hbase-sdk。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">这些组件必须协同工作才能满足所有需求,使得数据仓库变得难以处理,不容易上手。因为工程师必须接受所有这些组件的培训。此外,架构的复杂性也增加了延迟的风险。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">因此,用户试图寻找一种能够满足更多要求的工具。他们首先需要的是实时能力,包括实时写入、实时更新、实时响应数据查询。其次,需要在数据分析方面更加灵活,以支持面向客户的自助查询,如多维分析、大表连接查询、主键索引、上滚和下钻等。然后,对于批处理,还希望数据写入具有高吞吐量。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">用户最终决定选择&nbsp;</span> <span style="font-size: 16px;">Apache Doris</span> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">。</span> </section> <p><br></p> <h1 data-selectable-paragraph="" style="box-sizing: inherit;font-family: sohne, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;color: rgb(36, 36, 36);line-height: 30px;letter-spacing: -0.016em;font-weight: 600;font-size: 24px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="font-size: 18px;"><strong><span style="font-size: 18px;box-sizing: inherit;vertical-align: inherit;">用 Apache Doris 替换四个组件</span></strong></span></h1> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Apache Doris 能够进行实时和离线数据分析,同时支持高吞吐量的交互式分析和高并发的点查询。这就是为什么它可以取代 ClickHouse、MySQL、Presto 和 Apache HBase,作为整个数据系统的统一查询网关。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <img class="rich_pages wxw-img" data-ratio="0.5361904761904762" data-type="png" data-w="1050" height="376" src="/upload/25d40b5cdff7e917dce1fa4aa0cd3a86.png" style="color: rgba(0, 0, 0, 0.8);font-family: medium-content-sans-serif-font, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif;font-size: medium;letter-spacing: normal;box-sizing: inherit;vertical-align: middle;width: 677px !important;height: auto !important;visibility: visible !important;" width="700"> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">改进后的数据管道是一个更加干净的 Lambda 架构。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Apache Doris 提供了多种数据摄取方法。数据写入速度很快。除此之外,它还实现了 Merge-on-Write 以提高并发点查询的性能。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;">降低成本</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">新的架构降低了用户的人力成本。一方面,更简单的数据架构使得维护更容易;另一方面,开发者不再需要在数据服务 API 中加入实时和离线数据。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">用户还可以使用 Doris 省钱,因为它支持分层存储。它允许用户将大量很少访问的历史数据放入对象存储中,这样囤积数据的成本要低得多。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;">更高效率</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Apache Doris 的 QPS 可以达到万级,毫秒级响应数十亿点查询,面对客户的查询也能轻松应对。将热数据与冷数据分开的分层存储也提高了查询效率。</span> </section> <p><br></p> <p style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="box-sizing: inherit;font-weight: 700;font-size: 16px;">服务可用性</span></p> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">作为存储、计算和数据服务的统一数据仓库,Apache Doris 可以轻松实现灾难恢复。由于组件较少,他们不必担心数据丢失或重复。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Apache Doris 的跨集群复制(CCR)能力是用户服务可用性的重要保障。可以在几分钟甚至几秒钟内实现集群之间的数据同步,并且实现了两种机制来保证数据的可靠性:</span> </section> <p><br></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;font-weight: 700;">Binlog</span> <span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;vertical-align: inherit;">:该机制可以自动记录数据的变化,并为每个数据修改操作生成一个LogID。增量 LogID 确保数据更改可追溯且有序。</span> </section></li> <li> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;font-weight: 700;">数据持久化</span> <span style="font-size: 16px;letter-spacing: -0.003em;box-sizing: inherit;vertical-align: inherit;">:在系统崩溃或紧急情况下,数据将被存入磁盘。</span> </section></li> </ul> <h1 data-selectable-paragraph="" style="box-sizing: inherit;font-family: sohne, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;color: rgb(36, 36, 36);line-height: 30px;letter-spacing: -0.016em;font-weight: 600;font-size: 24px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-bottom: 8px;margin-top: 24px;"><span style="font-size: 18px;"><strong><span style="font-size: 18px;box-sizing: inherit;vertical-align: inherit;">深入了解 Apache Doris</span></strong></span></h1> <p><br></p> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">Apache Doris 可以取代 ClickHouse、MySQL、Presto 和 HBase,因为它在数据处理管道上拥有全面的功能集合。在数据摄取方面,基于对 Flink CDC 和 Merge-on-Write 的支持,实现了低延迟实时写入。通过其标签机制和事务加载来保证 Exactly-Once 写入。在数据查询方面,它同时支持星型模式和平面表聚合,因此在麻烦的多表连接和大型单表查询中都可以提供高性能。它还提供了多种方法来加速不同的查询,例如用于全文搜索和范围查询的</span> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">倒排索引、用于点查询的短路计划和预备语句。</span> </section> <section style="box-sizing: inherit;color: rgb(36, 36, 36);word-break: break-word;line-height: 32px;letter-spacing: -0.003em;font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 20px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);margin-top: 0px;margin-bottom: 8px;"> <span style="box-sizing: inherit;vertical-align: inherit;font-size: 16px;">原文作者:<span style="color: rgb(36, 36, 36);font-family: source-serif-pro, Georgia, Cambria, &quot;Times New Roman&quot;, Times, serif;font-size: 16px;letter-spacing: -0.06px;text-align: start;text-wrap: wrap;background-color: rgb(255, 255, 255);">Apache Doris</span><br></span> </section> <p><br></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

优雅而强大:用easy-es简化ElasticSearch操作

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding: 0 10px;line-height: 1.6;word-spacing: 0px;letter-spacing: 0px;word-break: break-word;word-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;"> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;display: block;font-size: 0.9em;overflow: auto;border-left: 3px solid rgb(239, 112, 96);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;background: rgb(255, 249, 249);"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0px;color: black;line-height: 26px;">使用过Spring Data操作ES的小伙伴应该有所了解,它只能实现一些非常基本的数据管理工作,一旦遇到稍微复杂点的查询,基本都要依赖ES官方提供的RestHighLevelClient,Spring Data只是在其基础上进行了简单的封装。最近发现一款更优雅的ES ORM框架Easy-Es,使用它能像MyBatis-Plus一样操作ES,今天就以一个实际的mall商城项目中的商品搜索功能为例,来聊聊它的使用!</p> </blockquote> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;font-weight: bold;background: rgb(239, 112, 96);color: #ffffff;padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">Easy-Es简介</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="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">Easy-Es(简称EE)是基于Elasticsearch(简称ES)官方提供的RestHighLevelClient开发的ORM框架,旨在简化开发流程并提高效率。EE在保持RestHighLevelClient原有功能的基础上进行增强,而不做任何改变。与Mybatis-Plus(简称MP)相比,EE的用法非常相似,如果您之前使用过MP,应该能够很快上手EE。EE的设计理念是:将简单、易用和方便留给用户,而将复杂的任务交由框架来处理。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">EE的主要特性如下:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li style="box-sizing: inherit;"><p>全自动索引管理:开发者无需繁琐地处理索引的创建、更新和数据迁移等步骤,框架会自动完成这些任务。</p></li> <li style="box-sizing: inherit;margin-top: 0.25em;"><p>屏蔽语言差异:开发者只需要熟悉MySQL语法,就能够轻松地使用ES进行开发。</p></li> <li style="box-sizing: inherit;margin-top: 0.25em;"><p>更少的代码量:相比直接使用官方提供的RestHighLevelClient,使用EE平均可以节省3-5倍的代码量来进行相同的查询操作。</p></li> <li><p>零魔法值:字段名称会直接从实体中获取,无需手动编写。</p></li> <li><p><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;letter-spacing: 0px;text-align: left;text-wrap: wrap;color: black;">无额外学习成本:</span><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;letter-spacing: 0px;text-align: left;text-wrap: wrap;color: black;">如果开发者已经熟悉国内最受欢迎的Mybatis-Plus的用法,那么可以无缝迁移至EE,无需额外学习成本。</span><br></p></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;font-weight: bold;background: rgb(239, 112, 96);color: #ffffff;padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">MySQL与Easy-Es语法对比</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: 0;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.9738625363020329" src="/upload/d1f76d02657c1e57789e155db5c6e155.png" data-type="png" data-w="1033" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <figure data-tool="mdnice编辑器" style="margin: 0;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.8468992248062015" src="/upload/61670a776eb10deda4cb50297bdab206.png" data-type="png" data-w="1032" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <figure data-tool="mdnice编辑器" style="margin: 0;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.4530493707647628" src="/upload/11c72e7193412e70aa2e0f158dab88c3.png" data-type="png" data-w="1033" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;font-weight: bold;background: rgb(239, 112, 96);color: #ffffff;padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">集成及配置</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 首先需要在pom.xml中添加Easy-Es的相关依赖; </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">&lt;dependencyManagement&gt;<br> &lt;dependencies&gt;<br> &lt;dependency&gt;<br> &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt;<br> &lt;artifactId&gt;elasticsearch-rest-high-level-client&lt;/artifactId&gt;<br> &lt;version&gt;7.14.0&lt;/version&gt;<br> &lt;/dependency&gt;<br> &lt;dependency&gt;<br> &lt;groupId&gt;org.elasticsearch&lt;/groupId&gt;<br> &lt;artifactId&gt;elasticsearch&lt;/artifactId&gt;<br> &lt;version&gt;7.14.0&lt;/version&gt;<br> &lt;/dependency&gt;<br> &lt;/dependencies&gt;<br>&lt;/dependencyManagement&gt;<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 再修改配置文件application.yml对Easy-Es进行配置。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">easy-es:<br> # 是否开启EE自动配置<br> enable: true<br> # ES连接地址+端口<br> address: localhost:9200<br> # 关闭自带banner<br> banner: false<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 添加Easy-Es的Java配置,使用@EsMapperScan配置好Easy-Es的Mapper接口和文档对象路径,如果你使用了MyBatis-Plus的话,需要和它的扫描路径区分开来。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * EasyEs配置类<br> * Created by macro on 2022/9/16.<br> */<br>@Configuration<br>@EsMapperScan("com.macro.mall.tiny.easyes")<br>public class EasyEsConfig {<br>}<br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;font-weight: bold;background: rgb(239, 112, 96);color: #ffffff;padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">使用</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span>注解的使用<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 首先我们需要创建文档对象EsProduct,然后给类和字段添加上Easy-Es的注解; </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品的信息<br> * Created by macro on 2018/6/19.<br> */<br>@Data<br>@EqualsAndHashCode<br>@IndexName(value = "pms", shardsNum = 1, replicasNum = 0)<br>public class EsProduct implements Serializable {<br> private static final long serialVersionUID = -1L;<br> @IndexId(type = IdType.CUSTOMIZE)<br> private Long id;<br> @IndexField(fieldType = FieldType.KEYWORD)<br> private String productSn;<br> private Long brandId;<br> @IndexField(fieldType = FieldType.KEYWORD)<br> private String brandName;<br> private Long productCategoryId;<br> @IndexField(fieldType = FieldType.KEYWORD)<br> private String productCategoryName;<br> private String pic;<br> @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")<br> private String name;<br> @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")<br> private String subTitle;<br> @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")<br> private String keywords;<br> private BigDecimal price;<br> private Integer sale;<br> private Integer newStatus;<br> private Integer recommandStatus;<br> private Integer stock;<br> private Integer promotionType;<br> private Integer sort;<br> @IndexField(fieldType = FieldType.NESTED, nestedClass = EsProductAttributeValue.class)<br> private List&lt;EsProductAttributeValue&gt; attrValueList;<br> @Score<br> private Float score;<br>}<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> EsProduct中的注解具体说明如下: </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin: 0;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.4951737451737452" src="/upload/fb7da5f597580182f4661fc81c938e93.png" data-type="png" data-w="1036" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> EsProduct中嵌套类型EsProductAttributeValue的代码如下。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品的属性信息<br> * Created by macro on 2018/6/27.<br> */<br>@Data<br>@EqualsAndHashCode<br>public class EsProductAttributeValue implements Serializable {<br> private static final long serialVersionUID = 1L;<br> @IndexField(fieldType = FieldType.LONG)<br> private Long id;<br> @IndexField(fieldType = FieldType.KEYWORD)<br> private Long productAttributeId;<br> //属性值<br> @IndexField(fieldType = FieldType.KEYWORD)<br> private String value;<br> //属性参数:0-&gt;规格;1-&gt;参数<br> @IndexField(fieldType = FieldType.INTEGER)<br> private Integer type;<br> //属性名称<br> @IndexField(fieldType=FieldType.KEYWORD)<br> private String name;<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span>商品信息维护<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">下面我们来实现几个简单的商品信息维护接口,包括商品信息的导入、创建和删除。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 首先我们需要定义一个Mapper,继承BaseEsMapper; </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 商品ES操作类<br> * Created by macro on 2018/6/19.<br> */<br>public interface EsProductMapper extends BaseEsMapper&lt;EsProduct&gt; {<br><br>}<br><br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 然后在Service实现类中直接使用EsProductMapper内置方法实现即可,是不是和MyBatis-Plus的用法一致? </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品管理Service实现类<br> * Created by macro on 2018/6/19.<br> */<br>@Service<br>public class EsProductServiceImpl implements EsProductService {<br> @Autowired<br> private EsProductDao productDao;<br> @Autowired<br> private EsProductMapper esProductMapper;<br> @Override<br> public int importAll() {<br> List&lt;EsProduct&gt; esProductList = productDao.getAllEsProductList(null);<br> return esProductMapper.insertBatch(esProductList);<br> }<br><br> @Override<br> public void delete(Long id) {<br> esProductMapper.deleteById(id);<br> }<br><br> @Override<br> public EsProduct create(Long id) {<br> EsProduct result = null;<br> List&lt;EsProduct&gt; esProductList = productDao.getAllEsProductList(id);<br> if (esProductList.size() &gt; 0) {<br> result = esProductList.get(0);<br> esProductMapper.insert(result);<br> }<br> return result;<br> }<br><br> @Override<br> public void delete(List&lt;Long&gt; ids) {<br> if (!CollectionUtils.isEmpty(ids)) {<br> esProductMapper.deleteBatchIds(ids);<br> }<br> }<br>}<br><br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span>简单商品搜索<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">下面我们来实现一个最简单的商品搜索,分页搜索商品名称、副标题、关键词中包含指定关键字的商品。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 通过QueryWrapper来构造查询条件,然后使用Mapper中的方法来进行查询,使用过MyBatis-Plus的小伙伴应该很熟悉了; </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品管理Service实现类<br> * Created by macro on 2018/6/19.<br> */<br>@Service<br>public class EsProductServiceImpl implements EsProductService {<br> @Autowired<br> private EsProductMapper esProductMapper;<br> @Override<br> public PageInfo&lt;EsProduct&gt; search(String keyword, Integer pageNum, Integer pageSize) {<br> LambdaEsQueryWrapper&lt;EsProduct&gt; wrapper = new LambdaEsQueryWrapper&lt;&gt;();<br> if(StrUtil.isEmpty(keyword)){<br> wrapper.matchAllQuery();<br> }else{<br> wrapper.multiMatchQuery(keyword,EsProduct::getName,EsProduct::getSubTitle,EsProduct::getKeywords);<br> }<br> return esProductMapper.pageQuery(wrapper, pageNum, pageSize);<br> }<br>}<br><br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 使用Swagger访问接口后,可以在控制台输出查看生成的DSL语句,访问地址:http://localhost:8080/swagger-ui/ </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin: 0;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.29411764705882354" src="/upload/2516ac6698f9db0059b72df2417282a9.png" data-type="png" data-w="1037" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 把DSL语句直接复制Kibana中即可执行查看结果了,这和我们手写DSL语句没什么两样的。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span>综合商品搜索<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">下面我们来实现一个复杂的商品搜索,涉及到过滤、不同字段匹配权重不同以及可以进行排序。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 首先来说需求,按输入的关键字搜索商品名称(权重10)、副标题(权重5)和关键词(权重2),可以按品牌和分类进行筛选,可以有5种排序方式,默认按相关度进行排序,看下接口文档有助于理解; </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin: 0;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.6972222222222222" src="/upload/15fc65ca4e47bc3e343ee7ca690dd5fb.png" data-type="png" data-w="1080" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 这个功能之前使用Spring Data来实现非常复杂,使用Easy-Es来实现确实简洁不少,下面是使用Easy-Es的实现方式; </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品管理Service实现类<br> * Created by macro on 2018/6/19.<br> */<br>@Service<br>public class EsProductServiceImpl implements EsProductService {<br> @Autowired<br> private EsProductMapper esProductMapper;<br> @Override<br> public PageInfo&lt;EsProduct&gt; search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort) {<br> LambdaEsQueryWrapper&lt;EsProduct&gt; wrapper = new LambdaEsQueryWrapper&lt;&gt;();<br> //过滤<br> if (brandId != null || productCategoryId != null) {<br> if (brandId != null) {<br> wrapper.eq(EsProduct::getBrandId,brandId);<br> }<br> if (productCategoryId != null) {<br> wrapper.eq(EsProduct::getProductCategoryId,productCategoryId).enableMust2Filter(true);<br> }<br> }<br> //搜索<br> if (StrUtil.isEmpty(keyword)) {<br> wrapper.matchAllQuery();<br> } else {<br> wrapper.and(i -&gt; i.match(EsProduct::getName, keyword, 10f)<br> .or().match(EsProduct::getSubTitle, keyword, 5f)<br> .or().match(EsProduct::getKeywords, keyword, 2f));<br> }<br> //排序<br> if(sort==1){<br> //按新品从新到旧<br> wrapper.orderByDesc(EsProduct::getId);<br> }else if(sort==2){<br> //按销量从高到低<br> wrapper.orderByDesc(EsProduct::getSale);<br> }else if(sort==3){<br> //按价格从低到高<br> wrapper.orderByAsc(EsProduct::getPrice);<br> }else if(sort==4){<br> //按价格从高到低<br> wrapper.orderByDesc(EsProduct::getPrice);<br> }else{<br> //按相关度<br> wrapper.sortByScore(SortOrder.DESC);<br> }<br> return esProductMapper.pageQuery(wrapper, pageNum, pageSize);<br> }<br>}<br><br></code></pre> <figure data-tool="mdnice编辑器" style="margin: 0;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.7416666666666667" src="/upload/e69e5513e190fc5a34176a61fef2c7bb.png" data-type="png" data-w="1080" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 再对比下之前使用Spring Data的实现方式,没有QueryWrapper来构造条件,还要硬编码字段名称,确实优雅了不少! </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin: 0;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.7416666666666667" src="/upload/e69e5513e190fc5a34176a61fef2c7bb.png" data-type="png" data-w="1080" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span>相关商品推荐<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">当我们查看相关商品的时候,一般底部会有一些商品推荐,这里简单来实现下。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 首先来说下需求,可以根据指定商品的ID来查找相关商品,看下接口文档有助于理解; </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin: 0;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.48055555555555557" src="/upload/564bb4c1177d4d89f03eb2bd7f367fa7.jpg" data-type="jpeg" data-w="1080" style="display: block;margin: 0 auto;max-width: 100%;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 这里我们的实现原理是这样的:首先根据ID获取指定商品信息,然后以指定商品的名称、品牌和分类来搜索商品,并且要过滤掉当前商品,调整搜索条件中的权重以获取最好的匹配度; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> 使用Easy-Es来实现依旧是那么简洁! </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/b2ONlmmVZRpkmpmxQicejPJB7PVtZ8gSqFkABnJ4jNobEgoVKKvKCt4z8FesNdnb0EWibYl0EmvgseibibOyOHcE337VNrOHrjuR/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * 搜索商品管理Service实现类<br> * Created by macro on 2018/6/19.<br> */<br>@Service<br>public class EsProductServiceImpl implements EsProductService {<br> @Autowired<br> private EsProductMapper esProductMapper;<br> @Override<br> public PageInfo&lt;EsProduct&gt; recommend(Long id, Integer pageNum, Integer pageSize) {<br> LambdaEsQueryWrapper&lt;EsProduct&gt; wrapper = new LambdaEsQueryWrapper&lt;&gt;();<br> List&lt;EsProduct&gt; esProductList = productDao.getAllEsProductList(id);<br> if (esProductList.size() &gt; 0) {<br> EsProduct esProduct = esProductList.get(0);<br> String keyword = esProduct.getName();<br> Long brandId = esProduct.getBrandId();<br> Long productCategoryId = esProduct.getProductCategoryId();<br> //用于过滤掉相同的商品<br> wrapper.ne(EsProduct::getId,id);<br> //根据商品标题、品牌、分类进行搜索<br> wrapper.and(i -&gt; i.match(EsProduct::getName, keyword, 8f)<br> .or().match(EsProduct::getSubTitle, keyword, 2f)<br> .or().match(EsProduct::getKeywords, keyword, 2f)<br> .or().match(EsProduct::getBrandId, brandId, 5f)<br> .or().match(EsProduct::getProductCategoryId, productCategoryId, 3f));<br> return esProductMapper.pageQuery(wrapper, pageNum, pageSize);<br> }<br> return esProductMapper.pageQuery(wrapper, pageNum, pageSize);<br> }<br>}<br><br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;font-weight: bold;background: rgb(239, 112, 96);color: #ffffff;padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">总结</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;">今天主要介绍了Easy-Es的一些常见的用法,确实使用Easy-Es更简单,但是对于复杂的聚合搜索功能,还是需要使用原生的RestHighLevelClient用法来实现。使用Easy-Es来操作ES确实足够优雅,它类似MyBatis-Plus的用法能大大降低我们的学习成本,快速完成开发工作!</p> </section> <p><br></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

Apache SkyWalking 轻松处理亿级流量的分布式系统监控工具

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <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;">背景介绍</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;">SkyWalking是一个开源的APM系统,包括分布式系统的监控、跟踪、诊断功能 在云原生架构中。</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);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">分布式跟踪</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">端到端分布式跟踪。服务拓扑分析、以服务为中心的可观测性和 API 仪表板。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">堆栈的代理</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">Java,.Net Core,PHP,NodeJS,Golang,LUA,Rust,C++,Client JavaScript和Python代理具有积极的开发和维护。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">eBPF早期采用</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">Rover 代理充当由 eBPF 提供支持的指标收集器和分析器,以诊断 CPU 和网络性能。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">缩放</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">可以从一个SkyWalking集群收集和分析100+十亿遥测数据。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">支持成熟的遥测生态系统</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">支持来自成熟生态系统的指标、跟踪和日志,例如 Zipkin、OpenTelemetry、Prometheus、Zabbix、Fluentd</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">原生 APM 数据库</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">BanyanDB 是一个可观测性数据库,创建于 2022 年,旨在摄取、分析和存储遥测/可观测性数据。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">一致的指标聚合</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">SkyWalking原生仪表格式和广为人知的度量格式(OpenTelemetry,Telegraf,Zabbix等)通过相同的脚本管道进行处理。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">日志管理管道</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">通过脚本流水线支持日志格式化、提取指标、各种采样策略,性能高。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">警报和遥测管道</p> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">支持以服务为中心、以部署为中心、以API为中心的告警规则设置。支持将告警和所有遥测数据转发给第三方。</p> </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.3333333333333333" src="/upload/480eb95c7b6d4b33df5208880882fa93.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;">原理</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;">SkyWalking整体分为4个部分:探针采集层、数据传输和逻辑处理层、数据存储层、数据展示层。</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.6111111111111112" src="/upload/9dc1a540efb36a1f3a8314f3da3fadcb.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.2、探针采集层<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所谓探针,实际上是一种动态代理技术,只不过不是我们常用的Java代理类,而是在类加载时,就生成了增强过的代理类的字节码,增强了数据拦截和采集上报的功能。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">探针技术是在项目启动时通过字节码技术(比如JavaAgent、ByteBuddy)进行类加载和替换,生成新的增强过的Class文件,对性能的影响是一次性的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">探针技术,因为在类加载时进行转换,增强了部分功能,所以会增加项目启动时间,同时也会增加内存占用量和线程数量。但是对性能影响不大,官方介绍在5% ~ 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 class="rich_pages wxw-img" data-ratio="0.11851851851851852" src="/upload/4899fc23e0a56a77cd0c9d6924ffc90e.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;">探针层在类转换时,通过各种插件对原有的类进行增强,之后在运行时拦截请求,然后将拦截的数据上报给Skywalking服务端。同时再加上一些定时任务,去采集应用服务器的基础数据,比如JVM信息等。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.3、数据传输和逻辑处理层<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">SkyWalking探针层使用了GRPC作为数据传输框架,将采集的数据上报到SkyWalking服务端。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">SkyWalking服务端接收数据后,利用各种插件来进行数据的分析和逻辑处理。比如:JVM相关插件,主要用于处理上报上来的JVM信息,数据库插件用来分析访问数据库的信息。然后在将数据存入到数据存储层。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.4、数据存储层<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">SkyWalking的数据存储层支持多种主流数据库,可以自行到配置文件里查阅。我推荐使用ElasticSearch,存储量大,搜索性能又好。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.5、数据展示层<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">SkyWalking 通过 Rocketbot 进行页面UI展示。可以在页面的左上角看到这个可爱的Rocketbot。</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;">实战总结</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>使用大盘<span style="display: none;"></span></h3> <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.49074074074074076" src="/upload/e974d28ebb87dbac1d005e6d3498fe62.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;">服务(Service):某个微服务,或者某个应用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">服务实例(Instance):某个微服务或者某个应用集群的一台实例或者一台负载。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">端点(Endpoint):某个Http请求的接口,或者 某个接口名+方法名。<img class="rich_pages wxw-img" data-ratio="0.48518518518518516" src="/upload/a961823d5bc61a7330e09380c804cf5b.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"></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.487962962962963" src="/upload/8067b6987dc15ab21415dfa9495799ec.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>全局拓扑结构<span style="display: none;"></span></h3> <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.49074074074074076" src="/upload/9827588261f947a9a29146a1e7a27067.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>链路详情<span style="display: none;"></span></h3> <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.4898148148148148" src="/upload/167112f643061055eaca26d55fbab497.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;">使用总结</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;">SkyWalking:APM(应用程序性能监视器)系统,专为 微服务、云原生和基于容器的架构。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">SkyWalking其实就4部分组成:探针采集上报 、 数据分析和逻辑处理、数据存储 、 数据展示 。安装使用简单、易上手。探针技术是SkyWalking的基石,说白了就是:在类加载时进行 字节码转换增强 ,然后去拦截请求,采集上报数据。UI页面的使用 ,多用用就熟悉了。</p> </section> <p><br></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

8000字+22张图探秘SpringCloud配置中心的核心原理

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;margin-bottom: 24px;" data-mpa-powered-by="yiban.io"> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzAwMTk4NjM1MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4gcBzLSUNh2cgXUsuLIsvQYJE1lzZd74qpC3iciaM6gcYIfOVV0KjDDkeN4CTLTn4ETPtaHOAuTWSWA/0?wx_fmt=png" data-nickname="JAVA日知录" data-alias="javadaily" data-signature="写代码的架构师,做架构的程序员! 实战、源码、数据库、架构...只要你来,你想了解的这里都有!" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这篇文章来扒一扒SpringCloud配置中心的核心原理。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">不知你是否跟我一样,在刚开始使用SpringCloud配置中心的时候也有很多的疑惑:</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);"> SpringCloud是什么时候去拉取配置中心的? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 配置中心客户端的配置信息为什么要写在bootstrap文件中? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 对象中注入的属性是如何动态刷新的? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 一些开源的配置中心是如何整合SpringCloud的? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ... </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">本文就通过探讨上述问题来探秘SpringCloud配置中心核心的底层原理。</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;">从SpringBoot的启动过程说起</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;">在SpringBoot启动的时候会经历一系列步骤,核心就是SpringApplication的run方法的逻辑</p> <figure d

一文带你掌握MyBatis-Plus的plus高级功能点如何使用

作者:微信小助手

<section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg5MDY1NzI0MQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/ibiaEekvAJHWiaznPJmfgtRI9SQT1b9gVYicxm1HpRoI7ib7zP4WIsFqax7sxP3hqOHDreujVdwHMbFaleygytUHX8g/0?wx_fmt=png" data-nickname="Shepherd进阶笔记" data-alias="shepherdZFJ" data-signature="专注分享Java技术进阶知识点,日常工作点点滴滴,滴水穿石" data-from="0" data-is_biz_ban="0"></mp-common-profile> </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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">今天接着之前总结的入门教程分析:<a href="https://mp.weixin.qq.com/s?__biz=Mzg5MDY1NzI0MQ==&amp;mid=2247486885&amp;idx=1&amp;sn=c3b8a0be2f670312a129885ae2da8d49&amp;chksm=cfd80d13f8af84055fdf9e708bfa2fb2e06defb7061ded3fef5e7d43b8c407ea86392e438bc2&amp;token=2027172068&amp;lang=zh_CN&amp;scene=21#wechat_redirect" style="color: rgb(30, 107, 184);font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);" data-linktype="2">MyBatis-Plus最详细的入门教程</a>,首先还是同样地需要准备一张表<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">tb_user</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">CREATE</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">TABLE</span>&nbsp;<span style="color: #98c379;line-height: 26px;">`tb_user`</span>&nbsp;(<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`id`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">bigint</span>(<span style="color: #d19a66;line-height: 26px;">20</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;AUTO_INCREMENT&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'主键'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`user_no`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">varchar</span>(<span style="color: #d19a66;line-height: 26px;">255</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'编号'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`nickname`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">varchar</span>(<span style="color: #d19a66;line-height: 26px;">255</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'昵称'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`email`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">varchar</span>(<span style="color: #d19a66;line-height: 26px;">255</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'邮箱'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`phone`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">varchar</span>(<span style="color: #d19a66;line-height: 26px;">255</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'手机号'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`gender`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">tinyint</span>(<span style="color: #d19a66;line-height: 26px;">4</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'0'</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'性别&nbsp;&nbsp;0:男生&nbsp;&nbsp;&nbsp;1:女生'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`birthday`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">timestamp</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">CURRENT_TIMESTAMP</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">ON</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">UPDATE</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">CURRENT_TIMESTAMP</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'出生日期'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`is_delete`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">tinyint</span>(<span style="color: #d19a66;line-height: 26px;">4</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">NOT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'0'</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'删除标志&nbsp;0:否&nbsp;&nbsp;1:是'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`create_time`</span>&nbsp;datetime&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'创建时间'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`update_time`</span>&nbsp;datetime&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'更新时间'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`create_by`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">bigint</span>(<span style="color: #d19a66;line-height: 26px;">20</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'创建人'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`update_by`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">bigint</span>(<span style="color: #d19a66;line-height: 26px;">20</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'更新人'</span>,<br>&nbsp;&nbsp;<span style="color: #98c379;line-height: 26px;">`address`</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">varchar</span>(<span style="color: #d19a66;line-height: 26px;">1024</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #56b6c2;line-height: 26px;">NULL</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #98c379;line-height: 26px;">'地址'</span>,<br>&nbsp;&nbsp;PRIMARY&nbsp;<span style="color: #c678dd;line-height: 26px;">KEY</span>&nbsp;(<span style="color: #98c379;line-height: 26px;">`id`</span>)&nbsp;<span style="color: #c678dd;line-height: 26px;">USING</span>&nbsp;BTREE<br>)&nbsp;<span style="color: #c678dd;line-height: 26px;">ENGINE</span>=<span style="color: #c678dd;line-height: 26px;">InnoDB</span>&nbsp;AUTO_INCREMENT=<span style="color: #d19a66;line-height: 26px;">1</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">CHARSET</span>=utf8mb4&nbsp;ROW_FORMAT=DYNAMIC;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在项目服务中对应的实体类<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">User</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #61aeee;line-height: 26px;">@Data</span><br><span style="color: #61aeee;line-height: 26px;">@Builder</span><br><span style="color: #61aeee;line-height: 26px;">@AllArgsConstructor</span><br><span style="color: #61aeee;line-height: 26px;">@NoArgsConstructor</span><br><span style="color: #61aeee;line-height: 26px;">@TableName</span>(value&nbsp;=&nbsp;<span style="color: #98c379;line-height: 26px;">"tb_user"</span>)<br><span style="color: #c678dd;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">class</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">User</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">@TableId</span>(type&nbsp;=&nbsp;IdType.AUTO)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Long&nbsp;id;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;String&nbsp;userNo;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;String&nbsp;nickname;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;String&nbsp;email;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;String&nbsp;phone;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Integer&nbsp;gender;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Date&nbsp;birthday;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Integer&nbsp;isDelete;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Date&nbsp;createTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Date&nbsp;updateTime;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">下面高级功能的示例都是基于上面的表进行展开的。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>1.批量插入</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我们在日常开发中知道大批量插入数据可能造成性能瓶颈,所以需要格外关注。在之前的入门教程讲过<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">mp(MyBatis-Plus简称,下文都用简称)</code>对数据库的CRUD操作提供了<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service层和mapper层的接口方法</code>封装,两者的一大区别就是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">service CRUD接口</code>提供了批量保存的操作,下面就分别来看看批量保存1000条user数据,然后对执行时间进行统计对比和性能评估,这里我连接的数据库是4核8G10M轻量服务器部署的,不同的数据库服务环境配置,执行效率是不一样的,所以下面的执行时间仅供对比参考。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>mapper层的CRUD接口</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;mapper层的crud接口方法批量插入<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">@Test</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">public</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">void</span>&nbsp;<span style="color: #61aeee;line-height: 26px;">testMapperBatchAdd</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;User&gt;&nbsp;users&nbsp;=&nbsp;<span style="color: #c678dd;line-height: 26px;">new</span>&nbsp;ArrayList&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">for</span>(<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;i&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">1</span>;&nbsp;i&nbsp;&lt;=&nbsp;<span style="color: #d19a66;line-height: 26px;">1000</span>;&nbsp;i++)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;User.builder()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.id(i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.userNo(<span style="color: #98c379;line-height: 26px;">"No-"</span>&nbsp;+&nbsp;i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.nickname(<span style="color: #98c379;line-height: 26px;">"哈哈"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.phone(<span style="color: #98c379;line-height: 26px;">"12345678901"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.email(<span style="color: #98c379;line-height: 26px;">"shepherd_123@qq.com"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.birthday(<span style="color: #c678dd;line-height: 26px;">new</span>&nbsp;Date())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.gender(<span style="color: #d19a66;line-height: 26px;">0</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.isDelete(<span style="color: #d19a66;line-height: 26px;">0</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users.add(user);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;start&nbsp;=&nbsp;System.currentTimeMillis();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users.forEach(user&nbsp;-&gt;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userDAO.insert(user);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;end&nbsp;=&nbsp;System.currentTimeMillis();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #98c379;line-height: 26px;">"执行时长:"</span>&nbsp;+&nbsp;(end-start)&nbsp;+&nbsp;<span style="color: #98c379;line-height: 26px;">"毫秒"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">执行时长:42516毫秒<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>service层CRUD接口</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;service层的crud接口方法批量插入<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">@Test</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">public</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">void</span>&nbsp;<span style="color: #61aeee;line-height: 26px;">testServiceBatchAdd</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;User&gt;&nbsp;users&nbsp;=&nbsp;<span style="color: #c678dd;line-height: 26px;">new</span>&nbsp;ArrayList&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">for</span>(<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;i&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">1</span>;&nbsp;i&nbsp;&lt;=&nbsp;<span style="color: #d19a66;line-height: 26px;">1000</span>;&nbsp;i++)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;User.builder()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.id(i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.userNo(<span style="color: #98c379;line-height: 26px;">"No-"</span>&nbsp;+&nbsp;i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.nickname(<span style="color: #98c379;line-height: 26px;">"哈哈"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.phone(<span style="color: #98c379;line-height: 26px;">"12345678901"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.email(<span style="color: #98c379;line-height: 26px;">"shepherd_123@qq.com"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.birthday(<span style="color: #c678dd;line-height: 26px;">new</span>&nbsp;Date())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.gender(<span style="color: #d19a66;line-height: 26px;">0</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.isDelete(<span style="color: #d19a66;line-height: 26px;">0</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users.add(user);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;start&nbsp;=&nbsp;System.currentTimeMillis();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userService.saveBatch(users);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">long</span>&nbsp;end&nbsp;=&nbsp;System.currentTimeMillis();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #98c379;line-height: 26px;">"执行时长:"</span>&nbsp;+&nbsp;(end-start)&nbsp;+&nbsp;<span style="color: #98c379;line-height: 26px;">"毫秒"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">执行时长:19385毫秒<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">可以看出,使用service层提供的批量保存接口<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">userService.saveBatch(users)</code>虽然快了很多,却仍需要19s,耗时比起mapper层的一条一条地插入快了23s,但是对于服务接口响应来说还是不可接受的。那为什么批量插入保存还是比较慢呢?</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">MySQL 的 JDBC 连接的 url 中要加 rewriteBatchedStatements 参数,并保证 5.1.13 以上版本的驱动,才能实现高性能的批量插入。</p> </blockquote> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">spring:</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">datasource:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">driver-class-name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">com.mysql.cj.jdbc.Driver</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">username:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">root</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">password:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">root</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">url:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">jdbc:mysql://ip:3306/db_test?&amp;serverTimezone=Asia/Shanghai&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;autoReconnect=true&amp;useSSL=false&amp;allowPublicKeyRetrieval=true&amp;rewriteBatchedStatements=true</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">再次执行上面的service层crud接口批量插入方法,执行结果如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">执行时长:1364毫秒<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">可以看到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">jdbcurl</code> 添加了 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">rewriteBatchedStatements=true</code> 参数后,批量操作的执行耗时已经只有 1364 毫秒快的飞起,具体缘由分析请看:https://juejin.cn/post/7295688187752562751</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>2.逻辑删除</h2> <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;">添加配置如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">mybatis-plus:</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">global-config:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">db-config:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">logic-delete-field:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">isDelete</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;全局逻辑删除的实体字段名</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">logic-delete-value:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">1</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;逻辑已删除值(默认为&nbsp;1)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">logic-not-delete-value:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">0</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;逻辑未删除值(默认为&nbsp;0)</span><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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;逻辑删除<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">@Test</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">public</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">void</span>&nbsp;<span style="color: #61aeee;line-height: 26px;">testLogicDelete</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userDAO.deleteById(<span style="color: #d19a66;line-height: 26px;">1L</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/50HcP4UOeLUKkJ1N0DXN4vchRASnLVnWiaN8YZVYeHbbhVoY0IVL43QJaAAFXlHR5jkwOhRW4A657KKG5icrnTw47Qa44GcOoe/640?wx_fmt=svg&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">2023-11-16&nbsp;17:01:47.656&nbsp;DEBUG&nbsp;10649&nbsp;---&nbsp;[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main]&nbsp;c.s.m.demo.dao.UserDAO.deleteById&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;==&gt;&nbsp;&nbsp;Preparing:&nbsp;UPDATE&nbsp;tb_user&nbsp;SET&nbsp;is_delete=1&nbsp;WHERE&nbsp;id=?&nbsp;AND&nbsp;is_delete=0<br>2023-11-16&nbsp;17:01:47.702&nbsp;DEBUG&nbsp;10649&nbsp;---&nbsp;[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main]&nbsp;c.s.m.demo.dao.UserDAO.deleteById&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;==&gt;&nbsp;Parameters:&nbsp;1(Long)<br>2023-11-16&nbsp;17:01:47.744&nbsp;DEBUG&nbsp;10649&nbsp;---&nbsp;[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main]&nbsp;c.s.m.demo.dao.UserDAO.deleteById&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&lt;==&nbsp;&nbsp;&nbsp;&nbsp;Updates:&nbsp;1<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">从日志可以看出做了更新,这就是逻辑删除,接�

注解方式优雅的实现 Redisson 分布式锁

作者:微信小助手

<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;counter-reset: counterh1 0 counterh2 0 counterh3 0;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" data-mpa-powered-by="yiban.io"> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: inline-block;"><span style="counter-increment: counterh2;color: rgb(159,205,208);border-bottom: 4px solid rgb(159,205,208);font-size: 18px;padding: 2px 4px;">1</span></span><span style="font-size: 18px;border-bottom: 4px solid rgb(37,132,181);padding: 2px 4px;color: rgb(37,132,181);">前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">日常开发中,难免遇到一些并发的场景,为了保证接口执行的一致性,通常采用加锁的方式,因为服务是分布式部署模式,本地锁Reentrantlock和Synchnorized这些就先放到一边了,Redis的setnx锁存在无法抱保证原子性的问题就暂时搁且到一边,直接上大招Redisson也是我最近开发项目中基本都在用的缓存,并且也都是用它的分布式锁机制。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: inline-block;"><span style="counter-increment: counterh2;color: rgb(159,205,208);border-bottom: 4px solid rgb(159,205,208);font-size: 18px;padding: 2px 4px;">2</span></span><span style="font-size: 18px;border-bottom: 4px solid rgb(37,132,181);padding: 2px 4px;color: rgb(37,132,181);">Redisson分布式锁常规使用</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">关于Redisson的一些基本概念,本章就不做太详细的说明了,有兴趣的小伙伴可以自己去了解下,主要说下加锁的常规使用,Redisson分布式锁是基于Redis的Rlock锁,实现了JavaJUC包下的Lock接口。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: inline-block;background-image: linear-gradient(45deg, transparent 48%, rgb(37, 132, 181) 48%, rgb(37, 132, 181) 52%, transparent 52%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;width: 24px;height: 24px;margin-bottom: -7px;"></span><span style="font-size: 16px;border-bottom: 1px solid rgb(37,132,181);padding: 2px 10px;color: rgb(37,132,181);">Lock</span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUPFlsrzna5Ytz9k7zL1bxmnPgk4RmPKvkoEevs1Fd1Ls0YgP6wjSl8q3rl4I44hia9cNTvkjXHC1lT6uLrwEMdgz/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;"><span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">public</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">void</span>&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">getLock</span><span style="line-height: 26px;">()</span></span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">//获取锁</span><br>&nbsp;&nbsp;&nbsp;&nbsp;RLock&nbsp;lock&nbsp;=&nbsp;redisson.getLock(<span style="color: #a6e22e;line-height: 26px;">"Lxlxxx_Lock"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">try</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">//&nbsp;2.加锁</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">catch</span>&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">finally</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">//&nbsp;3.解锁</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #a6e22e;line-height: 26px;">"Finally,释放锁成功"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">getLock获取锁,lock.lock进行加锁,会出现的问题就是lock拿不到锁一直等待,会进入阻塞状态,显然这样是不好的。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: inline-block;background-image: linear-gradient(45deg, transparent 48%, rgb(37, 132, 181) 48%, rgb(37, 132, 181) 52%, transparent 52%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;width: 24px;height: 24px;margin-bottom: -7px;"></span><span style="font-size: 16px;border-bottom: 1px solid rgb(37,132,181);padding: 2px 10px;color: rgb(37,132,181);">TryLock</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">返回boolean类型,和Reentrantlock的tryLock是一个意思,尝试获取锁,获取到就返回true,获取失败就返回false,不会使获不到锁的线程一直处于等待状态,返回false可以继续执行下面的业务逻辑,当然Ression锁内部也涉及到watchDog看门狗机制,主要作用就是给快过期的锁进行续期,主要用途就是使拿到锁的有限时间让业务执行完,再进行锁释放。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUPFlsrzna5Ytz9k7zL1bxmnPgk4RmPKvkoEevs1Fd1Ls0YgP6wjSl8q3rl4I44hia9cNTvkjXHC1lT6uLrwEMdgz/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">RLock&nbsp;lock&nbsp;=&nbsp;redisson.getLock(name);<br><span style="color: #f92672;font-weight: bold;line-height: 26px;">try</span>&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(lock.tryLock(<span style="line-height: 26px;">2</span>,&nbsp;<span style="line-height: 26px;">10</span>,&nbsp;TimeUnit.SECONDS))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">//执行业务逻辑</span><br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #a6e22e;line-height: 26px;">"已存在"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">catch</span>&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>}<span style="color: #f92672;font-weight: bold;line-height: 26px;">finally</span>&nbsp;{<br><span style="color: #75715e;line-height: 26px;">//判断当前线程持有的锁是不是处于锁定状态,锁定状态再进行释放</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.redissonLock.isHeldByCurrentThread(lockName))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.redissonLock.unlock(lockName);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: inline-block;"><span style="counter-increment: counterh2;color: rgb(159,205,208);border-bottom: 4px solid rgb(159,205,208);font-size: 18px;padding: 2px 4px;">3</span></span><span style="font-size: 18px;border-bottom: 4px solid rgb(37,132,181);padding: 2px 4px;color: rgb(37,132,181);">自定义注解实现锁机制</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通常我们都会将redisson实例注入到方法类里面,然后调用加锁方法进行加锁,如果其他业务方法也需要加锁执行,将会产生很多重复代码,由此采用AOP切面的方式,只需要通过注解的方式就能将方法进行加锁处理。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: inline-block;background-image: linear-gradient(45deg, transparent 48%, rgb(37, 132, 181) 48%, rgb(37, 132, 181) 52%, transparent 52%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;width: 24px;height: 24px;margin-bottom: -7px;"></span><span style="font-size: 16px;border-bottom: 1px solid rgb(37,132,181);padding: 2px 10px;color: rgb(37,132,181);">自定义注解</span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUPFlsrzna5Ytz9k7zL1bxmnPgk4RmPKvkoEevs1Fd1Ls0YgP6wjSl8q3rl4I44hia9cNTvkjXHC1lT6uLrwEMdgz/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;"><span style="color: #75715e;line-height: 26px;">@Documented</span><br><span style="color: #75715e;line-height: 26px;">@Inherited</span><br><span style="color: #75715e;line-height: 26px;">@Retention</span>(RetentionPolicy.RUNTIME)<br><span style="color: #75715e;line-height: 26px;">@Target</span>({ElementType.METHOD})<br><span style="color: #f92672;font-weight: bold;line-height: 26px;">public</span>&nbsp;<span style="color: #75715e;line-height: 26px;">@interface</span>&nbsp;DistributedLock&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">String&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">key</span><span style="line-height: 26px;">()</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">default</span>&nbsp;""</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">leaseTime</span><span style="line-height: 26px;">()</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">default</span>&nbsp;10</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">boolean</span>&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">autoRelease</span><span style="line-height: 26px;">()</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">default</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">true</span></span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">String&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">errorDesc</span><span style="line-height: 26px;">()</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">default</span>&nbsp;"系统正常处理,请稍后提交"</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">waitTime</span><span style="line-height: 26px;">()</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">default</span>&nbsp;1</span>;<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: inline-block;background-image: linear-gradient(45deg, transparent 48%, rgb(37, 132, 181) 48%, rgb(37, 132, 181) 52%, transparent 52%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;width: 24px;height: 24px;margin-bottom: -7px;"></span><span style="font-size: 16px;border-bottom: 1px solid rgb(37,132,181);padding: 2px 10px;color: rgb(37,132,181);">切面类实现</span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUPFlsrzna5Ytz9k7zL1bxmnPgk4RmPKvkoEevs1Fd1Ls0YgP6wjSl8q3rl4I44hia9cNTvkjXHC1lT6uLrwEMdgz/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;"><span style="color: #75715e;line-height: 26px;">@Aspect</span><br><span style="color: #75715e;line-height: 26px;">@Component</span><br><span style="color: #f92672;font-weight: bold;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">class</span>&nbsp;<span style="font-weight: bold;color: white;line-height: 26px;">DistributedLockHandler</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">private</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">static</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">final</span>&nbsp;Logger&nbsp;log&nbsp;=&nbsp;LoggerFactory.getLogger(DistributedLockHandler<span style="line-height: 26px;">.<span style="color: #f92672;font-weight: bold;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">@Autowired</span><br>&nbsp;&nbsp;&nbsp;&nbsp;RedissonLock&nbsp;redissonLock;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">public</span>&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">DistributedLockHandler</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">@Around</span>(<span style="color: #a6e22e;line-height: 26px;">"@annotation(distributedLock)"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">public</span>&nbsp;Object&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">around</span><span style="line-height: 26px;">(ProceedingJoinPoint&nbsp;joinPoint,&nbsp;DistributedLock&nbsp;distributedLock)</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">throws</span>&nbsp;Throwable&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;lockName&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.getRedisKey(joinPoint,&nbsp;distributedLock);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;leaseTime&nbsp;=&nbsp;distributedLock.leaseTime();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;errorDesc&nbsp;=&nbsp;distributedLock.errorDesc();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;waitTime&nbsp;=&nbsp;distributedLock.waitTime();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;var8;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">try</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">boolean</span>&nbsp;lock&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.redissonLock.tryLock(lockName,&nbsp;(<span style="color: #f92672;font-weight: bold;line-height: 26px;">long</span>)leaseTime,&nbsp;(<span style="color: #f92672;font-weight: bold;line-height: 26px;">long</span>)waitTime);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(!lock)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">throw</span>&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">new</span>&nbsp;RuntimeException(errorDesc);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var8&nbsp;=&nbsp;joinPoint.proceed();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">catch</span>&nbsp;(Throwable&nbsp;var12)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.error(<span style="color: #a6e22e;line-height: 26px;">"执行业务方法异常"</span>,&nbsp;var12);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">throw</span>&nbsp;var12;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">finally</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.redissonLock.isHeldByCurrentThread(lockName))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">this</span>.redissonLock.unlock(lockName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">return</span>&nbsp;var8;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #75715e;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;获取加锁的key<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@param</span>&nbsp;joinPoint<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@param</span>&nbsp;distributedLock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@return</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #f92672;font-weight: bold;line-height: 26px;">private</span>&nbsp;String&nbsp;<span style="color: #a6e22e;font-weight: bold;line-height: 26px;">getRedisKey</span><span style="line-height: 26px;">(ProceedingJoinPoint&nbsp;joinPoint,&nbsp;DistributedLock&nbsp;distributedLock)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;key&nbsp;=&nbsp;distributedLock.key();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[]&nbsp;parameterValues&nbsp;=&nbsp;joinPoint.getArgs();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodSignature&nbsp;signature&nbsp;=&nbsp;(MethodSignature)joinPoint.getSignature();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method&nbsp;=&nbsp;signature.getMethod();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultParameterNameDiscoverer&nbsp;nameDiscoverer&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">new</span>&nbsp;DefaultParameterNameDiscoverer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;parameterNames&nbsp;=&nbsp;nameDiscoverer.getParameterNames(method);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(StringUtils.isEmpty(key))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(parameterNames&nbsp;!=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">null</span>&nbsp;&amp;&amp;&nbsp;parameterNames.length&nbsp;&gt;&nbsp;<span style="line-height: 26px;">0</span>)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;sb&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">new</span>&nbsp;StringBuffer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;i&nbsp;=&nbsp;<span style="line-height: 26px;">0</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">for</span>(<span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;len&nbsp;=&nbsp;parameterNames.length;&nbsp;i&nbsp;&lt;&nbsp;len;&nbsp;++i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(parameterNames[i]).append(<span style="color: #a6e22e;line-height: 26px;">"&nbsp;=&nbsp;"</span>).append(parameterValues[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;=&nbsp;sb.toString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;=&nbsp;<span style="color: #a6e22e;line-height: 26px;">"redissionLock"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">return</span>&nbsp;key;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SpelExpressionParser&nbsp;parser&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">new</span>&nbsp;SpelExpressionParser();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;expression&nbsp;=&nbsp;parser.parseExpression(key);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span>&nbsp;(parameterNames&nbsp;!=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">null</span>&nbsp;&amp;&amp;&nbsp;parameterNames.length&nbsp;!=&nbsp;<span style="line-height: 26px;">0</span>)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EvaluationContext&nbsp;evaluationContext&nbsp;=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">new</span>&nbsp;StandardEvaluationContext();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">for</span>(<span style="color: #f92672;font-weight: bold;line-height: 26px;">int</span>&nbsp;i&nbsp;=&nbsp;<span style="line-height: 26px;">0</span>;&nbsp;i&nbsp;&lt;&nbsp;parameterNames.length;&nbsp;++i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;evaluationContext.setVariable(parameterNames[i],&nbsp;parameterValues[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">try</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;expressionValue&nbsp;=&nbsp;expression.getValue(evaluationContext);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">return</span>&nbsp;expressionValue&nbsp;!=&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">null</span>&nbsp;&amp;&amp;&nbsp;!<span style="color: #a6e22e;line-height: 26px;">""</span>.equals(expressionValue.toString())&nbsp;?&nbsp;expressionValue.toString()&nbsp;:&nbsp;key;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">catch</span>&nbsp;(Exception&nbsp;var13)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">return</span>&nbsp;key;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #f92672;font-weight: bold;line-height: 26px;">return</span>&nbsp;key;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: inline-block;background-image: linear-gradient(45deg, transparent 48%, rgb(37, 132, 181) 48%, rgb(37, 132, 181) 52%, transparent 52%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;width: 24px;height: 24px;margin-bottom: -7px;"></span><span style="font-size: 16px;border-bottom: 1px solid rgb(37,132,181);padding: 2px 10px;color: rgb(37,132,181);">具体使用</span><span style="display: none;"></span></h3> <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.07076719576719577" src="/upload/33a8aad2ff04c4ea9ddb2c37c5a07654.png" data-type="other" data-w="1512" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">方法头加自定义注解,key参数代表需要加锁的key,errorDesc获取锁失败提示报错信息。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这边我将项目通过修改端口启动了两个服务,分别是8460和8461</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.12235449735449735" src="/upload/11fa896b001a31eb6d9ed195ba0f2bc6.png" data-type="other" data-w="1512" 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 class="rich_pages wxw-img" data-ratio="0.11243386243386243" src="/upload/bb61682f803fb44c419bb63d20d4d5d0.png" data-type="other" data-w="1512" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过postman调用这两个服务,模拟两个服务同时获取一把锁的场景,其中一个服务拿到锁,另外一个服务获取锁失败。</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.5747354497354498" src="/upload/cc45e28fdb8ad5943ecd3f81848ec02e.png" data-type="other" data-w="1512" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">可以看到端口8460服务先拿到锁,8461服务tryLock获取锁失败,实现了加锁逻辑。</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.24338624338624337" src="/upload/e8a064c80e8591e505917cb39776cabd.png" data-type="other" data-w="1512" 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 class="rich_pages wxw-img" data-ratio="0.22288359788359788" src="/upload/21ff4f75235e67d561636298272a074e.png" data-type="other" data-w="1512" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: inline-block;"><span style="counter-increment: counterh2;color: rgb(159,205,208);border-bottom: 4px solid rgb(159,205,208);font-size: 18px;padding: 2px 4px;">4</span></span><span style="font-size: 18px;border-bottom: 4px solid rgb(37,132,181);padding: 2px 4px;color: rgb(37,132,181);">总结</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">分布式锁的使用场景还是需要多注意下,根据业务场景来,并发量不大的情况下,其实没有必要加,可能在移动端操作比较频繁的情况下需要注意并发,目前我做的b端项目,通过简单接口幂等性操作就可以避免重复提交,切勿不要盲目加锁,多少会影响一些性能。</p> </section> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="37" data-source-title="" style="outline: 0px;color: var(--weui-FG-1);text-wrap: wrap;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;letter-spacing: normal;text-align: left;background-color: rgb(255, 255, 255);"> <section class="js_blockquote_digest" style="outline: 0px;"> <section style="outline: 0px;"> <span style="outline: 0px;font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;color: rgb(136, 136, 136);cursor: pointer;font-size: 11px;">来源:juejin.cn/post/7215142807861379109</span> </section> </section> </blockquote> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 1em;outline: 0px;border-left-width: 2px;border-left-color: rgb(136, 136, 136);color: rgb(119, 119, 119);font-size: 0.9em;text-wrap: wrap;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;letter-spacing: normal;text-align: left;caret-color: rgb(60, 60, 60);widows: 1;border-top: none;border-bottom: none;overflow: auto;background: rgba(0, 0, 0, 0.05);border-right: 2px solid rgb(136, 136, 136);visibility: visible;"></blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;text-wrap: wrap;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;letter-spacing: normal;text-align: left;caret-color: rgb(60, 60, 60);widows: 1;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;visibility: visible;"> <figcaption style="margin-top: 5px;outline: 0px;text-align: center;color: rgb(136, 136, 136);font-size: 14px;visibility: visible;"> 加我好友,拉你进群 </figcaption> </figure>

分布式锁的各种实现,看完这篇你就懂了!

作者:微信小助手

<p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">今天我们讲讲分布式锁,网上相关的内容有很多,但是比较分散,刚好自己刚学习完总结下,分享给大家,文章内容会比较多,我们先从思维导图中了解要讲的内容。</p> <figure style="font-size: 14px;letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin: 1.5em 8px;color: rgb(63, 63, 63);"> <img data-imgfileid="100000535" data-ratio="1.0756646216768917" src="/upload/2f5489db551a6b15fef78f82a12c0144.png" data-type="png" data-w="978" style="line-height: 1.75;border-radius: 4px;display: block;margin: 0.1em auto 0.5em;" title="null"> </figure> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">什么是分布式锁</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">分布式锁是控制分布式系统之间同步访问共享资源的一种方式,通过互斥来保持一致性。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">了解分布式锁之前先了解下线程锁和进程锁:</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如Synchronized、Lock等</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">进程锁:控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">比如Golang语言中的sync包就提供了基本的同步基元,如互斥锁</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">但是以上两种适合在单体架构应用,但是分布式系统中多个服务节点,多个进程分散部署在不同节点机器中,此时对于资源的竞争,上诉两种对节点本地资源的锁就无效了。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这个时候就需要分布式锁来对分布式系统多进程访问资源进行控制,因此分布式锁是为了解决分布式互斥问题!</p> <figure style="font-size: 14px;letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin: 1.5em 8px;color: rgb(63, 63, 63);"> <img data-imgfileid="100000536" data-ratio="0.5279411764705882" src="/upload/eef18e455c23d10592cf733b7b312b79.png" data-type="png" data-w="680" style="line-height: 1.75;border-radius: 4px;display: block;margin: 0.1em auto 0.5em;" title="null"> </figure> <h2 style="letter-spacing: normal;text-wrap: wrap;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.4em;font-weight: bold;display: table;margin-top: 1.5em;margin-bottom: 1.5em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(15, 76, 129);color: rgb(255, 255, 255);">分布式锁的特性</h2> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">互斥</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">互斥性很好理解,这也是最基本功能,就是在任意时刻,只能有一个客户端才能获取锁,不能同时有两个客户端获取到锁。</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">避免死锁</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">为什么会出现死锁,因为获取锁的客户端因为某些原因(如down机等)而未能释放锁,其它客户端再也无法获取到该锁,从而导致整个流程无法继续进行。</p> <figure style="font-size: 14px;letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin: 1.5em 8px;color: rgb(63, 63, 63);"> <img data-imgfileid="100000534" data-ratio="0.25953259532595324" src="/upload/25f26d35cd0b3b6885d8587263eadc62.png" data-type="png" data-w="813" style="line-height: 1.75;border-radius: 4px;display: block;margin: 0.1em auto 0.5em;" title="null"> </figure> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">面对这种情况,当然有解决办法啦!</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">引入过期时间:通常情况下我们会设置一个 TTL(Time To Live,存活时间) 来避免死锁,但是这并不能完全避免。</p> <ol style="font-size: 14px;letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;padding-left: 32px;color: rgb(63, 63, 63);" class="list-paddingleft-1"> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>1.&nbsp;比如TTL为5秒,进程A获得锁</p></li> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>2.&nbsp;问题是5秒内进程A并未释放锁,被系统自动释放,进程B获得锁</p></li> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>3.&nbsp;刚好第6秒时进程A执行完,又会释放锁,也就是进程A释放了进程B的锁</p></li> </ol> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">仅仅加个过期时间会设计到两个问题:锁过期和释放别人的锁问题</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">锁附加唯一性:针对释放别人锁这种问题,我们可以给每个客户端进程设置【唯一ID】,这样我们就可以在应用层就进行检查唯一ID。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">自动续期:锁过期问题的出现,是我们对持有锁的时间不好进行预估,设置较短的话会有【提前过期】风险,但是过期时间设置过长,可能锁长时间得不到释放。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这种情况同样有处理方式,可以开启一个守护进程(watch dog),检测失效时间进行续租,比如Java技术栈可以用Redisson来处理。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">可重入:</p> <blockquote style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 0.9em;border-left-width: 6px;border-left-color: rgb(220, 230, 240);padding: 15px 15px 15px 1rem;border-radius: 8px;color: rgb(129, 145, 152);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="line-height: 1.75;font-size: 1em;letter-spacing: 0.1em;color: rgb(80, 80, 80);">一个线程获取了锁,但是在执行时,又再次尝试获取锁会发生什么情况?</p> </blockquote> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">是的,导致了重复获取锁,占用了锁资源,造成了死锁问题。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">我们了解下什么是【可重入】:指的是同一个线程在持有锁的情况下,可以多次获取该锁而不会造成死锁,也就是一个线程可以在获取锁之后再次获取同一个锁,而不需要等待锁释放。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">解决方式:比如实现Redis分布式锁的可重入,在实现时,需要借助Redis的Lua脚本语言,并使用引用计数器技术,保证同一线程可重入锁的正确性。</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">容错</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">容错性是为了当部分节点(redis节点等)宕机时,客户端仍然能够获取锁和释放锁,一般来说会有以下两种处理方式:</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">一种像etcd/zookeeper这种作为锁服务能够自动进行故障切换,因为它本身就是个集群,另一种可以提供多个独立的锁服务,客户端向多个独立锁服务进行请求,某个锁服务故障时,也可以从其他服务获取到锁信息,但是这种缺点很明显,客户端需要去请求多个锁服务。</p> <h2 style="letter-spacing: normal;text-wrap: wrap;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.4em;font-weight: bold;display: table;margin-top: 1.5em;margin-bottom: 1.5em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(15, 76, 129);color: rgb(255, 255, 255);">分类</h2> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">本文会讲述四种关于分布式锁的实现,按实现方式来看,可以分为两种:自旋、watch监听</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">自旋方式</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">基于数据库和基于Redis的实现就是需要在客户端未获得锁时,进入一个循环,不断的尝试请求是否能获得锁,直到成功或者超时过期为止。</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">监听方式</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这种方式只需要客户端Watch监听某个key就可以了,锁可用的时候会通知客户端,客户端不需要反复请求,基于zooKeeper和基于Etcd实现分布式锁就是用这种方式。</p> <h2 style="letter-spacing: normal;text-wrap: wrap;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.4em;font-weight: bold;display: table;margin-top: 1.5em;margin-bottom: 1.5em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(15, 76, 129);color: rgb(255, 255, 255);">实现方式</h2> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">分布式锁的实现方式有数据库、基于Redis缓存、ZooKeeper、Etcd等,文章主要从这几种实现方式并结合问题的方式展开叙述!</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">基于MySQL</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">利用数据库表来实现实现分布式锁,是不是感觉有点疑惑,是的,我再写之前收集资料的时候也有点疑问,虽然这种方式我们并不推崇,但是我们也可以作为一个方案来进行了解,我们看看到底怎么做的:</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">比如在数据库中创建一个表,表中包含方法名等字段,并在方法名name字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入一条记录,成功插入则获取锁,删除对应的行就是锁释放。</p> <pre style="color: rgb(224, 226, 228);background: rgb(40, 43, 46);font-size: 14px;letter-spacing: normal;text-align: left;line-height: 1.5;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;overflow-x: auto;border-radius: 8px;margin: 10px 8px;"><span style="padding: initial;display: block;height: 25px;background-color: transparent;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/VzQsdzsGScPov1icicO8OktPuxZfVBHbtfOVFpsiaSxNKpr8Esic64QtYn3eZkSQibEjc2jvYbbJdFW2djeQJ299LTfhWd7qObiaRE/640?wx_fmt=svg&amp;from=appmsg&quot;);background-position: 14px 10px;background-repeat: no-repeat;background-size: 40px;"></span><code style="font-family: Menlo, &quot;Operator Mono&quot;, Consolas, Monaco, monospace;display: -webkit-box;overflow-x: auto;line-height: 1.75;margin-right: 2px;margin-left: 2px;white-space-collapse: collapse;padding: 2px 4px;border-radius: 4px;"><span>//锁记录表</span><br><span>CREATE&nbsp;TABLE&nbsp;</span><span>`lock_info`</span><span>&nbsp;</span><span>(</span><br><span>&nbsp;&nbsp;</span><span>`id`</span><span>&nbsp;</span><span>int</span><span>(</span><span>11</span><span>)</span><span>&nbsp;</span><span>unsigned</span><span>&nbsp;NOT&nbsp;NULL&nbsp;AUTO_INCREMENT&nbsp;COMMENT&nbsp;</span><span>'主键'</span><span>,</span><br><span>&nbsp;&nbsp;</span><span>`name`</span><span>&nbsp;varchar</span><span>(</span><span>64</span><span>)</span><span>&nbsp;NOT&nbsp;NULL&nbsp;COMMENT&nbsp;</span><span>'方法名'</span><span>,</span><br><span>&nbsp;&nbsp;PRIMARY&nbsp;KEY&nbsp;</span><span>(</span><span>`id`</span><span>),</span><br><span>&nbsp;&nbsp;UNIQUE&nbsp;KEY&nbsp;</span><span>`idx_name`</span><span>&nbsp;</span><span>(</span><span>`method_name`</span><span>)</span><span>&nbsp;</span><br><span>)</span><span>&nbsp;ENGINE</span><span>=</span><span>InnoD</span></code></pre> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这里主要是用name字段作为唯一索引来实现,唯一索引保证了该记录的唯一性,锁释放就直接删掉该条记录就行了。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">缺点也很多:</p> <ol style="font-size: 14px;letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;padding-left: 32px;color: rgb(63, 63, 63);" class="list-paddingleft-1"> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>1.&nbsp;数据库是单点,非常依赖数据库的可用性</p></li> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>2.&nbsp;需要额外自己维护TTL</p></li> <li style="text-align: left;line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px 0.5em;"><p>3.&nbsp;在高并发常见下数据库读写是非常缓慢</p></li> </ol> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这里我们就不用过多的文字了,现实中我们更多的是用基于内存存储来实现分布式锁。</p> <h3 style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 1.3em;font-weight: bold;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 8px;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);border-bottom: 2px solid rgb(0, 172, 193);">基于Redis</h3> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">面试官问:你了解分布式锁吗?想必绝大部分面试者都会说关于Redis实现分布式锁的方式,OK,进入正题【基于Redis分布式锁】</p> <blockquote style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 0.9em;border-left-width: 6px;border-left-color: rgb(220, 230, 240);padding: 15px 15px 15px 1rem;border-radius: 8px;color: rgb(129, 145, 152);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="line-height: 1.75;font-size: 1em;letter-spacing: 0.1em;color: rgb(80, 80, 80);">Redis 的分布式锁, setnx 命令并设置过期时间就行吗?</p> </blockquote> <pre style="color: rgb(224, 226, 228);background: rgb(40, 43, 46);font-size: 14px;letter-spacing: normal;text-align: left;line-height: 1.5;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;overflow-x: auto;border-radius: 8px;margin: 10px 8px;"><span style="padding: initial;display: block;height: 25px;background-color: transparent;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/VzQsdzsGScPov1icicO8OktPuxZfVBHbtfOVFpsiaSxNKpr8Esic64QtYn3eZkSQibEjc2jvYbbJdFW2djeQJ299LTfhWd7qObiaRE/640?wx_fmt=svg&amp;from=appmsg&quot;);background-position: 14px 10px;background-repeat: no-repeat;background-size: 40px;"></span><code style="font-family: Menlo, &quot;Operator Mono&quot;, Consolas, Monaco, monospace;display: -webkit-box;overflow-x: auto;line-height: 1.75;margin-right: 2px;margin-left: 2px;white-space-collapse: collapse;padding: 2px 4px;border-radius: 4px;"><span>setnx&nbsp;lkey&nbsp;lvalue&nbsp;expire&nbsp;lockKey&nbsp;</span><span>30</span></code></pre> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">正常情况下是可以的,但是这里有个问题,虽然setnx是原子性的,但是setnx + expire就不是了,也就是说setnx和expire是分两步执行的,【加锁和超时】两个操作是分开的,如果expire执行失败了,那么锁同样得不到释放。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">关于为什么要加锁和超时时间的设定在文章开头【避免死锁】有提到,不明白的可以多看看。</p> <blockquote style="letter-spacing: normal;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 0.9em;border-left-width: 6px;border-left-color: rgb(220, 230, 240);padding: 15px 15px 15px 1rem;border-radius: 8px;color: rgb(129, 145, 152);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="line-height: 1.75;font-size: 1em;letter-spacing: 0.1em;color: rgb(80, 80, 80);">Redis正确的加锁命令是什么?</p> </blockquote> <pre style="color: rgb(224, 226, 228);background: rgb(40, 43, 46);font-size: 14px;letter-spacing: normal;text-align: left;line-height: 1.5;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;overflow-x: auto;border-radius: 8px;margin: 10px 8px;"><span style="padding: initial;display: block;height: 25px;background-color: transparent;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/VzQsdzsGScPov1icicO8OktPuxZfVBHbtfOVFpsiaSxNKpr8Esic64QtYn3eZkSQibEjc2jvYbbJdFW2djeQJ299LTfhWd7qObiaRE/640?wx_fmt=svg&amp;from=appmsg&quot;);background-position: 14px 10px;background-repeat: no-repeat;background-size: 40px;"></span><code style="font-family: Menlo, &quot;Operator Mono&quot;, Consolas, Monaco, monospace;display: -webkit-box;overflow-x: auto;line-height: 1.75;margin-right: 2px;margin-left: 2px;white-space-collapse: collapse;padding: 2px 4px;border-radius: 4px;"><span>//保证原子性执行命令</span><br><span>SET&nbsp;lKey&nbsp;randId&nbsp;NX&nbsp;PX&nbsp;</span><span>30000</span></code></pre> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rgb(63, 63, 63);">randId是由客户端生成的一个随机字符串,该客户端加锁时具有唯一性,主要是为了避免释放别人的锁。</p> <p style="font-size: 14px;text-wrap: wrap;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;margin-top: 1.5em;margin-bottom: 1.5em;letter-spacing: 0.1em;color: rg

Grafana实现搭建免密登录大屏教程

作者:微信小助手

<p style="text-align: center;" data-mpa-powered-by="yiban.io"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100008763" data-ratio="0.42314814814814816" data-s="300,640" src="/upload/1384189701ac5ced7af270b8717ca2a.png" data-type="png" data-w="1080" style=""></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.背景<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">经常会有这样一种场景,在办公室或是监控中心能够有一块屏幕来监控和展示一些软件、硬件的详细信息,比如运维比较关心的CPU/内存/硬盘的指标或者系统软件的运行信息等。当我们用grafana来展示时,发现每次都需要手动登录并切换到标签页,才能看到详细信息,而我们希望系统操作系统只要一开机后就能自动切换到我们的屏幕上,方便实现自动化。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>2.实现原理</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">创建一个免密登录用户,使用大屏归属于此用户上,使用grafana的免密登录加大屏的链接分享实现。即直接访问一个固定链接(无论是否登录)都能够看到此页面。</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-imgfileid="100008761" data-ratio="0.49074074074074076" src="/upload/c552c62efbb7f351eb9a208df38863ac.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;font-size: 22px;"><span style="display: none;"></span>3.实现过程</h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>3.1 创建免密用户<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">首先使用admin管理员账户登录grafana,找到orgs用户组管理。</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-imgfileid="100008764" data-ratio="0.47129629629629627" src="/upload/d48d5320c1d8c0e76a022290eb45ad26.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;">添加一个用户组home(根据实际情况修改,我这里以家庭演示为例):</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-imgfileid="100008766" data-ratio="0.39166666666666666" src="/upload/36d961792bbee56bca63a4caf50f1f0f.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;">创建完会新增一个home用户组:</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-imgfileid="100008768" data-ratio="0.3398148148148148" src="/upload/7928216cce14f43d1aeb3be20473deae.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;">在user下边创建一个home用户:<img class="rich_pages wxw-img" data-imgfileid="100008770" data-ratio="0.32407407407407407" src="/upload/e3929b5c682fff31434226548fb14e1d.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"></p> <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 class="rich_pages wxw-img" data-imgfileid="100008767" data-ratio="0.32222222222222224" src="/upload/ece12fc445e08c2bbeb64d4df9426736.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>3.2.授权免密登录<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">打开grafana的配置文件,在修改前备份:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/Lm4IarPJiaOMA1bfv0v3TSaMj8Uam7KyerWqXDnTBFeotiay1WCPLbc3UqiaBlT1RFU8SSZTWlTn5poXsuvnmGydA/640?wx_fmt=png&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;">cp&nbsp;grafana.ini&nbsp;grafana.ini.bak<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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/Lm4IarPJiaOMA1bfv0v3TSaMj8Uam7KyerWqXDnTBFeotiay1WCPLbc3UqiaBlT1RFU8SSZTWlTn5poXsuvnmGydA/640?wx_fmt=png&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;">vim&nbsp;grafana.ini<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">找到如图所示的配置:<img class="rich_pages wxw-img" data-imgfileid="100008769" data-ratio="0.42962962962962964" src="/upload/d06e7855d306485369a18186091a4eba.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"></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;">#表示开启匿名登录 enabled = true</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">#修改为之前建立的home组织 org_name = home</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">#角色为观看者 org_role = Viewer</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">#隐藏版本 hide_version = true</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/Lm4IarPJiaOMA1bfv0v3TSaMj8Uam7KyerWqXDnTBFeotiay1WCPLbc3UqiaBlT1RFU8SSZTWlTn5poXsuvnmGydA/640?wx_fmt=png&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;">[auth.anonymous]<br><span style="color: #57A64A;font-style: italic;line-height: 26px;">#&nbsp;enable&nbsp;anonymous&nbsp;access</span><br>enabled&nbsp;=&nbsp;<span style="color: #569CD6;line-height: 26px;">true</span><br><br><span style="color: #57A64A;font-style: italic;line-height: 26px;">#&nbsp;specify&nbsp;organization&nbsp;name&nbsp;that&nbsp;should&nbsp;be&nbsp;used&nbsp;for&nbsp;unauthenticated&nbsp;users</span><br>org_name&nbsp;=&nbsp;home<br><br><span style="color: #57A64A;font-style: italic;line-height: 26px;">#&nbsp;specify&nbsp;role&nbsp;for&nbsp;unauthenticated&nbsp;users</span><br>org_role&nbsp;=&nbsp;Viewer<br><br><span style="color: #57A64A;font-style: italic;line-height: 26px;">#&nbsp;mask&nbsp;the&nbsp;Grafana&nbsp;version&nbsp;number&nbsp;for&nbsp;unauthenticated&nbsp;users</span><br>hide_version&nbsp;=&nbsp;<span style="color: #569CD6;line-height: 26px;">true</span><br><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 class="rich_pages wxw-img" data-imgfileid="100008774" data-ratio="0.48148148148148145" src="/upload/ee3e9bbb11bb0354ec6fee2de928da56.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> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/Lm4IarPJiaOMA1bfv0v3TSaMj8Uam7KyerWqXDnTBFeotiay1WCPLbc3UqiaBlT1RFU8SSZTWlTn5poXsuvnmGydA/640?wx_fmt=png&amp;from=appmsg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;">docker&nbsp;restart&nbsp;grafana<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>3.3 配置大屏<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">切换到home组织下:</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-imgfileid="100008772" data-ratio="1.762962962962963" src="/upload/dcf8918ab130b727ef5eafc1a0933014.png" data-type="png" data-w="810" 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 class="rich_pages wxw-img" data-imgfileid="100008771" data-ratio="0.32222222222222224" src="/upload/1e01d1c79de0f7f4cf8045ece7ecfd2f.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 class="rich_pages wxw-img" data-imgfileid="100008773" data-ratio="0.33796296296296297" src="/upload/42547c8214f45ea1244f183d434a3669.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 class="rich_pages wxw-img" data-imgfileid="100008775" data-ratio="0.30185185185185187" src="/upload/4e72bf78d845e06b3e4b324862767e43.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;">确保Viewer权限为view,然后保存。<img class="rich_pages wxw-img" data-imgfileid="100008779" data-ratio="0.2462962962962963" src="/upload/7dabf109e7c9a0f6d22c1a623d6d75c.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"></p> <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 class="rich_pages wxw-img" data-imgfileid="100008776" data-ratio="0.31296296296296294" src="/upload/5af3cf430b10b8019dd13c51cffc7bf4.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;">将shorten URL打勾,最后拷贝生成的链接即可。<img class="rich_pages wxw-img" data-imgfileid="100008777" data-ratio="0.5296296296296297" src="/upload/96d51c0d80392fd8b55e3d01e2af6ad2.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>3.4 测试<span style="display: none;"></span></h3> <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 class="rich_pages wxw-img" data-imgfileid="100008778" data-ratio="0.462037037037037" src="/upload/ed46a6e06a0c7bff07bdb3d5d795d7d9.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;font-size: 22px;"><span style="display: none;"></span>4.最后</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如果需要完成上电自启动展示,搭配浏览器自启动实现,在后续出详细教程,欢迎关注!</p> </section> <p><strong><span style="font-size: 16px;"><img class="rich_pages wxw-img" data-ratio="1" src="/upload/ba49e27fb394ea681b84321e80211c96.null" data-w="128" style="display:inline-block;width:20px;vertical-align:middle;background-size:cover;">往期推荐:</span></strong></p> <ol class="list-paddingleft-1" style="list-style-type: decimal;"> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU0MzQ3ODc4OA==&amp;mid=2247492368&amp;idx=1&amp;sn=7ab94920a02f0b373b5883db13cf161b&amp;chksm=fb08667bcc7fef6ddf18a09d384bbe4408b3226d4b6682fe6aef0cf7b4976fa3185358dcba7f&amp;scene=21#wechat_redirect" textvalue="快捷传输文件利器之sftp命令" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">快捷传输文件利器之sftp命令</a><br></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU0MzQ3ODc4OA==&amp;mid=2247492352&amp;idx=1&amp;sn=7f748b30237647bdc51270f2b311bc88&amp;chksm=fb08666bcc7fef7d434851862986fd29ed21c23987d78c4ea80dad4a68a2eae67871995b8b68&amp;scene=21#wechat_redirect" textvalue="Linux中10个一线工作中常用 Shell 脚本" linktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2">Linux中10个一线工作中常用 Shell 脚本</a></p></li> <li><p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU0MzQ3ODc4OA==&amp;mid=2247492349&amp;idx=1&amp;sn=3850ffbdad0954c3a9a9d89460dcafec&amp;chksm=fb086796cc7fee80d6205fcc4153d64276c79b66b7303f549e8623d8b936983785a4d62fe3b6&amp;scene=21#wechat_redirect" textvalue="建议收藏!Linux下Java/Python启动管理脚本" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">建议收藏!Linux下Java/Python启动管理脚本</a></p></li> </ol> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU0MzQ3ODc4OA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/Lm4IarPJiaOMF9KKX3xyk5ib5cysnFIysk11uTA5k2USlXWkljPmPibtU8H9QiaGFrENiacvu6PRQokmVe1ibPjvaggg/0?wx_fmt=png" data-nickname="运维贼船" data-alias="yunweizeichuan" data-signature="90后运维老司机,折腾各种服务器软硬件、树莓派、软路由。公众号分享大量Linux干货,包括Linux基础、Linux应用、服务器技术,软件,以及Python等前沿实用系列教程" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <p><br></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>