ingbyr https://ingbyr.github.io/ ingbyr Hugo 0.148.2 & FixIt v0.4.0-alpha.3-20251124100610-99fd4fb7 zh-CN [email protected] (ingbyr) [email protected] (ingbyr) Tue, 16 Dec 2025 09:30:01 +0800 Java8 Spring MVC 5 项目迁移 Java21 SpringBoot 3.5 记录 https://ingbyr.github.io/posts/migrate-to-java21-springboot3/ Mon, 15 Dec 2025 16:26:11 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/migrate-to-java21-springboot3/ Java Spring <p>总结了迁移 JDK8 Spring MVC 5 项目到 JDK21 SpringBoot 3.5 的一些处理方式与步骤。</p> <h2 class="heading-element" id="前置检查"><span>前置检查</span> <a href="#%e5%89%8d%e7%bd%ae%e6%a3%80%e6%9f%a5" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><ul> <li>检查与HTTP相关的第三方依赖和私有依赖,是否已经有支持Jakarta的版本,没有则需要克隆源码自行修改后发布到私有仓库。</li> <li>检查项目中是否使用了Oracle相关的代码库,删除或使用其他开源库替代。</li> </ul> <h2 class="heading-element" id="升级依赖"><span>升级依赖</span> <a href="#%e5%8d%87%e7%ba%a7%e4%be%9d%e8%b5%96" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><h3 class="heading-element" id="修改版本控制"><span>修改版本控制</span> <a href="#%e4%bf%ae%e6%94%b9%e7%89%88%e6%9c%ac%e6%8e%a7%e5%88%b6" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>修改pom中的 parent 为 <code>spring-boot-starter-parent</code>,将大部分依赖版本号管理委托至 spring boot, 降低不同版本不兼容风险,例如:</p> <pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nt">&lt;parent&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;groupId&gt;</span>org.springframework.boot<span class="nt">&lt;/groupId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;artifactId&gt;</span>spring-boot-starter-parent<span class="nt">&lt;/artifactId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;version&gt;</span>3.5.8<span class="nt">&lt;/version&gt;</span> </span></span><span class="line"><span class="cl"><span class="nt">&lt;/parent&gt;</span></span></span></code></pre><p>添加版本控制后,需要将旧版本依赖的版本号全部删除,执行 <code>maven&ensp;dependency:resolve</code> 查看哪些依赖版本号缺失, 并添加缺失的依赖版本号。</p> <h3 class="heading-element" id="替换-spring-boot-starter-系列"><span>替换 spring-boot-starter 系列</span> <a href="#%e6%9b%bf%e6%8d%a2-spring-boot-starter-%e7%b3%bb%e5%88%97" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>一些依赖组件提供了原生的 spring-boot-starter,最好直接使用starter依赖替换旧的版本管理,降低迁移成本,例如:</p> <ul> <li>spring-boot-starter-web</li> <li>spring-boot-starter-test</li> <li>spring-boot-starter-validation</li> <li>mybatis-spring-boot-starter</li> <li>其他的 starter 可以在官网查看</li> </ul> <h3 class="heading-element" id="排除重复依赖"><span>排除重复依赖</span> <a href="#%e6%8e%92%e9%99%a4%e9%87%8d%e5%a4%8d%e4%be%9d%e8%b5%96" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>有一些无法升级或老旧的第三方包,可能兼容Java21,但自身会带来旧版本Spring或其他的依赖,此时使用命令 <code>mvn&ensp;dependency:tree&ensp;-Dverbose</code>检查依赖传递情况,找到重复依赖并排除,例如下面需要排除 commons-fileupload,转而使用 新版本 fileupload2:</p> <pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nt">&lt;dependencyManagement&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;dependency&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;groupId&gt;</span>com.bstek.ureport<span class="nt">&lt;/groupId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;artifactId&gt;</span>ureport2-console<span class="nt">&lt;/artifactId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;version&gt;</span>${ureport.version}<span class="nt">&lt;/version&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;exclusions&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;exclusion&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;groupId&gt;</span>commons-fileupload<span class="nt">&lt;/groupId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;artifactId&gt;</span>commons-fileupload<span class="nt">&lt;/artifactId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/exclusion&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/exclusions&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/dependency&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;dependency&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;groupId&gt;</span>org.apache.commons<span class="nt">&lt;/groupId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;artifactId&gt;</span>commons-fileupload2-jakarta-servlet6<span class="nt">&lt;/artifactId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;version&gt;</span>${commons-fileupload.version}<span class="nt">&lt;/version&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/dependency&gt;</span> </span></span><span class="line"><span class="cl"><span class="nt">&lt;/dependencyManagement&gt;</span></span></span></code></pre><h3 class="heading-element" id="定制化停止更新的依赖"><span>定制化停止更新的依赖</span> <a href="#%e5%ae%9a%e5%88%b6%e5%8c%96%e5%81%9c%e6%ad%a2%e6%9b%b4%e6%96%b0%e7%9a%84%e4%be%9d%e8%b5%96" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>一些老旧的依赖可能在发布 Jakarta 前就已停更,此时需要获取到源码工程,修改源码兼容Java21和Spring Boot 3.5,并发布到私有仓库。 例如本次迁移中项目中使用Ureport2已经停更,且不支持Java21 Jakarta,修改源码大致步骤:</p> <ul> <li>Ureport源码中添加 spring-boot parent,删除由spring-boot管理的版本号。</li> <li>修改或升级Ureport中的三方依赖。</li> <li>修改源码以兼容新版的 Jakarta命名空间,操作同后续内容中的项目源码修改</li> </ul> <h3 class="heading-element" id="升级-maven-插件"><span>升级 maven 插件</span> <a href="#%e5%8d%87%e7%ba%a7-maven-%e6%8f%92%e4%bb%b6" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>一些maven插件在Java21环境下也需要升级,可以一并升级到最新版本,这个一般不会有兼容性问题。查看具体的版本传递可以使用插件</p> <pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nt">&lt;plugin&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;groupId&gt;</span>org.codehaus.mojo<span class="nt">&lt;/groupId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;artifactId&gt;</span>flatten-maven-plugin<span class="nt">&lt;/artifactId&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;version&gt;</span>1.7.3<span class="nt">&lt;/version&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;configuration&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/configuration&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;executions&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c">&lt;!--&ensp;enable&ensp;flattening&ensp;--&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;execution&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;id&gt;</span>flatten<span class="nt">&lt;/id&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;phase&gt;</span>process-resources<span class="nt">&lt;/phase&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;goals&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;goal&gt;</span>flatten<span class="nt">&lt;/goal&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/goals&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/execution&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c">&lt;!--&ensp;ensure&ensp;proper&ensp;cleanup&ensp;--&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;execution&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;id&gt;</span>flatten.clean<span class="nt">&lt;/id&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;goals&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;goal&gt;</span>clean<span class="nt">&lt;/goal&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/goals&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/execution&gt;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="nt">&lt;/executions&gt;</span> </span></span><span class="line"><span class="cl"><span class="nt">&lt;/plugin&gt;</span></span></span></code></pre><h2 class="heading-element" id="项目代码适配"><span>项目代码适配</span> <a href="#%e9%a1%b9%e7%9b%ae%e4%bb%a3%e7%a0%81%e9%80%82%e9%85%8d" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><h3 class="heading-element" id="javax-迁移-jakarta-命名空间"><span>javax 迁移 Jakarta 命名空间</span> <a href="#javax-%e8%bf%81%e7%a7%bb-jakarta-%e5%91%bd%e5%90%8d%e7%a9%ba%e9%97%b4" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>使用IDEA自带工具批量替换 <code>javax</code> 命名空间为 <code>jakarta</code>,菜单位于 <code>Refactoring&ensp;-&gt;&ensp;Migrate&ensp;Packages&ensp;and&ensp;Classes&ensp;-&gt;&ensp;Java&ensp;EE&ensp;to&ensp;Jakarta&ensp;EE</code>,本质上是替换代码文件中的字符串,可以新建自己的规则 批量替换其他命名空间。</p> <h3 class="heading-element" id="迁移-spring-xml-配置为代码配置方式"><span>迁移 spring xml 配置为代码配置方式</span> <a href="#%e8%bf%81%e7%a7%bb-spring-xml-%e9%85%8d%e7%bd%ae%e4%b8%ba%e4%bb%a3%e7%a0%81%e9%85%8d%e7%bd%ae%e6%96%b9%e5%bc%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>旧项目使用了spring xml 配置,需要将配置文件迁移为代码配置方式,并使用 <code>@Configuration</code> 注解声明为配置类,这个需要按项目 具体需求进行修改,注意最好不要使用xml与代码混合使用,建议全部迁移为代码配置方式。</p> <h3 class="heading-element" id="旧配置文件适配-spring-boot-3"><span>旧配置文件适配 spring boot 3</span> <a href="#%e6%97%a7%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e9%80%82%e9%85%8d-spring-boot-3" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>项目中配置文件为多个<code>properties</code>文件,使用springboot3中新引入的配置文件导入,由spring合并配置,例如在<code>application.yaml</code>中 引入旧项目配置文件<code>base.properties</code>、<code>biz.properties</code>等:</p> <pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">spring</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">config</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">import</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">classpath:base.properties</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">classpath:biz.properties</span></span></span></code></pre><p>项目中如果使用了自定义的配置读取类,需要将配置文件注入到Spring Environment中,例如:</p> <pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w">&ensp;</span><span class="kd">class</span>&ensp;<span class="nc">MyPropertySourcePostProcessor</span><span class="w">&ensp;</span><span class="kd">implements</span><span class="w">&ensp;</span><span class="n">EnvironmentPostProcessor</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kd">static</span><span class="w">&ensp;</span><span class="n">MapPropertySource</span><span class="w">&ensp;</span><span class="nf">mergeMyPropertySource</span><span class="p">()</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">Properties</span><span class="w">&ensp;</span><span class="n">properties</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">Global</span><span class="p">.</span><span class="na">PROPERTIES_LOADER</span><span class="p">.</span><span class="na">getProperties</span><span class="p">();</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">Object</span><span class="o">&gt;</span><span class="w">&ensp;</span><span class="n">map</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="k">new</span><span class="w">&ensp;</span><span class="n">HashMap</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">properties</span><span class="p">.</span><span class="na">forEach</span><span class="p">((</span><span class="n">k</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">v</span><span class="p">)</span><span class="w">&ensp;</span><span class="o">-&gt;</span><span class="w">&ensp;</span><span class="n">map</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">k</span><span class="p">.</span><span class="na">toString</span><span class="p">(),</span><span class="w">&ensp;</span><span class="n">Global</span><span class="p">.</span><span class="na">getConfig</span><span class="p">(</span><span class="n">k</span><span class="p">.</span><span class="na">toString</span><span class="p">())));</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">MapPropertySource</span><span class="w">&ensp;</span><span class="n">source</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="k">new</span><span class="w">&ensp;</span><span class="n">MapPropertySource</span><span class="p">(</span><span class="s">&#34;myProperties&#34;</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">map</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">source</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nd">@Override</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">public</span><span class="w">&ensp;</span><span class="kt">void</span><span class="w">&ensp;</span><span class="nf">postProcessEnvironment</span><span class="p">(</span><span class="n">ConfigurableEnvironment</span><span class="w">&ensp;</span><span class="n">environment</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">SpringApplication</span><span class="w">&ensp;</span><span class="n">application</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">environment</span><span class="p">.</span><span class="na">getPropertySources</span><span class="p">()</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">.</span><span class="na">addFirst</span><span class="p">(</span><span class="n">mergeMyPropertySource</span><span class="p">());</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="编译测试"><span>编译测试</span> <a href="#%e7%bc%96%e8%af%91%e6%b5%8b%e8%af%95" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>完成迁移后,需要编译测试项目,确保项目正常启动,并检查是否有兼容性问题。具体而言要完成回归测试、集成测试和性能测试, 同时部署后进行渗透漏洞扫描,确保当前依赖下无重大安全隐患。</p> 一次JVM堆外内存问题排查 https://ingbyr.github.io/posts/jvm-native-memory-leak/ Thu, 14 Mar 2024 10:24:03 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/jvm-native-memory-leak/ Java <p>记录一下JVM堆外内存泄露排查的过程</p> <h2 class="heading-element" id="出现的问题"><span>出现的问题</span> <a href="#%e5%87%ba%e7%8e%b0%e7%9a%84%e9%97%ae%e9%a2%98" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>线上运行的Java应用在持续运行数小时后会因堆外内存不足而终止,查看日志可以看到类似输出: <img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/hs-error-log.png' alt="/posts/jvm-native-memory-leak/hs-error-log.png" height="1618" width="2209"></p> <p>先尝试了使用手动释放cached memory,发现还有大量内存未释放,基本排除了操作系统内存释放策略配置错误的问题</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/release-cached-memory.png' alt="/posts/jvm-native-memory-leak/release-cached-memory.png" height="279" width="1460"></p> <h2 class="heading-element" id="开启jvm堆外内存追踪"><span>开启JVM堆外内存追踪</span> <a href="#%e5%bc%80%e5%90%afjvm%e5%a0%86%e5%a4%96%e5%86%85%e5%ad%98%e8%bf%bd%e8%b8%aa" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>在启动Java应用的参数中添加 <code>-XX:NativeMemoryTracking=detail</code> ,重启应用后运行一段时间,使用 <code>jcmd&ensp;$pid&ensp;VM.native_memory&ensp;summary</code> 查看内存分配情况,可以看到类似输出</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/jcmd-native-memory-sumarry.png' alt="/posts/jvm-native-memory-leak/jcmd-native-memory-sumarry.png" height="1820" width="1354"></p> <p>与 top 命令输出的 RSS 比对发现远小于其值,此时基本可以确定是 JNI 调用 Native Code 导致的堆外内存泄露</p> <h2 class="heading-element" id="查看未释放的堆外内存内容"><span>查看未释放的堆外内存内容</span> <a href="#%e6%9f%a5%e7%9c%8b%e6%9c%aa%e9%87%8a%e6%94%be%e7%9a%84%e5%a0%86%e5%a4%96%e5%86%85%e5%ad%98%e5%86%85%e5%ae%b9" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><ol> <li>先使用 <code>pmp&ensp;-x&ensp;$pid</code> 查看内存分布情况,对比前后两次的内容发现一直会申请一些64MB的内存块,并且始终处于未释放状态</li> <li>查看 <code>/proc/$pid/smaps</code> 或 <code>/proc/$pid/maps</code> 找到对应内存起始和终止地址</li> <li>使用 <code>gdb&ensp;-pid&ensp;$pid</code> attach 到问题进程, <code>dump&ensp;memory&ensp;mem.bin&ensp;起始地址&ensp;终止地址</code> dump 出对应的多块内存块。</li> <li>由于此次Java应用中存在中文字符,因此使用 <code>strings&ensp;-eS&ensp;mem.bin</code> 查看可显示的字符内容</li> </ol> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/strings-memory.png' alt="/posts/jvm-native-memory-leak/strings-memory.png" height="831" width="2073"></p> <p>经查看多个内存块后发现出现频率高的字符串没有明显规律,需要进一步排查</p> <h2 class="heading-element" id="监控内存分配"><span>监控内存分配</span> <a href="#%e7%9b%91%e6%8e%a7%e5%86%85%e5%ad%98%e5%88%86%e9%85%8d" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>本次使用 <a href="https://github.com/jemalloc/jemalloc"target="_blank" rel="external nofollow noopener noreferrer">Jemalloc</a> 分析应用内存分配情况,首先在应用启动环境添加</p> <pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span>&ensp;<span class="nv">LD_PRELOAD</span><span class="o">=</span>/usr/local/lib/libjemalloc.so </span></span><span class="line"><span class="cl"><span class="nb">export</span>&ensp;<span class="nv">MALLOC_CONF</span><span class="o">=</span>prof:true,lg_prof_interval:31,prof_prefix:/root/jeprof-result/app</span></span></code></pre><p>重启应用后等待 Jemalloc 输出内存采样文件,查看多个采样文件后发现端倪</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/jeprof-heap.png' alt="/posts/jvm-native-memory-leak/jeprof-heap.png" height="684" width="1630"></p> <p>可以看到 <code>524336&ensp;&ensp;&ensp;0.1%&ensp;100.0%&ensp;&ensp;7386790&ensp;&ensp;&ensp;0.8%&ensp;Java_java_util_zip_Inflater_init</code> JNI调用</p> <h2 class="heading-element" id="定位问题代码"><span>定位问题代码</span> <a href="#%e5%ae%9a%e4%bd%8d%e9%97%ae%e9%a2%98%e4%bb%a3%e7%a0%81" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>使用 <code>jstack&ensp;$pid&ensp;|&ensp;grep&ensp;Inflater</code> 查找调用栈(可能需要多次)</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/jstack-inflater.png' alt="/posts/jvm-native-memory-leak/jstack-inflater.png" height="702" width="1783"></p> <p>发现在 Redis 序列化与反序列时使用了 JDK 中的 ZLIB 压缩算法,查看源码可以看到未调用 <code>stream.close()</code> <code>infalter.end()</code> 和 <code>defalter.end()</code>方法</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/wrong-java-code.png' alt="/posts/jvm-native-memory-leak/wrong-java-code.png" height="1434" width="2047"></p> <p>顺便确认下 native code 调用</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/infalter-java-code.png' alt="/posts/jvm-native-memory-leak/infalter-java-code.png" height="1616" width="1564"></p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/infalter-java-code-2.png' alt="/posts/jvm-native-memory-leak/infalter-java-code-2.png" height="171" width="1452"></p> <h2 class="heading-element" id="修改问题代码"><span>修改问题代码</span> <a href="#%e4%bf%ae%e6%94%b9%e9%97%ae%e9%a2%98%e4%bb%a3%e7%a0%81" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>直接看代码</p> <p><img loading="lazy" src='https://ingbyr.github.io/posts/jvm-native-memory-leak/right-code.png' alt="/posts/jvm-native-memory-leak/right-code.png" height="1718" width="2022"></p> ELK分布式日志收集 https://ingbyr.github.io/posts/elk%E5%88%86%E5%B8%83%E5%BC%8F%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86/ Sat, 07 Oct 2023 14:45:11 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/elk%E5%88%86%E5%B8%83%E5%BC%8F%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86/ 分布式系统 <h2 class="heading-element" id="elk-架构"><span>ELK 架构</span> <a href="#elk-%e6%9e%b6%e6%9e%84" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p><a href="https://www.elastic.co/guide/index.html"target="_blank" rel="external nofollow noopener noreferrer">文档</a></p> <pre class="mermaid">flowchart&ensp;LR &ensp;&ensp;&ensp;&ensp;subgraph&ensp;server-1 &ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;log-file-1&ensp;-->&ensp;filebeat-1 &ensp;&ensp;&ensp;&ensp;end &ensp;&ensp;&ensp;&ensp;subgraph&ensp;server-2 &ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;log-file-2&ensp;-->&ensp;filebeat-2 &ensp;&ensp;&ensp;&ensp;end &ensp;&ensp;&ensp;&ensp;filebeat-1&ensp;--&ensp;push&ensp;log&ensp;-->&ensp;kafka &ensp;&ensp;&ensp;&ensp;filebeat-2&ensp;--&ensp;push&ensp;log&ensp;-->&ensp;kafka &ensp;&ensp;&ensp;&ensp;kafka&ensp;--&ensp;sub&ensp;log&ensp;-->&ensp;logstash-filter &ensp;&ensp;&ensp;&ensp;logstash-filter&ensp;--&ensp;pub&ensp;log&ensp;-->&ensp;kafka &ensp;&ensp;&ensp;&ensp;kafka&ensp;--&ensp;sub&ensp;log&ensp;-->&ensp;logstash &ensp;&ensp;&ensp;&ensp;logstash&ensp;--&ensp;push&ensp;-->&ensp;es &ensp;&ensp;&ensp;&ensp;kibana&ensp;--&ensp;query&ensp;-->&ensp;es</pre></div><h2 class="heading-element" id="配置es"><span>配置ES</span> <a href="#%e9%85%8d%e7%bd%aees" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>修改文件<code>config/elasticsearch.yml</code></p> <ul> <li>path.data</li> <li>path.logs</li> <li>network.host</li> <li>http.port</li> </ul> <p>生成相应账户密码</p> <ul> <li><code>./bin/elasticsearch-reset-password&ensp;-u&ensp;elastic</code></li> <li><code>./bin/elasticsearch-reset-password&ensp;-u&ensp;kibana-system</code></li> </ul> <h2 class="heading-element" id="配置kibana"><span>配置Kibana</span> <a href="#%e9%85%8d%e7%bd%aekibana" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><ul> <li>server.port</li> <li>server.host</li> <li>elasticsearch.username</li> <li>elasticsearch.password</li> <li>i18n.locale</li> </ul> <h2 class="heading-element" id="配置kafka"><span>配置Kafka</span> <a href="#%e9%85%8d%e7%bd%aekafka" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>新建 <code>config/kafka_server_jass.conf</code></p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">KafkaServer&ensp;{ </span></span><span class="line"><span class="cl">&ensp;&ensp;org.apache.kafka.common.security.plain.PlainLoginModule&ensp;required </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;username=&#34;admin&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;password=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_admin=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_tom=&#34;tom-password&#34;; </span></span><span class="line"><span class="cl">}; </span></span><span class="line"><span class="cl">KafkaClient&ensp;{ </span></span><span class="line"><span class="cl">&ensp;&ensp;org.apache.kafka.common.security.plain.PlainLoginModule&ensp;required </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;username=&#34;admin&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;password=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_admin=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_tom=&#34;tom-password&#34;; </span></span><span class="line"><span class="cl">}; </span></span><span class="line"><span class="cl">Client&ensp;{ </span></span><span class="line"><span class="cl">&ensp;&ensp;org.apache.kafka.common.security.plain.PlainLoginModule&ensp;required </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;username=&#34;admin&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;password=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_admin=&#34;admin-password&#34;; </span></span><span class="line"><span class="cl">}; </span></span><span class="line"><span class="cl">Server&ensp;{ </span></span><span class="line"><span class="cl">&ensp;&ensp;org.apache.kafka.common.security.plain.PlainLoginModule&ensp;required </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;username=&#34;admin&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;password=&#34;admin-password&#34; </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;user_admin=&#34;admin-password&#34;; </span></span><span class="line"><span class="cl">};</span></span></code></pre><p>修改 <code>bin/kafka-server-start.sh</code>, 最后一行前添加 <code>export&ensp;KAFKA_OPTS=&quot;-Djava.security.auth.login.config=$base_dir/../config/kafka_server_jaas.conf&quot;</code></p> <p>新建 <code>config/tom-client.conf</code></p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule&ensp;\ </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;required&ensp;username=&#34;tom&#34;&ensp;password=&#34;tom-password&#34;; </span></span><span class="line"><span class="cl">security.protocol=SASL_PLAINTEXT </span></span><span class="line"><span class="cl">sasl.mechanism=PLAIN</span></span></code></pre><p>测试执行命令 <code>./bin/kafka-topics.sh&ensp;--bootstrap-server&ensp;ip:port&ensp;--command-config&ensp;config/tom-client.conf&ensp;--list</code></p> 算法基础-前缀树 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%89%8D%E7%BC%80%E6%A0%91/ Tue, 15 Mar 2022 10:53:07 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%89%8D%E7%BC%80%E6%A0%91/ 算法 <p>字符串前缀相关操作</p> <h2 class="heading-element" id="实现"><span>实现</span> <a href="#%e5%ae%9e%e7%8e%b0" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span>&ensp;<span class="nx">main</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">TrieNode</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">isWord</span>&ensp;&ensp;&ensp;<span class="kt">bool</span> </span></span><span class="line"><span class="cl"> <span class="nx">children</span>&ensp;<span class="p">[]</span><span class="o">*</span><span class="nx">TrieNode</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewTrieNode</span><span class="p">()</span>&ensp;<span class="o">*</span><span class="nx">TrieNode</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">&amp;</span><span class="nx">TrieNode</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">isWord</span><span class="p">:</span>&ensp;&ensp;&ensp;<span class="kc">false</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">children</span><span class="p">:</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span>&ensp;<span class="mi">26</span><span class="p">),</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">Trie</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">root</span>&ensp;<span class="o">*</span><span class="nx">TrieNode</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewTrie</span><span class="p">()</span>&ensp;<span class="nx">Trie</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">Trie</span><span class="p">{</span><span class="nf">NewTrieNode</span><span class="p">()}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">t</span>&ensp;<span class="o">*</span><span class="nx">Trie</span><span class="p">)</span>&ensp;<span class="nf">Insert</span><span class="p">(</span><span class="nx">word</span>&ensp;<span class="kt">string</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">t</span><span class="p">.</span><span class="nx">root</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">word</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">idx</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">int</span><span class="p">(</span><span class="nx">word</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="o">-</span>&ensp;<span class="sc">&#39;a&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">node</span><span class="p">.</span><span class="nx">children</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>&ensp;<span class="o">==</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span><span class="p">.</span><span class="nx">children</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nf">NewTrieNode</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">node</span><span class="p">.</span><span class="nx">children</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span><span class="p">.</span><span class="nx">isWord</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">t</span>&ensp;<span class="o">*</span><span class="nx">Trie</span><span class="p">)</span>&ensp;<span class="nf">Search</span><span class="p">(</span><span class="nx">word</span>&ensp;<span class="kt">string</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">t</span><span class="p">.</span><span class="nf">GetNode</span><span class="p">(</span><span class="nx">word</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">node</span>&ensp;<span class="o">==</span>&ensp;<span class="kc">nil</span>&ensp;<span class="o">||</span>&ensp;<span class="p">!</span><span class="nx">node</span><span class="p">.</span><span class="nx">isWord</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="kc">false</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">t</span>&ensp;<span class="o">*</span><span class="nx">Trie</span><span class="p">)</span>&ensp;<span class="nf">StartsWith</span><span class="p">(</span><span class="nx">prefix</span>&ensp;<span class="kt">string</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">t</span><span class="p">.</span><span class="nf">GetNode</span><span class="p">(</span><span class="nx">prefix</span><span class="p">)</span>&ensp;<span class="o">!=</span>&ensp;<span class="kc">nil</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">t</span>&ensp;<span class="o">*</span><span class="nx">Trie</span><span class="p">)</span>&ensp;<span class="nf">GetNode</span><span class="p">(</span><span class="nx">word</span>&ensp;<span class="kt">string</span><span class="p">)</span>&ensp;<span class="o">*</span><span class="nx">TrieNode</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">t</span><span class="p">.</span><span class="nx">root</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">word</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">idx</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">int</span><span class="p">(</span><span class="nx">word</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="o">-</span>&ensp;<span class="sc">&#39;a&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">node</span><span class="p">.</span><span class="nx">children</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">child</span>&ensp;<span class="o">==</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="kc">nil</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">child</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">node</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">t</span>&ensp;<span class="o">*</span><span class="nx">Trie</span><span class="p">)</span>&ensp;<span class="nf">Scan</span><span class="p">(</span><span class="nx">prefix</span>&ensp;<span class="kt">string</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">string</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">t</span><span class="p">.</span><span class="nf">GetNode</span><span class="p">(</span><span class="nx">prefix</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">string</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">node</span>&ensp;<span class="o">==</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span>&ensp;<span class="nx">dfs</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">node</span>&ensp;<span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span>&ensp;<span class="nx">path</span>&ensp;<span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">dfs</span>&ensp;<span class="p">=</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">node</span>&ensp;<span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span>&ensp;<span class="nx">path</span>&ensp;<span class="p">[]</span><span class="kt">byte</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">node</span>&ensp;<span class="o">==</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">node</span><span class="p">.</span><span class="nx">isWord</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">prefix</span><span class="o">+</span><span class="nb">string</span><span class="p">(</span><span class="nx">path</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="mi">26</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">node</span><span class="p">.</span><span class="nx">children</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">child</span>&ensp;<span class="o">!=</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">path</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span>&ensp;<span class="nb">byte</span><span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="sc">&#39;a&#39;</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="nf">dfs</span><span class="p">(</span><span class="nx">child</span><span class="p">,</span>&ensp;<span class="nx">path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">path</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">path</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="nx">path</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nf">dfs</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span>&ensp;<span class="p">[]</span><span class="kt">byte</span><span class="p">{})</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> 算法基础-最小生成树 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/ Thu, 10 Mar 2022 14:42:47 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/ 算法 <p>由图生成权重最小的树</p> <p>给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。</p> <p>连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。</p> <p>请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。</p> <blockquote> <p>来源:力扣(LeetCode)</p> <p>链接:https://leetcode-cn.com/problems/min-cost-to-connect-all-points</p> <p>著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。</p></blockquote> <h2 class="heading-element" id="kruskal"><span>Kruskal</span> <a href="#kruskal" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>所有边按权重排序,使用并查集选出不成环的边</p> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewUF</span><span class="p">(</span><span class="nx">n</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">parent</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">i</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">&amp;</span><span class="nx">UnionFind</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span><span class="p">:</span>&ensp;<span class="nx">parent</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">count</span><span class="p">:</span>&ensp;&ensp;<span class="nx">n</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">UnionFind</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span>&ensp;<span class="p">[]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"> <span class="nx">count</span>&ensp;&ensp;<span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Union</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootA</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootB</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">rootA</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">rootB</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">rootA</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">rootB</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">count</span><span class="o">--</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Find</span><span class="p">(</span><span class="nx">a</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="o">!=</span>&ensp;<span class="nx">a</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]]</span> </span></span><span class="line"><span class="cl"> <span class="nx">a</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">a</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Connected</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootA</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootB</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">rootA</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">rootB</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">minCostConnectPoints</span><span class="p">(</span><span class="nx">points</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">n</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">points</span><span class="p">)</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;graph&ensp;[from,&ensp;to,&ensp;weight]</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([][]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">+</span>&ensp;<span class="mi">1</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">j</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">edge</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">,</span>&ensp;<span class="nf">dist</span><span class="p">(</span><span class="nx">points</span><span class="p">,</span>&ensp;<span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">)}</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">graph</span><span class="p">,</span>&ensp;<span class="nx">edge</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">sort</span><span class="p">.</span><span class="nf">Slice</span><span class="p">(</span><span class="nx">graph</span><span class="p">,</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">graph</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">graph</span><span class="p">[</span><span class="nx">j</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span>&ensp;<span class="o">:=</span>&ensp;<span class="nf">NewUF</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">edge</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">graph</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span><span class="p">,</span>&ensp;<span class="nx">w</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>&ensp;<span class="nx">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>&ensp;<span class="nx">edge</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Connected</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">continue</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nf">Union</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">+=</span>&ensp;<span class="nx">w</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">a</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">a</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">a</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">-</span><span class="nx">a</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">dist</span><span class="p">(</span><span class="nx">points</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">points</span><span class="p">[</span><span class="nx">a</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="nx">points</span><span class="p">[</span><span class="nx">b</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>&ensp;<span class="o">+</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">points</span><span class="p">[</span><span class="nx">a</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="nx">points</span><span class="p">[</span><span class="nx">b</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="prim"><span>Prim</span> <a href="#prim" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>图中每次切分,至少包含一条最小生成树的边(即权重最小的边必为最小生成树路径)</p> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">a</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">a</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">a</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">-</span><span class="nx">a</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">dist</span><span class="p">(</span><span class="nx">points</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">points</span><span class="p">[</span><span class="nx">a</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="nx">points</span><span class="p">[</span><span class="nx">b</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>&ensp;<span class="o">+</span>&ensp;<span class="nf">abs</span><span class="p">(</span><span class="nx">points</span><span class="p">[</span><span class="nx">a</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="nx">points</span><span class="p">[</span><span class="nx">b</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">PriorityQueue</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">data</span>&ensp;<span class="p">[][]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">p</span>&ensp;<span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span>&ensp;<span class="nf">Len</span><span class="p">()</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">p</span>&ensp;<span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span>&ensp;<span class="nf">Less</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">j</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">p</span>&ensp;<span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span>&ensp;<span class="nf">Swap</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">j</span><span class="p">],</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">p</span>&ensp;<span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span>&ensp;<span class="nf">Push</span><span class="p">(</span><span class="nx">x</span>&ensp;<span class="kd">interface</span><span class="p">{})</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">p</span><span class="p">.</span><span class="nx">data</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>&ensp;<span class="nx">x</span><span class="p">.([]</span><span class="kt">int</span><span class="p">))</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">p</span>&ensp;<span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span>&ensp;<span class="nf">Pop</span><span class="p">()</span>&ensp;<span class="kd">interface</span><span class="p">{}</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">p</span><span class="p">.</span><span class="nx">data</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">minCostConnectPoints</span><span class="p">(</span><span class="nx">points</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">n</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">points</span><span class="p">)</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;graph[from]&ensp;[to,&ensp;weight]</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([][][]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;邻接表表示的无向图,需要双向赋值</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">j</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">continue</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">graph</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="nx">j</span><span class="p">,</span>&ensp;<span class="nf">dist</span><span class="p">(</span><span class="nx">points</span><span class="p">,</span>&ensp;<span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">)})</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">used</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">pq</span>&ensp;<span class="o">:=</span>&ensp;<span class="o">&amp;</span><span class="nx">PriorityQueue</span><span class="p">{[][]</span><span class="kt">int</span><span class="p">{}}</span> </span></span><span class="line"><span class="cl"> <span class="nx">cut</span>&ensp;<span class="o">:=</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">a</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">edge</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">graph</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">used</span><span class="p">[</span><span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">continue</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">heap</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="nx">pq</span><span class="p">,</span>&ensp;<span class="nx">edge</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">used</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nf">cut</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">w</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">pq</span><span class="p">.</span><span class="nf">Len</span><span class="p">()</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">edge</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">heap</span><span class="p">.</span><span class="nf">Pop</span><span class="p">(</span><span class="nx">pq</span><span class="p">).([]</span><span class="kt">int</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">used</span><span class="p">[</span><span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">continue</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">w</span>&ensp;<span class="o">+=</span>&ensp;<span class="nx">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">used</span><span class="p">[</span><span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nf">cut</span><span class="p">(</span><span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">w</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> 算法基础-二分图 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E4%BA%8C%E5%88%86%E5%9B%BE/ Tue, 08 Mar 2022 17:42:32 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E4%BA%8C%E5%88%86%E5%9B%BE/ 算法 <p>用于将节点分为两组</p> <h2 class="heading-element" id="判断是否为二分图"><span>判断是否为二分图</span> <a href="#%e5%88%a4%e6%96%ad%e6%98%af%e5%90%a6%e4%b8%ba%e4%ba%8c%e5%88%86%e5%9b%be" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><h3 class="heading-element" id="bfs-实现"><span>BFS 实现</span> <a href="#bfs-%e5%ae%9e%e7%8e%b0" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">isBipartite</span><span class="p">(</span><span class="nx">graph</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">n</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">graph</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">visited</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">color</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">valid</span>&ensp;<span class="o">:=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">var</span>&ensp;<span class="nx">bfs</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">bfs</span>&ensp;<span class="p">=</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">root</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">visited</span><span class="p">[</span><span class="nx">root</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nx">queue</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="nx">root</span><span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">queue</span><span class="p">)</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">node</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">queue</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">queue</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">queue</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">next</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">graph</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="p">!</span><span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">visited</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nx">queue</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span>&ensp;<span class="nx">next</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span>&ensp;<span class="k">else</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">valid</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">false</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">valid</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nf">bfs</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">valid</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h3 class="heading-element" id="dfs-实现"><span>DFS 实现</span> <a href="#dfs-%e5%ae%9e%e7%8e%b0" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">possibleBipartition</span><span class="p">(</span><span class="nx">n</span>&ensp;<span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">dislikes</span>&ensp;<span class="p">[][]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([][]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">dislike</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">dislikes</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">dislike</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>&ensp;<span class="nx">dislike</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="mi">1</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">graph</span><span class="p">[</span><span class="nx">a</span><span class="p">],</span>&ensp;<span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">graph</span><span class="p">[</span><span class="nx">b</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">graph</span><span class="p">[</span><span class="nx">b</span><span class="p">],</span>&ensp;<span class="nx">a</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">valid</span>&ensp;<span class="o">:=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nx">visited</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">color</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span>&ensp;<span class="nx">dfs</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">node</span>&ensp;<span class="kt">int</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">dfs</span>&ensp;<span class="p">=</span>&ensp;<span class="kd">func</span><span class="p">(</span><span class="nx">node</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="p">!</span><span class="nx">valid</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">visited</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">next</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">graph</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="p">!</span><span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nf">dfs</span><span class="p">(</span><span class="nx">next</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span>&ensp;<span class="k">else</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">valid</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">false</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">valid</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nf">dfs</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">valid</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> 算法基础-并查集 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%B9%B6%E6%9F%A5%E9%9B%86/ Tue, 08 Mar 2022 17:38:39 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%B9%B6%E6%9F%A5%E9%9B%86/ 算法 <p>用于判断连通性、等效等问题</p> <h2 class="heading-element" id="实现"><span>实现</span> <a href="#%e5%ae%9e%e7%8e%b0" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewUF</span><span class="p">(</span><span class="nx">n</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">n</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">parent</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">i</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">&amp;</span><span class="nx">UnionFind</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span><span class="p">:</span>&ensp;<span class="nx">parent</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">count</span><span class="p">:</span>&ensp;&ensp;<span class="nx">n</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">UnionFind</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">parent</span>&ensp;<span class="p">[]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"> <span class="nx">count</span>&ensp;&ensp;<span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Union</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootA</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootB</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">rootA</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">rootB</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">rootA</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">rootB</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">count</span><span class="o">--</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Find</span><span class="p">(</span><span class="nx">a</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="o">!=</span>&ensp;<span class="nx">a</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;compress&ensp;parent&ensp;tree</span> </span></span><span class="line"><span class="cl"> <span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]]</span> </span></span><span class="line"><span class="cl"> <span class="nx">a</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nx">parent</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">a</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">uf</span>&ensp;<span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span>&ensp;<span class="nf">Connected</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span>&ensp;<span class="nx">b</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">bool</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootA</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">rootB</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">uf</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">rootA</span>&ensp;<span class="o">==</span>&ensp;<span class="nx">rootB</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> 算法基础-排序 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E6%8E%92%E5%BA%8F/ Fri, 10 Sep 2021 15:36:40 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E6%8E%92%E5%BA%8F/ 算法 <p>经典排序算法</p> <h2 class="heading-element" id="冒泡排序"><span>冒泡排序</span> <a href="#%e5%86%92%e6%b3%a1%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortBubble1</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">n</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;有序区间&ensp;[0,&ensp;i]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;从最右侧两两交换,将无序区间中的最小值放置到i</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">n</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">i</span><span class="p">;</span>&ensp;<span class="nx">j</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortBubble2</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">n</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">exchanged</span>&ensp;<span class="o">:=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;有序区间&ensp;[0,&ensp;i]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">n</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">exchanged</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;当&ensp;exchanged&ensp;为&ensp;true&ensp;时,表明剩余无序区间已有序,结束排序</span> </span></span><span class="line"><span class="cl"> <span class="nx">exchanged</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">false</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;从最右侧两两交换,将无序区间中的最小值放置到i</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">n</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">i</span><span class="p">;</span>&ensp;<span class="nx">j</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">exchanged</span>&ensp;<span class="p">=</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="快速排序"><span>快速排序</span> <a href="#%e5%bf%ab%e9%80%9f%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortQuick</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">left</span><span class="p">,</span>&ensp;<span class="nx">right</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">left</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">right</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">p</span>&ensp;<span class="o">:=</span>&ensp;<span class="nf">partition</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">left</span><span class="p">,</span>&ensp;<span class="nx">right</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">left</span><span class="p">,</span>&ensp;<span class="nx">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">p</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span>&ensp;<span class="nx">right</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">partition</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">l</span>&ensp;<span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">r</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;l位空出</span> </span></span><span class="line"><span class="cl"> <span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">l</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">r</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">l</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">r</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="nx">v</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">r</span><span class="o">--</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;r位保存至l位,r位空出</span> </span></span><span class="line"><span class="cl"> <span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">l</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">r</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span>&ensp;<span class="o">&lt;=</span>&ensp;<span class="nx">v</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">l</span><span class="o">++</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;l位保存至r位,l位空出</span> </span></span><span class="line"><span class="cl"> <span class="nx">arr</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;空出的l位填入基准值v</span> </span></span><span class="line"><span class="cl"> <span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">l</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> <pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;</span><span class="kd">class</span>&ensp;<span class="nc">Solution</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">public</span><span class="w">&ensp;</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="nf">sortArray</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">if</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">nums</span><span class="w">&ensp;</span><span class="o">==</span><span class="w">&ensp;</span><span class="kc">null</span><span class="w">&ensp;</span><span class="o">||</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w">&ensp;</span><span class="o">&lt;=</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">0</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kt">void</span><span class="w">&ensp;</span><span class="nf">quickSort</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">if</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">l</span><span class="w">&ensp;</span><span class="o">&gt;=</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">p</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">partition</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">p</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">p</span><span class="w">&ensp;</span><span class="o">+</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="nf">partition</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">v</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">randomPiv</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">l</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">l</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">r</span><span class="w">&ensp;</span><span class="o">&amp;&amp;</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">r</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">&gt;=</span><span class="w">&ensp;</span><span class="n">v</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">r</span><span class="o">--</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">r</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">l</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">r</span><span class="w">&ensp;</span><span class="o">&amp;&amp;</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">&lt;=</span><span class="w">&ensp;</span><span class="n">v</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">l</span><span class="o">++</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">r</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">v</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="nf">randomPiv</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">r</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">p</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">ThreadLocalRandom</span><span class="p">.</span><span class="na">current</span><span class="p">().</span><span class="na">nextInt</span><span class="p">(</span><span class="n">r</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">l</span><span class="w">&ensp;</span><span class="o">+</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">)</span><span class="w">&ensp;</span><span class="o">+</span><span class="w">&ensp;</span><span class="n">l</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">temp</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">temp</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">&ensp;&ensp;</span></span></span></code></pre><h2 class="heading-element" id="插入排序"><span>插入排序</span> <a href="#%e6%8f%92%e5%85%a5%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortInsert</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;有序区间&ensp;[0,&ensp;i],无序区间[i+1,&ensp;+00]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">1</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">i</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>&ensp;<span class="nx">j</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;小数前移</span> </span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">,</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="希尔排序插入排序改进版"><span>希尔排序(插入排序改进版)</span> <a href="#%e5%b8%8c%e5%b0%94%e6%8e%92%e5%ba%8f%e6%8f%92%e5%85%a5%e6%8e%92%e5%ba%8f%e6%94%b9%e8%bf%9b%e7%89%88" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><blockquote> <p>希尔为该算法发明人</p></blockquote> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortShell</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">step</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span><span class="p">;</span>&ensp;<span class="nx">step</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">step</span>&ensp;<span class="o">/=</span>&ensp;<span class="mi">2</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">step</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">i</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="nx">step</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="o">-</span><span class="nx">step</span><span class="p">];</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">-=</span>&ensp;<span class="nx">step</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;同组内小数前移</span> </span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="p">,</span>&ensp;<span class="nx">j</span><span class="o">-</span><span class="nx">step</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="选择排序"><span>选择排序</span> <a href="#%e9%80%89%e6%8b%a9%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortSelect</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">m</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">i</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;无序区间内选择最小值下标&ensp;m</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">i</span><span class="p">;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>&ensp;<span class="nx">j</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="nx">m</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">m</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">j</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">m</span>&ensp;<span class="o">!=</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span>&ensp;<span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">m</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="堆排序"><span>堆排序</span> <a href="#%e5%a0%86%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortHeap</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">MinHeap</span><span class="p">{}</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">build</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nf">pop</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">MinHeap</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">heap</span>&ensp;<span class="p">[]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1">//&ensp;上浮操作:节点与大于节点值的父节点交换</span> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">up</span><span class="p">(</span><span class="nx">k</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">==</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;节点&ensp;k&ensp;比&ensp;父节点&ensp;pk&ensp;小时,交换两节点,实现节点上浮</span> </span></span><span class="line"><span class="cl"> <span class="nx">pk</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nx">k</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="mi">0</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">]</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">k</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">pk</span> </span></span><span class="line"><span class="cl"> <span class="nx">pk</span>&ensp;<span class="p">=</span>&ensp;<span class="p">(</span><span class="nx">k</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1">//&ensp;下沉操作:节点与子节点中较小值交换</span> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">down</span><span class="p">(</span><span class="nx">k</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">&lt;=</span>&ensp;<span class="mi">1</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">lastNonLeaf</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">&lt;=</span>&ensp;<span class="nx">lastNonLeaf</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;默认左侧节点为子节点中值最小节点</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">2</span><span class="o">*</span><span class="nx">k</span>&ensp;<span class="o">+</span>&ensp;<span class="mi">1</span> </span></span><span class="line"><span class="cl"> <span class="nx">childV</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">]</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;检查右侧节点,若比默认节点小,替换之</span> </span></span><span class="line"><span class="cl"> <span class="nx">right</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">child</span>&ensp;<span class="o">+</span>&ensp;<span class="mi">1</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">right</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">right</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">childV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">right</span> </span></span><span class="line"><span class="cl"> <span class="nx">childV</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">right</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;若节点比子节点大,下沉</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">childV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">k</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">child</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span>&ensp;<span class="k">else</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">break</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1">//&ensp;添加操作:加至末尾节点,后上浮尾节点</span> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">add</span><span class="p">(</span><span class="nx">v</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">,</span>&ensp;<span class="nx">v</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">up</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1">//&ensp;弹出操作:头节点弹出,尾节点放置头节点,后下沉头节点</span> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">pop</span><span class="p">()</span>&ensp;<span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">==</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nb">panic</span><span class="p">(</span><span class="s">&#34;empty&ensp;heap&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;swap&ensp;last&ensp;and&ensp;first</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;remove&ensp;last</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;re-heap</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">down</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1">//&ensp;构建树:从最后一个非叶子节点开始,执行下沉操作</span> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">build</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">2</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">down</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="归并排序"><span>归并排序</span> <a href="#%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortMerge</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span>&ensp;<span class="o">&lt;=</span>&ensp;<span class="mi">1</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">mid</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nf">merge</span><span class="p">(</span><span class="nf">sortMerge</span><span class="p">(</span><span class="nx">arr</span><span class="p">[:</span><span class="nx">mid</span><span class="p">]),</span>&ensp;<span class="nf">sortMerge</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">mid</span><span class="p">:]))</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">merge</span><span class="p">(</span><span class="nx">left</span><span class="p">,</span>&ensp;<span class="nx">right</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">left</span><span class="p">)</span><span class="o">+</span><span class="nb">len</span><span class="p">(</span><span class="nx">right</span><span class="p">))</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;每次处理一个元素</span> </span></span><span class="line"><span class="cl"> <span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">j</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="mi">0</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">left</span><span class="p">)</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">right</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">left</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">right</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">left</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> <span class="nx">i</span><span class="o">++</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span>&ensp;<span class="k">else</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">right</span><span class="p">[</span><span class="nx">j</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> <span class="nx">j</span><span class="o">++</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">left</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">left</span><span class="p">[</span><span class="nx">i</span><span class="p">:]</span><span class="o">...</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">j</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">right</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">right</span><span class="p">[</span><span class="nx">j</span><span class="p">:]</span><span class="o">...</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> <pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span>&ensp;<span class="nc">Solution</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">public</span><span class="w">&ensp;</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="nf">sortArray</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">if</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">nums</span><span class="w">&ensp;</span><span class="o">==</span><span class="w">&ensp;</span><span class="kc">null</span><span class="w">&ensp;</span><span class="o">||</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w">&ensp;</span><span class="o">&lt;=</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">0</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="c1">//&ensp;[left,&ensp;right)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kt">void</span><span class="w">&ensp;</span><span class="nf">sort</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">if</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">right</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">left</span><span class="w">&ensp;</span><span class="o">&lt;=</span><span class="w">&ensp;</span><span class="n">1</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">return</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">mid</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">left</span><span class="w">&ensp;</span><span class="o">+</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">right</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">)</span><span class="w">&ensp;</span><span class="o">/</span><span class="w">&ensp;</span><span class="n">2</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">merge</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="kd">private</span><span class="w">&ensp;</span><span class="kt">void</span><span class="w">&ensp;</span><span class="nf">merge</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">,</span><span class="w">&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="o">[]</span><span class="w">&ensp;</span><span class="n">arr</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="k">new</span><span class="w">&ensp;</span><span class="kt">int</span><span class="o">[</span><span class="n">right</span><span class="w">&ensp;</span><span class="o">-</span><span class="w">&ensp;</span><span class="n">left</span><span class="o">]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">p</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">0</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="kt">int</span><span class="w">&ensp;</span><span class="n">i</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">j</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">i</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">mid</span><span class="w">&ensp;</span><span class="o">&amp;&amp;</span><span class="w">&ensp;</span><span class="n">j</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">if</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">nums</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">j</span><span class="o">]</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">i</span><span class="o">++]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w">&ensp;</span><span class="k">else</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">j</span><span class="o">++]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">p</span><span class="o">++</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">i</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">mid</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">++]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">i</span><span class="o">++]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="k">while</span><span class="w">&ensp;</span><span class="p">(</span><span class="n">j</span><span class="w">&ensp;</span><span class="o">&lt;</span><span class="w">&ensp;</span><span class="n">right</span><span class="p">)</span><span class="w">&ensp;</span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">++]</span><span class="w">&ensp;</span><span class="o">=</span><span class="w">&ensp;</span><span class="n">nums</span><span class="o">[</span><span class="n">j</span><span class="o">++]</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span><span class="n">System</span><span class="p">.</span><span class="na">arraycopy</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">0</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">nums</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">left</span><span class="p">,</span><span class="w">&ensp;</span><span class="n">right</span><span class="o">-</span><span class="n">left</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="计数排序"><span>计数排序</span> <a href="#%e8%ae%a1%e6%95%b0%e6%8e%92%e5%ba%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortCount</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;建立排序桶&ensp;[min,&ensp;max]</span> </span></span><span class="line"><span class="cl"> <span class="nx">minV</span><span class="p">,</span>&ensp;<span class="nx">maxV</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">arr</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">v</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">minV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">minV</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">v</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">maxV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">maxV</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">buckets</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="nx">maxV</span><span class="o">-</span><span class="nx">minV</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">arr</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;需要&ensp;min&ensp;偏移</span> </span></span><span class="line"><span class="cl"> <span class="nx">buckets</span><span class="p">[</span><span class="nx">v</span><span class="o">-</span><span class="nx">minV</span><span class="p">]</span><span class="o">++</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;桶中提取数据</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span><span class="p">,</span>&ensp;<span class="nx">count</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">buckets</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="p">;</span>&ensp;<span class="nx">count</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">count</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;加回偏移量&ensp;minV</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">i</span><span class="o">+</span><span class="nx">minV</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h2 class="heading-element" id="基数排序桶排序的一种"><span>基数排序(桶排序的一种)</span> <a href="#%e5%9f%ba%e6%95%b0%e6%8e%92%e5%ba%8f%e6%a1%b6%e6%8e%92%e5%ba%8f%e7%9a%84%e4%b8%80%e7%a7%8d" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><ul> <li>基数排序:根据键值的每位数字来分配桶</li> <li>计数排序:每个桶只存储单一键值</li> <li>桶排序:每个桶存储一定范围的数值,桶内使用其他排序算法</li> </ul> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">sortRadix</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">[]</span><span class="kt">int</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;默认&ensp;10&ensp;进制,故桶为&ensp;[0,&ensp;9]&ensp;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;最大值位数默认</span> </span></span><span class="line"><span class="cl"> <span class="nx">maxV</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">arr</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">v</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">maxV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">maxV</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">maxLen</span>&ensp;<span class="o">:=</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">strconv</span><span class="p">.</span><span class="nf">Itoa</span><span class="p">(</span><span class="nx">maxV</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;<span class="c1">//&ensp;按低位至高位排序</span> </span></span><span class="line"><span class="cl"> <span class="nx">step</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">1</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">maxLen</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span>&ensp;<span class="nx">buckets</span>&ensp;<span class="p">[</span><span class="mi">10</span><span class="p">][]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;插入排序桶</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">arr</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">bitV</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">/</span>&ensp;<span class="nx">step</span>&ensp;<span class="o">%</span>&ensp;<span class="mi">10</span> </span></span><span class="line"><span class="cl"> <span class="nx">buckets</span><span class="p">[</span><span class="nx">bitV</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">buckets</span><span class="p">[</span><span class="nx">bitV</span><span class="p">],</span>&ensp;<span class="nx">v</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="c1">//&ensp;更新数组</span> </span></span><span class="line"><span class="cl"> <span class="nx">idx</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">0</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">bucket</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">buckets</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">_</span><span class="p">,</span>&ensp;<span class="nx">v</span>&ensp;<span class="o">:=</span>&ensp;<span class="k">range</span>&ensp;<span class="nx">bucket</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">arr</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">v</span> </span></span><span class="line"><span class="cl"> <span class="nx">idx</span><span class="o">++</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">step</span>&ensp;<span class="o">*=</span>&ensp;<span class="mi">10</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre> Redis主从与集群模式 https://ingbyr.github.io/posts/redis%E4%B8%BB%E4%BB%8E%E4%B8%8E%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F/ Mon, 16 Aug 2021 09:55:00 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/redis%E4%B8%BB%E4%BB%8E%E4%B8%8E%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F/ 缓存 <p>Redis集群相关</p> <h2 class="heading-element" id="主从模式"><span>主从模式</span> <a href="#%e4%b8%bb%e4%bb%8e%e6%a8%a1%e5%bc%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>主节点Redis配置 <code>redis-6090.conf</code>:</p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port&ensp;6090 </span></span><span class="line"><span class="cl">protected-mode&ensp;no</span></span></code></pre><p>从节点Redis配置 <code>redis-6091.conf</code>:</p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port&ensp;6091 </span></span><span class="line"><span class="cl">protected-mode&ensp;no </span></span><span class="line"><span class="cl">slaveof&ensp;127.0.0.1&ensp;6090&ensp;</span></span></code></pre><p>从节点Redis配置 <code>redis-6092.conf</code>:</p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port&ensp;6092 </span></span><span class="line"><span class="cl">protected-mode&ensp;no </span></span><span class="line"><span class="cl">slaveof&ensp;127.0.0.1&ensp;6090&ensp;</span></span></code></pre><p>Redis Sentinel配置模版 <code>redis-sentinel-cluster.tmpl</code>:</p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port&ensp;${PORT} </span></span><span class="line"><span class="cl">sentinel&ensp;monitor&ensp;mymaster&ensp;127.0.0.1&ensp;6090&ensp;2 </span></span><span class="line"><span class="cl">sentinel&ensp;down-after-milliseconds&ensp;mymaster&ensp;5000 </span></span><span class="line"><span class="cl">sentinel&ensp;failover-timeout&ensp;mymaster&ensp;60000</span></span></code></pre><p>Redis Sentinel 实例的配置文件 <code>redis-sentinel-cluster-config.sh</code>,生成 5000-5002 3个实例:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/bash </span></span></span><span class="line"><span class="cl"><span class="cp"></span> </span></span><span class="line"><span class="cl"><span class="k">for</span>&ensp;port&ensp;in&ensp;<span class="sb">`</span>seq&ensp;<span class="m">5000</span>&ensp;5002<span class="sb">`</span><span class="p">;</span>&ensp;<span class="k">do</span>&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;mkdir&ensp;-p&ensp;./redis-sentinel-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf </span></span><span class="line"><span class="cl">&ensp;&ensp;<span class="nv">PORT</span><span class="o">=</span><span class="si">${</span><span class="nv">port</span><span class="si">}</span>&ensp;envsubst&ensp;&lt;&ensp;./redis-sentinel-cluster.tmpl&ensp;&gt;&ensp;./redis-sentinel-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf/sentinel.conf </span></span><span class="line"><span class="cl">&ensp;&ensp;chmod&ensp;<span class="m">777</span>&ensp;./redis-sentinel-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf/sentinel.conf </span></span><span class="line"><span class="cl">&ensp;&ensp;mkdir&ensp;-p&ensp;./redis-sentinel-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/data </span></span><span class="line"><span class="cl"><span class="k">done</span></span></span></code></pre><p>使用 Docker Compose 部署:</p> <pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">version</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;3&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">services</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7000</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis6090</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6090/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6090/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7001</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis6091</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6091/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6091/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7002</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis6092</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6092/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-6092/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">sentinel5000</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">sentinel5000</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/sentinel.conf&ensp;--sentinel&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5000/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5000/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">sentinel5001</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">sentinel5001</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/sentinel.conf&ensp;--sentinel&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5001/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5001/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">sentinel5002</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">sentinel5002</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/sentinel.conf&ensp;--sentinel&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5002/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-sentinel-cluster/5002/data:/data</span></span></span></code></pre><h2 class="heading-element" id="cluster-模式"><span>Cluster 模式</span> <a href="#cluster-%e6%a8%a1%e5%bc%8f" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><blockquote> <p><a href="https://redis.io/learn/operate/redis-at-scale/scalability/exercise-1"target="_blank" rel="external nofollow noopener noreferrer">参考资料</a></p></blockquote> <h3 class="heading-element" id="redis集群配置文件"><span>Redis集群配置文件</span> <a href="#redis%e9%9b%86%e7%be%a4%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>Redis配置模版 <code>redis-cluster.tmpl</code>:</p> <pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port&ensp;${PORT} </span></span><span class="line"><span class="cl">protected-mode&ensp;no </span></span><span class="line"><span class="cl">cluster-enabled&ensp;yes </span></span><span class="line"><span class="cl">cluster-config-file&ensp;nodes.conf </span></span><span class="line"><span class="cl">cluster-node-timeout&ensp;5000 </span></span><span class="line"><span class="cl">appendonly&ensp;yes</span></span></code></pre><p>各个Redis实例配置生成脚本 <code>redis-cluster-config.sh</code>,脚本生成端口号 7000-7005 6个Redis实例:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/bash </span></span></span><span class="line"><span class="cl"><span class="cp"></span> </span></span><span class="line"><span class="cl"><span class="k">for</span>&ensp;port&ensp;in&ensp;<span class="sb">`</span>seq&ensp;<span class="m">7000</span>&ensp;7005<span class="sb">`</span><span class="p">;</span>&ensp;<span class="k">do</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;mkdir&ensp;-p&ensp;./redis-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf </span></span><span class="line"><span class="cl">&ensp;&ensp;<span class="nv">PORT</span><span class="o">=</span><span class="si">${</span><span class="nv">port</span><span class="si">}</span>&ensp;envsubst&ensp;&lt;&ensp;./redis-cluster.tmpl&ensp;&gt;&ensp;./redis-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf/redis.conf </span></span><span class="line"><span class="cl">&ensp;&ensp;chmod&ensp;<span class="m">666</span>&ensp;./redis-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf/redis.conf </span></span><span class="line"><span class="cl">&ensp;&ensp;mkdir&ensp;-p&ensp;./redis-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/data </span></span><span class="line"><span class="cl"><span class="k">done</span></span></span></code></pre><h3 class="heading-element" id="redis集群启动"><span>Redis集群启动</span> <a href="#redis%e9%9b%86%e7%be%a4%e5%90%af%e5%8a%a8" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>使用 Docker Compose 部署:</p> <pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">version</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;3&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">services</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7000</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7000</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7000/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7000/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7001</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7001</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7001/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7001/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7002</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7002</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7002/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7002/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7003</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7003</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7003/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7003/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7004</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7004</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7004/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7004/data:/data</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;</span><span class="nt">redis7005</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">image</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis:alpine</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">container_name</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">redis7005</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">command</span><span class="p">:</span><span class="w">&ensp;</span><span class="s2">&#34;redis-server&ensp;/usr/local/etc/redis/redis.conf&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">network_mode</span><span class="p">:</span><span class="w">&ensp;</span><span class="l">host</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;</span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7005/conf:/usr/local/etc/redis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>-&ensp;<span class="l">./redis-cluster/7005/data:/data</span></span></span></code></pre><p>容器启动完毕后,连接至任意一个Redis示例,开始初始化集群:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">redis-cli&ensp;--cluster&ensp;create&ensp;127.0.0.1:7000&ensp;127.0.0.1:7001&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;127.0.0.1:7002&ensp;127.0.0.1:7003&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;127.0.0.1:7004&ensp;127.0.0.1:7005&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;--cluster-replicas&ensp;<span class="m">1</span></span></span></code></pre><p>执行完毕后将构建一个3主3从的Redis集群。</p> <h3 class="heading-element" id="测试集群"><span>测试集群</span> <a href="#%e6%b5%8b%e8%af%95%e9%9b%86%e7%be%a4" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><blockquote> <p>对于Redis集群,命令行模式需要增加 -c 选项,否则无法操作Redis,即 <code>redis-cli&ensp;-c&ensp;-p&ensp;7000</code></p></blockquote> <p>连接到端口号为7000的Redis,查看节点信息:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">127.0.0.1:7000&gt;&ensp;cluster&ensp;nodes </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">output&gt;&ensp;2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c&ensp;127.0.0.1:7002@17002&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629082981000</span>&ensp;<span class="m">3</span>&ensp;connected&ensp;10923-16383 </span></span><span class="line"><span class="cl">fc92c1709a88bdca8e86b9b5a27d035609e46059&ensp;127.0.0.1:7001@17001&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629082982000</span>&ensp;<span class="m">2</span>&ensp;connected&ensp;5461-10922 </span></span><span class="line"><span class="cl">3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4&ensp;127.0.0.1:7000@17000&ensp;myself,master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629082981000</span>&ensp;<span class="m">1</span>&ensp;connected&ensp;0-5460 </span></span><span class="line"><span class="cl">cf361fc2b72ca2bfd070b282754ad19da7640485&ensp;127.0.0.1:7003@17003&ensp;slave&ensp;3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4&ensp;<span class="m">0</span>&ensp;<span class="m">1629082982590</span>&ensp;<span class="m">1</span>&ensp;connected </span></span><span class="line"><span class="cl">fddc21542112cdcd8857bbfc77481b673e3a543e&ensp;127.0.0.1:7004@17004&ensp;slave&ensp;fc92c1709a88bdca8e86b9b5a27d035609e46059&ensp;<span class="m">0</span>&ensp;<span class="m">1629082981586</span>&ensp;<span class="m">2</span>&ensp;connected </span></span><span class="line"><span class="cl">2a5e09014c852fd15c2e54d500c532ec6ee2490e&ensp;127.0.0.1:7005@17005&ensp;slave&ensp;2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c&ensp;<span class="m">0</span>&ensp;<span class="m">1629082982088</span>&ensp;<span class="m">3</span>&ensp;connected</span></span></code></pre><p>现在让7000的实例离线30秒:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;DEBUG&ensp;sleep&ensp;<span class="m">30</span></span></span></code></pre><p>现在看一下集群信息,可以看到主节点已经由7000自动切换到了7003,:</p> <pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">127.0.0.1:7000&gt;&ensp;cluster&ensp;nodes </span></span><span class="line"><span class="cl">2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c&ensp;127.0.0.1:7002@17002&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629083362653</span>&ensp;<span class="m">3</span>&ensp;connected&ensp;10923-16383 </span></span><span class="line"><span class="cl">fc92c1709a88bdca8e86b9b5a27d035609e46059&ensp;127.0.0.1:7001@17001&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629083361000</span>&ensp;<span class="m">2</span>&ensp;connected&ensp;5461-10922 </span></span><span class="line"><span class="cl">3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4&ensp;127.0.0.1:7000@17000&ensp;myself,slave&ensp;cf361fc2b72ca2bfd070b282754ad19da7640485&ensp;<span class="m">0</span>&ensp;<span class="m">1629083362000</span>&ensp;<span class="m">7</span>&ensp;connected </span></span><span class="line"><span class="cl">cf361fc2b72ca2bfd070b282754ad19da7640485&ensp;127.0.0.1:7003@17003&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1629083362000</span>&ensp;<span class="m">7</span>&ensp;connected&ensp;0-5460 </span></span><span class="line"><span class="cl">fddc21542112cdcd8857bbfc77481b673e3a543e&ensp;127.0.0.1:7004@17004&ensp;slave&ensp;fc92c1709a88bdca8e86b9b5a27d035609e46059&ensp;<span class="m">0</span>&ensp;<span class="m">1629083362553</span>&ensp;<span class="m">2</span>&ensp;connected </span></span><span class="line"><span class="cl">2a5e09014c852fd15c2e54d500c532ec6ee2490e&ensp;127.0.0.1:7005@17005&ensp;slave&ensp;2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c&ensp;<span class="m">0</span>&ensp;<span class="m">1629083361647</span>&ensp;<span class="m">3</span>&ensp;connected</span></span></code></pre><p>可以看到7000已经切换为了salve模式,7003切换成了master模式。</p> <p>使用Go语言测试读写:</p> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span>&ensp;<span class="nx">main</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kn">import</span>&ensp;<span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;context&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;fmt&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;github.com/go-redis/redis/v8&#34;</span> </span></span><span class="line"><span class="cl"><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">var</span>&ensp;<span class="nx">ctx</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">redisAddrList</span><span class="p">()</span>&ensp;<span class="p">[]</span><span class="kt">string</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">ip</span>&ensp;<span class="o">:=</span>&ensp;<span class="s">&#34;localhost&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nx">addrList</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">[]</span><span class="kt">string</span><span class="p">{}</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">port</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">7000</span><span class="p">;</span>&ensp;<span class="nx">port</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="mi">7006</span><span class="p">;</span>&ensp;<span class="nx">port</span><span class="o">++</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">addrList</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">addrList</span><span class="p">,</span>&ensp;<span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;%s:%d&#34;</span><span class="p">,</span>&ensp;<span class="nx">ip</span><span class="p">,</span>&ensp;<span class="nx">port</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">addrList</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewRedisClient</span><span class="p">()</span>&ensp;<span class="o">*</span><span class="nx">redis</span><span class="p">.</span><span class="nx">ClusterClient</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">redis</span><span class="p">.</span><span class="nf">NewClusterClient</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">redis</span><span class="p">.</span><span class="nx">ClusterOptions</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">Addrs</span><span class="p">:</span>&ensp;<span class="nf">redisAddrList</span><span class="p">(),</span> </span></span><span class="line"><span class="cl"> <span class="p">})</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">main</span><span class="p">()</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">rdb</span>&ensp;<span class="o">:=</span>&ensp;<span class="nf">NewRedisClient</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="nx">err</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">rdb</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span>&ensp;<span class="s">&#34;foo&#34;</span><span class="p">,</span>&ensp;<span class="s">&#34;bar&#34;</span><span class="p">,</span>&ensp;<span class="mi">0</span><span class="p">).</span><span class="nf">Err</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">err</span>&ensp;<span class="o">!=</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">res</span><span class="p">,</span>&ensp;<span class="nx">err</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">rdb</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span>&ensp;<span class="s">&#34;foo&#34;</span><span class="p">).</span><span class="nf">Result</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">err</span>&ensp;<span class="o">!=</span>&ensp;<span class="kc">nil</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">res</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre><h3 class="heading-element" id="扩充节点"><span>扩充节点</span> <a href="#%e6%89%a9%e5%85%85%e8%8a%82%e7%82%b9" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>当前节点和槽分配情况:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;cluster&ensp;nodes&ensp;&ensp;&ensp;&ensp;&ensp; </span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000@17000&ensp;myself,slave&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;<span class="m">0</span>&ensp;<span class="m">1736083233000</span>&ensp;<span class="m">7</span>&ensp;connected </span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003@17003&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083234560</span>&ensp;<span class="m">7</span>&ensp;connected&ensp;0-5460 </span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004@17004&ensp;slave&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;<span class="m">0</span>&ensp;<span class="m">1736083235665</span>&ensp;<span class="m">2</span>&ensp;connected </span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001@17001&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083235000</span>&ensp;<span class="m">2</span>&ensp;connected&ensp;5461-10922 </span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002@17002&ensp;slave&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;<span class="m">0</span>&ensp;<span class="m">1736083234660</span>&ensp;<span class="m">8</span>&ensp;connected </span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005@17005&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083235563</span>&ensp;<span class="m">8</span>&ensp;connected&ensp;10923-16383</span></span></code></pre><p>在工作目录下复制一个redis配置 <code>cp&ensp;-r&ensp;7005&ensp;7006</code>,并将其端口号配置为7006,使用docker启动临时redis</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">docker&ensp;run&ensp;-d&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;--name&ensp;redis7006&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;--network&ensp;host&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;-v&ensp;./redis-cluster/7006/conf:/usr/local/etc/redis&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;-v&ensp;./redis-cluster/7006/data:/data&ensp;<span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span>&ensp;&ensp;&ensp;&ensp;redis:6.2&ensp;redis-server&ensp;/usr/local/etc/redis/redis.conf</span></span></code></pre><p>确认启动成功后,执行命令添加新的 redis node 到集群中去:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;--cluster&ensp;add-node&ensp;127.0.0.1:7006&ensp;127.0.0.1:7000&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Adding&ensp;node&ensp;127.0.0.1:7006&ensp;to&ensp;cluster&ensp;127.0.0.1:7000 </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Performing&ensp;Cluster&ensp;Check&ensp;<span class="o">(</span>using&ensp;node&ensp;127.0.0.1:7000<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780 </span></span><span class="line"><span class="cl">M:&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>0-5460<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b </span></span><span class="line"><span class="cl">M:&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>5461-10922<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5462</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;57011e62426c833268c7f01b248b0e8f44af443a </span></span><span class="line"><span class="cl">M:&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>10923-16383<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;nodes&ensp;agree&ensp;about&ensp;slots&ensp;configuration. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;<span class="k">for</span>&ensp;open&ensp;slots... </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;slots&ensp;coverage... </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;<span class="m">16384</span>&ensp;slots&ensp;covered. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Send&ensp;CLUSTER&ensp;MEET&ensp;to&ensp;node&ensp;127.0.0.1:7006&ensp;to&ensp;make&ensp;it&ensp;join&ensp;the&ensp;cluster. </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;New&ensp;node&ensp;added&ensp;correctly.</span></span></code></pre><p>此时再次查看节点信息,可以看到7006已经加入到cluster中,:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;cluster&ensp;nodes&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000@17000&ensp;myself,slave&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;<span class="m">0</span>&ensp;<span class="m">1736083995000</span>&ensp;<span class="m">7</span>&ensp;connected </span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003@17003&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083997000</span>&ensp;<span class="m">7</span>&ensp;connected&ensp;0-5460 </span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004@17004&ensp;slave&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;<span class="m">0</span>&ensp;<span class="m">1736083995380</span>&ensp;<span class="m">2</span>&ensp;connected </span></span><span class="line"><span class="cl">&ensp;127.0.0.1:7006@17006&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083996384</span>&ensp;<span class="m">0</span>&ensp;connected </span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001@17001&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083997390</span>&ensp;<span class="m">2</span>&ensp;connected&ensp;5461-10922 </span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002@17002&ensp;slave&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;<span class="m">0</span>&ensp;<span class="m">1736083996585</span>&ensp;<span class="m">8</span>&ensp;connected </span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005@17005&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736083996000</span>&ensp;<span class="m">8</span>&ensp;connected&ensp;10923-16383</span></span></code></pre><p>如果需要给7006指定一个slave,则启动7007端口的redis后,执行命令以下命令:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;--cluster&ensp;add-node&ensp;127.0.0.1:7007&ensp;127.0.0.1:7000&ensp;--cluster-slave&ensp;--cluster-master-id&ensp;d1c7e05fefad29888e1e4eb3a19574b94a280932</span></span></code></pre><p>其中 &ndash;cluster-slave 指明新节点为slave,d1c7e05fefad29888e1e4eb3a19574b94a280932是7007节点id</p> <p>新加入的节点是没有自动分配slot的,可以查看确认:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;cluster&ensp;slots&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;↵&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">1<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">0</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">5460</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7003</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7000</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;9a353c214cb677b1e996573b4550875fb0754b65&#34;</span> </span></span><span class="line"><span class="cl">2<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">5461</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">10922</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7001</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;bd393aeacf7de92c8a3816cbfb1c497a310a418b&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7004</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&#34;</span> </span></span><span class="line"><span class="cl">3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">10923</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">16383</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7005</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;57011e62426c833268c7f01b248b0e8f44af443a&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7002</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3c21e101ea340698769de95812a98275693d3b2d&#34;</span></span></span></code></pre><p>开始为7006节点分配slot</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;--cluster&ensp;reshard&ensp;127.0.0.1:7000&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Performing&ensp;Cluster&ensp;Check&ensp;<span class="o">(</span>using&ensp;node&ensp;127.0.0.1:7000<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780 </span></span><span class="line"><span class="cl">M:&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>0-5460<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b </span></span><span class="line"><span class="cl">M:&ensp;d1c7e05fefad29888e1e4eb3a19574b94a280932&ensp;127.0.0.1:7006 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">M:&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>5461-10922<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5462</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;57011e62426c833268c7f01b248b0e8f44af443a </span></span><span class="line"><span class="cl">M:&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>10923-16383<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;nodes&ensp;agree&ensp;about&ensp;slots&ensp;configuration. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;<span class="k">for</span>&ensp;open&ensp;slots... </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;slots&ensp;coverage... </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;<span class="m">16384</span>&ensp;slots&ensp;covered. </span></span><span class="line"><span class="cl">How&ensp;many&ensp;slots&ensp;<span class="k">do</span>&ensp;you&ensp;want&ensp;to&ensp;move&ensp;<span class="o">(</span>from&ensp;<span class="m">1</span>&ensp;to&ensp;16384<span class="o">)</span>?</span></span></code></pre><p>接下来会要求输入分配多少slot到哪个node,我们选择slot数量4096,分配到7006节点d1c7e05fefad29888e1e4eb3a19574b94a280932</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;<span class="m">16384</span>&ensp;slots&ensp;covered. </span></span><span class="line"><span class="cl">How&ensp;many&ensp;slots&ensp;<span class="k">do</span>&ensp;you&ensp;want&ensp;to&ensp;move&ensp;<span class="o">(</span>from&ensp;<span class="m">1</span>&ensp;to&ensp;16384<span class="o">)</span>?&ensp;<span class="m">4096</span> </span></span><span class="line"><span class="cl">What&ensp;is&ensp;the&ensp;receiving&ensp;node&ensp;ID?&ensp;d1c7e05fefad29888e1e4eb3a19574b94a280932 </span></span><span class="line"><span class="cl">Please&ensp;enter&ensp;all&ensp;the&ensp;<span class="nb">source</span>&ensp;node&ensp;IDs. </span></span><span class="line"><span class="cl">&ensp;&ensp;Type&ensp;<span class="s1">&#39;all&#39;</span>&ensp;to&ensp;use&ensp;all&ensp;the&ensp;nodes&ensp;as&ensp;<span class="nb">source</span>&ensp;nodes&ensp;<span class="k">for</span>&ensp;the&ensp;<span class="nb">hash</span>&ensp;slots. </span></span><span class="line"><span class="cl">&ensp;&ensp;Type&ensp;<span class="s1">&#39;done&#39;</span>&ensp;once&ensp;you&ensp;entered&ensp;all&ensp;the&ensp;<span class="nb">source</span>&ensp;nodes&ensp;IDs. </span></span><span class="line"><span class="cl">Source&ensp;node&ensp;<span class="c1">#1:&ensp;all</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">Ready&ensp;to&ensp;move&ensp;<span class="m">4096</span>&ensp;slots. </span></span><span class="line"><span class="cl">&ensp;&ensp;Source&ensp;nodes: </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;M:&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;slots:<span class="o">[</span>0-5460<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;M:&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;slots:<span class="o">[</span>5461-10922<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5462</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;M:&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;slots:<span class="o">[</span>10923-16383<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">5461</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;Destination&ensp;node: </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;M:&ensp;d1c7e05fefad29888e1e4eb3a19574b94a280932&ensp;127.0.0.1:7006 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;Resharding&ensp;plan: </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;Moving&ensp;slot&ensp;<span class="m">5461</span>&ensp;from&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;Moving&ensp;slot&ensp;<span class="m">5462</span>&ensp;from&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;....</span></span></code></pre><p>执行完毕再次确认slot分配情况</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;cluster&ensp;slots&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">1<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">0</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">1364</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7006</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;d1c7e05fefad29888e1e4eb3a19574b94a280932&#34;</span> </span></span><span class="line"><span class="cl">2<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">1365</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">5460</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7003</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7000</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;9a353c214cb677b1e996573b4550875fb0754b65&#34;</span> </span></span><span class="line"><span class="cl">3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">5461</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">6826</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7006</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;d1c7e05fefad29888e1e4eb3a19574b94a280932&#34;</span> </span></span><span class="line"><span class="cl">4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">6827</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">10922</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7001</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;bd393aeacf7de92c8a3816cbfb1c497a310a418b&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7004</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&#34;</span> </span></span><span class="line"><span class="cl">5<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">10923</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">12287</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7006</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;d1c7e05fefad29888e1e4eb3a19574b94a280932&#34;</span> </span></span><span class="line"><span class="cl">6<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">12288</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">16383</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7005</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;57011e62426c833268c7f01b248b0e8f44af443a&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7002</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3c21e101ea340698769de95812a98275693d3b2d&#34;</span></span></span></code></pre><h3 class="heading-element" id="删除节点"><span>删除节点</span> <a href="#%e5%88%a0%e9%99%a4%e8%8a%82%e7%82%b9" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h3><p>停止7006容器 <code>docker&ensp;stop&ensp;7006</code>,使用<code>CLUSTER&ensp;FORGET</code>移除节点:</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;CLUSTER&ensp;FORGET&ensp;d1c7e05fefad29888e1e4eb3a19574b94a280932&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">OK</span></span></code></pre> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;CLUSTER&ensp;NODES&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000@17000&ensp;myself,slave&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;<span class="m">0</span>&ensp;<span class="m">1736085038000</span>&ensp;<span class="m">7</span>&ensp;connected </span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003@17003&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736085039571</span>&ensp;<span class="m">7</span>&ensp;connected&ensp;1365-5460 </span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004@17004&ensp;slave&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;<span class="m">0</span>&ensp;<span class="m">1736085039673</span>&ensp;<span class="m">2</span>&ensp;connected </span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001@17001&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736085038667</span>&ensp;<span class="m">2</span>&ensp;connected&ensp;6827-10922 </span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002@17002&ensp;slave&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;<span class="m">0</span>&ensp;<span class="m">1736085039068</span>&ensp;<span class="m">8</span>&ensp;connected </span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005@17005&ensp;master&ensp;-&ensp;<span class="m">0</span>&ensp;<span class="m">1736085039000</span>&ensp;<span class="m">8</span>&ensp;connected&ensp;12288-16383</span></span></code></pre> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;CLUSTER&ensp;SLOTS&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">1<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">1365</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">5460</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7003</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7000</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;9a353c214cb677b1e996573b4550875fb0754b65&#34;</span> </span></span><span class="line"><span class="cl">2<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">6827</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">10922</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7001</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;bd393aeacf7de92c8a3816cbfb1c497a310a418b&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7004</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&#34;</span> </span></span><span class="line"><span class="cl">3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">12288</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">16383</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7005</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;57011e62426c833268c7f01b248b0e8f44af443a&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;4<span class="o">)</span>&ensp;1<span class="o">)</span>&ensp;<span class="s2">&#34;127.0.0.1&#34;</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;2<span class="o">)</span>&ensp;<span class="o">(</span>integer<span class="o">)</span>&ensp;<span class="m">7002</span> </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;3<span class="o">)</span>&ensp;<span class="s2">&#34;3c21e101ea340698769de95812a98275693d3b2d&#34;</span></span></span></code></pre><p>发现此时slot缺失了一部分,查看cluster状态会发现集群此时处于 fail</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-p&ensp;<span class="m">7000</span>&ensp;-c&ensp;CLUSTER&ensp;INFO&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">cluster_state:fail </span></span><span class="line"><span class="cl">cluster_slots_assigned:12288 </span></span><span class="line"><span class="cl">cluster_slots_ok:12288 </span></span><span class="line"><span class="cl">cluster_slots_pfail:0 </span></span><span class="line"><span class="cl">cluster_slots_fail:0 </span></span><span class="line"><span class="cl">cluster_known_nodes:6 </span></span><span class="line"><span class="cl">cluster_size:3 </span></span><span class="line"><span class="cl">cluster_current_epoch:9 </span></span><span class="line"><span class="cl">cluster_my_epoch:7 </span></span><span class="line"><span class="cl">cluster_stats_messages_ping_sent:7170 </span></span><span class="line"><span class="cl">cluster_stats_messages_pong_sent:7271 </span></span><span class="line"><span class="cl">cluster_stats_messages_update_sent:2 </span></span><span class="line"><span class="cl">cluster_stats_messages_sent:14443 </span></span><span class="line"><span class="cl">cluster_stats_messages_ping_received:7270 </span></span><span class="line"><span class="cl">cluster_stats_messages_pong_received:11255 </span></span><span class="line"><span class="cl">cluster_stats_messages_meet_received:1 </span></span><span class="line"><span class="cl">cluster_stats_messages_fail_received:3 </span></span><span class="line"><span class="cl">cluster_stats_messages_auth-req_received:1 </span></span><span class="line"><span class="cl">cluster_stats_messages_received:18530</span></span></code></pre><p>原因是7006在持有slot的状态下被移除了集群,此时我们需要再次reshard</p> <blockquote> <p>当然你可以设置 cluster-require-full-coverage=no 让集群强制在缺失slot的情况下继续提供服务</p></blockquote> <p>执行命令修复集群</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;--cluster&ensp;fix&ensp;127.0.0.1:7000&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;↵&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">127.0.0.1:7003&ensp;<span class="o">(</span>0a50949e...<span class="o">)</span>&ensp;-&gt;&ensp;<span class="m">0</span>&ensp;keys&ensp;<span class="p">|</span>&ensp;<span class="m">4096</span>&ensp;slots&ensp;<span class="p">|</span>&ensp;<span class="m">1</span>&ensp;slaves. </span></span><span class="line"><span class="cl">127.0.0.1:7001&ensp;<span class="o">(</span>bd393aea...<span class="o">)</span>&ensp;-&gt;&ensp;<span class="m">0</span>&ensp;keys&ensp;<span class="p">|</span>&ensp;<span class="m">4096</span>&ensp;slots&ensp;<span class="p">|</span>&ensp;<span class="m">1</span>&ensp;slaves. </span></span><span class="line"><span class="cl">127.0.0.1:7005&ensp;<span class="o">(</span>57011e62...<span class="o">)</span>&ensp;-&gt;&ensp;<span class="m">1</span>&ensp;keys&ensp;<span class="p">|</span>&ensp;<span class="m">4096</span>&ensp;slots&ensp;<span class="p">|</span>&ensp;<span class="m">1</span>&ensp;slaves. </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;<span class="m">1</span>&ensp;keys&ensp;in&ensp;<span class="m">3</span>&ensp;masters. </span></span><span class="line"><span class="cl">0.00&ensp;keys&ensp;per&ensp;slot&ensp;on&ensp;average. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Performing&ensp;Cluster&ensp;Check&ensp;<span class="o">(</span>using&ensp;node&ensp;127.0.0.1:7000<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;9a353c214cb677b1e996573b4550875fb0754b65&ensp;127.0.0.1:7000 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780 </span></span><span class="line"><span class="cl">M:&ensp;0a50949e09aa0ebce0dbad1c8b0f301adbd62780&ensp;127.0.0.1:7003 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>1365-5460<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">4096</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3b8b46eac23b396e1d0b1adcfb70d086ee539da5&ensp;127.0.0.1:7004 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b </span></span><span class="line"><span class="cl">M:&ensp;bd393aeacf7de92c8a3816cbfb1c497a310a418b&ensp;127.0.0.1:7001 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>6827-10922<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">4096</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl">S:&ensp;3c21e101ea340698769de95812a98275693d3b2d&ensp;127.0.0.1:7002 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:&ensp;<span class="o">(</span><span class="m">0</span>&ensp;slots<span class="o">)</span>&ensp;slave </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;replicates&ensp;57011e62426c833268c7f01b248b0e8f44af443a </span></span><span class="line"><span class="cl">M:&ensp;57011e62426c833268c7f01b248b0e8f44af443a&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;slots:<span class="o">[</span>12288-16383<span class="o">]</span>&ensp;<span class="o">(</span><span class="m">4096</span>&ensp;slots<span class="o">)</span>&ensp;master </span></span><span class="line"><span class="cl">&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;additional&ensp;replica<span class="o">(</span>s<span class="o">)</span> </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;nodes&ensp;agree&ensp;about&ensp;slots&ensp;configuration. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;<span class="k">for</span>&ensp;open&ensp;slots... </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;slots&ensp;coverage... </span></span><span class="line"><span class="cl"><span class="o">[</span>ERR<span class="o">]</span>&ensp;Not&ensp;all&ensp;<span class="m">16384</span>&ensp;slots&ensp;are&ensp;covered&ensp;by&ensp;nodes. </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Fixing&ensp;slots&ensp;coverage... </span></span><span class="line"><span class="cl">The&ensp;following&ensp;uncovered&ensp;slots&ensp;have&ensp;no&ensp;keys&ensp;across&ensp;the&ensp;cluster: </span></span><span class="line"><span class="cl"><span class="o">[</span>0-1364<span class="o">]</span>,<span class="o">[</span>5461-6826<span class="o">]</span>,<span class="o">[</span>10923-12287<span class="o">]</span> </span></span><span class="line"><span class="cl">Fix&ensp;these&ensp;slots&ensp;by&ensp;covering&ensp;with&ensp;a&ensp;random&ensp;node?&ensp;<span class="o">(</span><span class="nb">type</span>&ensp;<span class="s1">&#39;yes&#39;</span>&ensp;to&ensp;accept<span class="o">)</span>:&ensp;yes </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Covering&ensp;slot&ensp;<span class="m">5470</span>&ensp;with&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Covering&ensp;slot&ensp;<span class="m">11756</span>&ensp;with&ensp;127.0.0.1:7005 </span></span><span class="line"><span class="cl">...</span></span></code></pre><p>执行命令检查集群状态</p> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;--cluster&ensp;check&ensp;127.0.0.1:7000&ensp;&ensp; </span></span><span class="line"><span class="cl">&ensp;... </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;nodes&ensp;agree&ensp;about&ensp;slots&ensp;configuration. </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;<span class="k">for</span>&ensp;open&ensp;slots... </span></span><span class="line"><span class="cl">&gt;&gt;&gt;&ensp;Check&ensp;slots&ensp;coverage... </span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span>&ensp;All&ensp;<span class="m">16384</span>&ensp;slots&ensp;covered.</span></span></code></pre> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">~/docker-app/redis-cluster&ensp;»&ensp;redis-cli&ensp;-c&ensp;-p&ensp;<span class="m">7000</span>&ensp;CLUSTER&ensp;INFO&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;<span class="m">1</span>&ensp;↵&ensp;ing@ing-pc </span></span><span class="line"><span class="cl">cluster_state:ok </span></span><span class="line"><span class="cl">cluster_slots_assigned:16384 </span></span><span class="line"><span class="cl">cluster_slots_ok:16384 </span></span><span class="line"><span class="cl">cluster_slots_pfail:0 </span></span><span class="line"><span class="cl">cluster_slots_fail:0 </span></span><span class="line"><span class="cl">cluster_known_nodes:6 </span></span><span class="line"><span class="cl">cluster_size:3 </span></span><span class="line"><span class="cl">cluster_current_epoch:14 </span></span><span class="line"><span class="cl">cluster_my_epoch:13 </span></span><span class="line"><span class="cl">cluster_stats_messages_ping_sent:8616 </span></span><span class="line"><span class="cl">cluster_stats_messages_pong_sent:8700 </span></span><span class="line"><span class="cl">cluster_stats_messages_update_sent:2 </span></span><span class="line"><span class="cl">cluster_stats_messages_sent:17318 </span></span><span class="line"><span class="cl">cluster_stats_messages_ping_received:8699 </span></span><span class="line"><span class="cl">cluster_stats_messages_pong_received:12698 </span></span><span class="line"><span class="cl">cluster_stats_messages_meet_received:1 </span></span><span class="line"><span class="cl">cluster_stats_messages_fail_received:3 </span></span><span class="line"><span class="cl">cluster_stats_messages_auth-req_received:1 </span></span><span class="line"><span class="cl">cluster_stats_messages_update_received:2 </span></span><span class="line"><span class="cl">cluster_stats_messages_received:21404</span></span></code></pre> 算法基础-堆 https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%A0%86/ Fri, 13 Aug 2021 09:47:50 +0800[email protected] (ingbyr) https://ingbyr.github.io/posts/%E7%AE%97%E6%B3%95%E5%9F%BA%E7%A1%80-%E5%A0%86/ 算法 <p>堆,亦称为优先队列</p> <h2 class="heading-element" id="最小堆"><span>最小堆</span> <a href="#%e6%9c%80%e5%b0%8f%e5%a0%86" class="heading-mark"> <svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> </a> </h2><p>设堆大小为 size,对于下标为k的节点:</p> <ul> <li>父节点下标为 <code>(k&ensp;-&ensp;1)&ensp;/&ensp;2</code></li> <li>左子节点下标为 <code>2&ensp;*&ensp;k&ensp;+&ensp;1</code>,右子节点下标为 <code>2&ensp;*&ensp;k&ensp;+&ensp;2</code></li> <li>最后一个非叶子节点的下标为 <code>(size&ensp;-&ensp;2)&ensp;/&ensp;2</code> (即最后一个节点 <code>size&ensp;-&ensp;1</code>的父节点 <code>((size&ensp;-&ensp;1)&ensp;-&ensp;1)&ensp;/&ensp;2</code>)</li> </ul> <p>go语言参考实现:</p> <pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span>&ensp;<span class="nx">MinHeap</span>&ensp;<span class="kd">struct</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">heap</span>&ensp;<span class="p">[]</span><span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="nf">NewMinHeap</span><span class="p">()</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="o">&amp;</span><span class="nx">MinHeap</span><span class="p">{</span><span class="nx">heap</span><span class="p">:</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">{}}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">up</span><span class="p">(</span><span class="nx">k</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">==</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">pk</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nx">k</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span><span class="p">;</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="mi">0</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">]</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">];</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">pk</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">k</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">pk</span> </span></span><span class="line"><span class="cl"> <span class="nx">pk</span>&ensp;<span class="p">=</span>&ensp;<span class="p">(</span><span class="nx">k</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">down</span><span class="p">(</span><span class="nx">k</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">==</span>&ensp;<span class="mi">1</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">last</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">2</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">k</span>&ensp;<span class="o">&lt;=</span>&ensp;<span class="nx">last</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="o">:=</span>&ensp;<span class="mi">2</span><span class="o">*</span><span class="nx">k</span>&ensp;<span class="o">+</span>&ensp;<span class="mi">1</span>&ensp;<span class="c1">//&ensp;left&ensp;child</span> </span></span><span class="line"><span class="cl"> <span class="nx">childV</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">right</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">child</span>&ensp;<span class="o">+</span>&ensp;<span class="mi">1</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">right</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">&amp;&amp;</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">right</span><span class="p">]</span>&ensp;<span class="p">&lt;</span>&ensp;<span class="nx">childV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">child</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">right</span> </span></span><span class="line"><span class="cl"> <span class="nx">childV</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">right</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="nx">childV</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">child</span><span class="p">],</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">k</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">child</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span>&ensp;<span class="k">else</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">break</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">add</span><span class="p">(</span><span class="nx">v</span>&ensp;<span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nb">append</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">,</span>&ensp;<span class="nx">v</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">up</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">pop</span><span class="p">()</span>&ensp;<span class="p">(</span><span class="kt">int</span><span class="p">,</span>&ensp;<span class="kt">bool</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">==</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="mi">0</span><span class="p">,</span>&ensp;<span class="kc">false</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">res</span>&ensp;<span class="o">:=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span>&ensp;<span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="p">&gt;</span>&ensp;<span class="mi">0</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">down</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span>&ensp;<span class="nx">res</span><span class="p">,</span>&ensp;<span class="kc">true</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span>&ensp;<span class="p">(</span><span class="nx">h</span>&ensp;<span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span>&ensp;<span class="nf">heapify</span><span class="p">(</span><span class="nx">arr</span>&ensp;<span class="p">[]</span><span class="kt">int</span><span class="p">)</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nx">heap</span>&ensp;<span class="p">=</span>&ensp;<span class="nx">arr</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">:=</span>&ensp;<span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">h</span><span class="p">.</span><span class="nx">heap</span><span class="p">)</span>&ensp;<span class="o">-</span>&ensp;<span class="mi">2</span><span class="p">)</span>&ensp;<span class="o">/</span>&ensp;<span class="mi">2</span><span class="p">;</span>&ensp;<span class="nx">i</span>&ensp;<span class="o">&gt;=</span>&ensp;<span class="mi">0</span><span class="p">;</span>&ensp;<span class="nx">i</span><span class="o">--</span>&ensp;<span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">h</span><span class="p">.</span><span class="nf">down</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>