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"><parent></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><groupId></span>org.springframework.boot<span class="nt"></groupId></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><artifactId></span>spring-boot-starter-parent<span class="nt"></artifactId></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><version></span>3.5.8<span class="nt"></version></span>
</span></span><span class="line"><span class="cl"><span class="nt"></parent></span></span></span></code></pre><p>添加版本控制后,需要将旧版本依赖的版本号全部删除,执行 <code>maven 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 dependency:tree -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"><dependencyManagement></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><dependency></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><groupId></span>com.bstek.ureport<span class="nt"></groupId></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><artifactId></span>ureport2-console<span class="nt"></artifactId></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><version></span>${ureport.version}<span class="nt"></version></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><exclusions></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><exclusion></span>
</span></span><span class="line"><span class="cl">                <span class="nt"><groupId></span>commons-fileupload<span class="nt"></groupId></span>
</span></span><span class="line"><span class="cl">                <span class="nt"><artifactId></span>commons-fileupload<span class="nt"></artifactId></span>
</span></span><span class="line"><span class="cl">            <span class="nt"></exclusion></span>
</span></span><span class="line"><span class="cl">        <span class="nt"></exclusions></span>
</span></span><span class="line"><span class="cl">    <span class="nt"></dependency></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><dependency></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><groupId></span>org.apache.commons<span class="nt"></groupId></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><artifactId></span>commons-fileupload2-jakarta-servlet6<span class="nt"></artifactId></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><version></span>${commons-fileupload.version}<span class="nt"></version></span>
</span></span><span class="line"><span class="cl">    <span class="nt"></dependency></span>
</span></span><span class="line"><span class="cl"><span class="nt"></dependencyManagement></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"><plugin></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><groupId></span>org.codehaus.mojo<span class="nt"></groupId></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><artifactId></span>flatten-maven-plugin<span class="nt"></artifactId></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><version></span>1.7.3<span class="nt"></version></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><configuration></span>
</span></span><span class="line"><span class="cl">    <span class="nt"></configuration></span>
</span></span><span class="line"><span class="cl">    <span class="nt"><executions></span>
</span></span><span class="line"><span class="cl">        <span class="c"><!-- enable flattening --></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><execution></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><id></span>flatten<span class="nt"></id></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><phase></span>process-resources<span class="nt"></phase></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><goals></span>
</span></span><span class="line"><span class="cl">                <span class="nt"><goal></span>flatten<span class="nt"></goal></span>
</span></span><span class="line"><span class="cl">            <span class="nt"></goals></span>
</span></span><span class="line"><span class="cl">        <span class="nt"></execution></span>
</span></span><span class="line"><span class="cl">        <span class="c"><!-- ensure proper cleanup --></span>
</span></span><span class="line"><span class="cl">        <span class="nt"><execution></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><id></span>flatten.clean<span class="nt"></id></span>
</span></span><span class="line"><span class="cl">            <span class="nt"><goals></span>
</span></span><span class="line"><span class="cl">                <span class="nt"><goal></span>clean<span class="nt"></goal></span>
</span></span><span class="line"><span class="cl">            <span class="nt"></goals></span>
</span></span><span class="line"><span class="cl">        <span class="nt"></execution></span>
</span></span><span class="line"><span class="cl">    <span class="nt"></executions></span>
</span></span><span class="line"><span class="cl"><span class="nt"></plugin></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 -> Migrate Packages and Classes -> Java EE to Jakarta 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">  </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">    </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">      </span>- <span class="l">classpath:base.properties</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <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"> </span><span class="kd">class</span> <span class="nc">MyPropertySourcePostProcessor</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">EnvironmentPostProcessor</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">MapPropertySource</span><span class="w"> </span><span class="nf">mergeMyPropertySource</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Properties</span><span class="w"> </span><span class="n">properties</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">></span><span class="w"> </span><span class="n">map</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HashMap</span><span class="o"><></span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </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"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </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"> </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">        </span><span class="n">MapPropertySource</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">MapPropertySource</span><span class="p">(</span><span class="s">"myProperties"</span><span class="p">,</span><span class="w"> </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">        </span><span class="k">return</span><span class="w"> </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">    </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="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">postProcessEnvironment</span><span class="p">(</span><span class="n">ConfigurableEnvironment</span><span class="w"> </span><span class="n">environment</span><span class="p">,</span><span class="w"> </span><span class="n">SpringApplication</span><span class="w"> </span><span class="n">application</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </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">                </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">    </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 $pid VM.native_memory 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 -x $pid</code> 查看内存分布情况,对比前后两次的内容发现一直会申请一些64MB的内存块,并且始终处于未释放状态</li>
<li>查看 <code>/proc/$pid/smaps</code> 或 <code>/proc/$pid/maps</code> 找到对应内存起始和终止地址</li>
<li>使用 <code>gdb -pid $pid</code> attach 到问题进程, <code>dump memory mem.bin 起始地址 终止地址</code> dump 出对应的多块内存块。</li>
<li>由于此次Java应用中存在中文字符,因此使用 <code>strings -eS 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> <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> <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   0.1% 100.0%  7386790   0.8% 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 $pid | grep 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 LR
    subgraph server-1
        log-file-1 --> filebeat-1
    end
    subgraph server-2
        log-file-2 --> filebeat-2
    end
    filebeat-1 -- push log --> kafka
    filebeat-2 -- push log --> kafka
    kafka -- sub log --> logstash-filter
    logstash-filter -- pub log --> kafka
    kafka -- sub log --> logstash
    logstash -- push --> es
    kibana -- query --> 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 -u elastic</code></li>
<li><code>./bin/elasticsearch-reset-password -u 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 {
</span></span><span class="line"><span class="cl">  org.apache.kafka.common.security.plain.PlainLoginModule required
</span></span><span class="line"><span class="cl">    username="admin"
</span></span><span class="line"><span class="cl">    password="admin-password"
</span></span><span class="line"><span class="cl">    user_admin="admin-password"
</span></span><span class="line"><span class="cl">    user_tom="tom-password";
</span></span><span class="line"><span class="cl">};
</span></span><span class="line"><span class="cl">KafkaClient {
</span></span><span class="line"><span class="cl">  org.apache.kafka.common.security.plain.PlainLoginModule required
</span></span><span class="line"><span class="cl">    username="admin"
</span></span><span class="line"><span class="cl">    password="admin-password"
</span></span><span class="line"><span class="cl">    user_admin="admin-password"
</span></span><span class="line"><span class="cl">    user_tom="tom-password";
</span></span><span class="line"><span class="cl">};
</span></span><span class="line"><span class="cl">Client {
</span></span><span class="line"><span class="cl">  org.apache.kafka.common.security.plain.PlainLoginModule required
</span></span><span class="line"><span class="cl">    username="admin"
</span></span><span class="line"><span class="cl">    password="admin-password"
</span></span><span class="line"><span class="cl">    user_admin="admin-password";
</span></span><span class="line"><span class="cl">};
</span></span><span class="line"><span class="cl">Server {
</span></span><span class="line"><span class="cl">  org.apache.kafka.common.security.plain.PlainLoginModule required
</span></span><span class="line"><span class="cl">    username="admin"
</span></span><span class="line"><span class="cl">    password="admin-password"
</span></span><span class="line"><span class="cl">    user_admin="admin-password";
</span></span><span class="line"><span class="cl">};</span></span></code></pre><p>修改 <code>bin/kafka-server-start.sh</code>, 最后一行前添加 <code>export KAFKA_OPTS="-Djava.security.auth.login.config=$base_dir/../config/kafka_server_jaas.conf"</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 \
</span></span><span class="line"><span class="cl">    required username="tom" password="tom-password";
</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 --bootstrap-server ip:port --command-config config/tom-client.conf --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> <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> <span class="nx">TrieNode</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">isWord</span>   <span class="kt">bool</span>
</span></span><span class="line"><span class="cl"> <span class="nx">children</span> <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> <span class="nf">NewTrieNode</span><span class="p">()</span> <span class="o">*</span><span class="nx">TrieNode</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">&</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>   <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> <span class="nb">make</span><span class="p">([]</span><span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span> <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> <span class="nx">Trie</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">root</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> <span class="nf">NewTrie</span><span class="p">()</span> <span class="nx">Trie</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">Trie</span><span class="p">)</span> <span class="nf">Insert</span><span class="p">(</span><span class="nx">word</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">node</span> <span class="o">:=</span> <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> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">word</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">idx</span> <span class="o">:=</span> <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> <span class="o">-</span> <span class="sc">'a'</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <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 class="o">==</span> <span class="kc">nil</span> <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> <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 class="nx">node</span> <span class="p">=</span> <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> <span class="p">=</span> <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> <span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">Trie</span><span class="p">)</span> <span class="nf">Search</span><span class="p">(</span><span class="nx">word</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">node</span> <span class="o">:=</span> <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> <span class="nx">node</span> <span class="o">==</span> <span class="kc">nil</span> <span class="o">||</span> <span class="p">!</span><span class="nx">node</span><span class="p">.</span><span class="nx">isWord</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <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> <span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">Trie</span><span class="p">)</span> <span class="nf">StartsWith</span><span class="p">(</span><span class="nx">prefix</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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 class="o">!=</span> <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> <span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">Trie</span><span class="p">)</span> <span class="nf">GetNode</span><span class="p">(</span><span class="nx">word</span> <span class="kt">string</span><span class="p">)</span> <span class="o">*</span><span class="nx">TrieNode</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">node</span> <span class="o">:=</span> <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> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">word</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">idx</span> <span class="o">:=</span> <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> <span class="o">-</span> <span class="sc">'a'</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="o">:=</span> <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> <span class="nx">child</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <span class="p">=</span> <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> <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> <span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">Trie</span><span class="p">)</span> <span class="nf">Scan</span><span class="p">(</span><span class="nx">prefix</span> <span class="kt">string</span><span class="p">)</span> <span class="p">[]</span><span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">node</span> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">string</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">if</span> <span class="nx">node</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <span class="nx">dfs</span> <span class="kd">func</span><span class="p">(</span><span class="nx">node</span> <span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span> <span class="nx">path</span> <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> <span class="p">=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">node</span> <span class="o">*</span><span class="nx">TrieNode</span><span class="p">,</span> <span class="nx">path</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">node</span> <span class="o">==</span> <span class="kc">nil</span> <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> <span class="nx">node</span><span class="p">.</span><span class="nx">isWord</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="mi">26</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="o">:=</span> <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> <span class="nx">child</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">path</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="nb">byte</span><span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="sc">'a'</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> <span class="nx">path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">path</span> <span class="p">=</span> <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> <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> <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> <span class="nf">NewUF</span><span class="p">(</span><span class="nx">n</span> <span class="kt">int</span><span class="p">)</span> <span class="o">*</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="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">parent</span> <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> <span class="p">=</span> <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> <span class="o">&</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> <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>  <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> <span class="nx">UnionFind</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">parent</span> <span class="p">[]</span><span class="kt">int</span>
</span></span><span class="line"><span class="cl"> <span class="nx">count</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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Union</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rootA</span> <span class="o">:=</span> <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> <span class="o">:=</span> <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> <span class="nx">rootA</span> <span class="o">==</span> <span class="nx">rootB</span> <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> <span class="p">=</span> <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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Find</span><span class="p">(</span><span class="nx">a</span> <span class="kt">int</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">for</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 class="o">!=</span> <span class="nx">a</span> <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> <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">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> <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="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Connected</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rootA</span> <span class="o">:=</span> <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> <span class="o">:=</span> <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> <span class="nx">rootA</span> <span class="o">==</span> <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> <span class="nf">minCostConnectPoints</span><span class="p">(</span><span class="nx">points</span> <span class="p">[][]</span><span class="kt">int</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">n</span> <span class="o">:=</span> <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">    <span class="c1">// graph [from, to, weight]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">graph</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([][]</span><span class="kt">int</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> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">edge</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span><span class="p">,</span> <span class="nf">dist</span><span class="p">(</span><span class="nx">points</span><span class="p">,</span> <span class="nx">i</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">graph</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">graph</span><span class="p">,</span> <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> <span class="kd">func</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <span class="p"><</span> <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> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">edge</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">graph</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">w</span> <span class="o">:=</span> <span class="nx">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <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> <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> <span class="nx">b</span><span class="p">)</span> <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> <span class="nx">b</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="o">+=</span> <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> <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> <span class="nf">abs</span><span class="p">(</span><span class="nx">a</span> <span class="kt">int</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> <span class="nx">a</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">return</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 class="k">return</span> <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> <span class="nf">dist</span><span class="p">(</span><span class="nx">points</span> <span class="p">[][]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</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">return</span> <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> <span class="o">+</span> <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> <span class="nf">abs</span><span class="p">(</span><span class="nx">a</span> <span class="kt">int</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> <span class="nx">a</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">return</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 class="k">return</span> <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> <span class="nf">dist</span><span class="p">(</span><span class="nx">points</span> <span class="p">[][]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</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">return</span> <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> <span class="o">+</span> <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> <span class="nx">PriorityQueue</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">data</span> <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> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span> <span class="nf">Len</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">return</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></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> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span> <span class="nf">Less</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <span class="p"><</span> <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> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span> <span class="nf">Swap</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</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><span class="p">[</span><span class="nx">i</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="nx">j</span><span class="p">]</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="nx">j</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="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> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span> <span class="nf">Push</span><span class="p">(</span><span class="nx">x</span> <span class="kd">interface</span><span class="p">{})</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> <span class="p">=</span> <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> <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> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><span class="nx">PriorityQueue</span><span class="p">)</span> <span class="nf">Pop</span><span class="p">()</span> <span class="kd">interface</span><span class="p">{}</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">v</span> <span class="o">:=</span> <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> <span class="p">=</span> <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> <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> <span class="nf">minCostConnectPoints</span><span class="p">(</span><span class="nx">points</span> <span class="p">[][]</span><span class="kt">int</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">n</span> <span class="o">:=</span> <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">    <span class="c1">// graph[from] [to, weight]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">graph</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([][][]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 邻接表表示的无向图,需要双向赋值</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">i</span> <span class="o">==</span> <span class="nx">j</span> <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> <span class="p">=</span> <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> <span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="nx">j</span><span class="p">,</span> <span class="nf">dist</span><span class="p">(</span><span class="nx">points</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <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> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">bool</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">pq</span> <span class="o">:=</span> <span class="o">&</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> <span class="o">:=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">a</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">edge</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">graph</span><span class="p">[</span><span class="nx">a</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <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> <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> <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> <span class="p">=</span> <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> <span class="o">:=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">pq</span><span class="p">.</span><span class="nf">Len</span><span class="p">()</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">edge</span> <span class="o">:=</span> <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> <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> <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> <span class="o">+=</span> <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> <span class="p">=</span> <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> <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> <span class="nf">isBipartite</span><span class="p">(</span><span class="nx">graph</span> <span class="p">[][]</span><span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">n</span> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">bool</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">color</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">bool</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">valid</span> <span class="o">:=</span> <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> <span class="nx">bfs</span> <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> <span class="p">=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">root</span> <span class="kt">int</span><span class="p">)</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">root</span><span class="p">]</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"> <span class="nx">queue</span> <span class="o">:=</span> <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> <span class="nb">len</span><span class="p">(</span><span class="nx">queue</span><span class="p">)</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">node</span> <span class="o">:=</span> <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> <span class="p">=</span> <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> <span class="nx">_</span><span class="p">,</span> <span class="nx">next</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">graph</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span> <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> <span class="p">=</span> <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> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"> <span class="nx">queue</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">queue</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> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span> <span class="o">==</span> <span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">valid</span> <span class="p">=</span> <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> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">&&</span> <span class="nx">valid</span> <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> <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> <span class="nf">possibleBipartition</span><span class="p">(</span><span class="nx">n</span> <span class="kt">int</span><span class="p">,</span> <span class="nx">dislikes</span> <span class="p">[][]</span><span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">graph</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([][]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">dislike</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">dislikes</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="o">:=</span> <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> <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> <span class="p">=</span> <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> <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> <span class="p">=</span> <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> <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> <span class="o">:=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"> <span class="nx">visited</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">bool</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">color</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">bool</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">dfs</span> <span class="kd">func</span><span class="p">(</span><span class="nx">node</span> <span class="kt">int</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">dfs</span> <span class="p">=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">node</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">valid</span> <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> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">next</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">graph</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span> <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> <span class="p">=</span> <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> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">color</span><span class="p">[</span><span class="nx">next</span><span class="p">]</span> <span class="o">==</span> <span class="nx">color</span><span class="p">[</span><span class="nx">node</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">valid</span> <span class="p">=</span> <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> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">visited</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">&&</span> <span class="nx">valid</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">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> <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> <span class="nf">NewUF</span><span class="p">(</span><span class="nx">n</span> <span class="kt">int</span><span class="p">)</span> <span class="o">*</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="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">parent</span> <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> <span class="p">=</span> <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> <span class="o">&</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> <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>  <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> <span class="nx">UnionFind</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">parent</span> <span class="p">[]</span><span class="kt">int</span>
</span></span><span class="line"><span class="cl"> <span class="nx">count</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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Union</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rootA</span> <span class="o">:=</span> <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> <span class="o">:=</span> <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> <span class="nx">rootA</span> <span class="o">==</span> <span class="nx">rootB</span> <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> <span class="p">=</span> <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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Find</span><span class="p">(</span><span class="nx">a</span> <span class="kt">int</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">for</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 class="o">!=</span> <span class="nx">a</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// compress parent 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> <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">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> <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="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</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> <span class="p">(</span><span class="nx">uf</span> <span class="o">*</span><span class="nx">UnionFind</span><span class="p">)</span> <span class="nf">Connected</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rootA</span> <span class="o">:=</span> <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> <span class="o">:=</span> <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> <span class="nx">rootA</span> <span class="o">==</span> <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> <span class="nf">sortBubble1</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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">n</span> <span class="o">:=</span> <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">// 有序区间 [0, i]</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 从最右侧两两交换,将无序区间中的最小值放置到i</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span> <span class="p">></span> <span class="nx">i</span><span class="p">;</span> <span class="nx">j</span><span class="o">--</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p"><</span> <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> <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> <span class="nx">j</span><span class="p">,</span> <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="k">return</span> <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> <span class="nf">sortBubble2</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">n</span> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 有序区间 [0, i]</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">n</span> <span class="o">&&</span> <span class="nx">exchanged</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 当 exchanged 为 true 时,表明剩余无序区间已有序,结束排序</span>
</span></span><span class="line"><span class="cl"> <span class="nx">exchanged</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 从最右侧两两交换,将无序区间中的最小值放置到i</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span> <span class="p">></span> <span class="nx">i</span><span class="p">;</span> <span class="nx">j</span><span class="o">--</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p"><</span> <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> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">exchanged</span> <span class="p">=</span> <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> <span class="nx">j</span><span class="p">,</span> <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> <span class="nf">sortQuick</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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">return</span> <span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</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></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">_sortQuick</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">left</span><span class="p">,</span> <span class="nx">right</span> <span class="kt">int</span><span class="p">)</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> <span class="nx">left</span> <span class="p"><</span> <span class="nx">right</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">p</span> <span class="o">:=</span> <span class="nf">partition</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">left</span><span class="p">,</span> <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> <span class="nx">left</span><span class="p">,</span> <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> <span class="nx">p</span><span class="o">+</span><span class="mi">1</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">return</span> <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> <span class="nf">partition</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">,</span> <span class="nx">l</span> <span class="kt">int</span><span class="p">,</span> <span class="nx">r</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// l位空出</span>
</span></span><span class="line"><span class="cl"> <span class="nx">v</span> <span class="o">:=</span> <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> <span class="nx">l</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> <span class="nx">l</span> <span class="p"><</span> <span class="nx">r</span> <span class="o">&&</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">>=</span> <span class="nx">v</span> <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">// 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> <span class="p">=</span> <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> <span class="nx">l</span> <span class="p"><</span> <span class="nx">r</span> <span class="o">&&</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">l</span><span class="p">]</span> <span class="o"><=</span> <span class="nx">v</span> <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">// 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> <span class="p">=</span> <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">// 空出的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> <span class="p">=</span> <span class="nx">v</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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">   </span><span class="kd">class</span> <span class="nc">Solution</span><span class="w"> </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="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="nf">sortArray</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">nums</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </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">        </span><span class="k">return</span><span class="w"> </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">    </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="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">quickSort</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </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">        </span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">-</span><span class="w"> </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">        </span><span class="n">quickSort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">,</span><span class="w"> </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">    </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="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">partition</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">randomPiv</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </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">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">nums</span><span class="o">[</span><span class="n">r</span><span class="o">]</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </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">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">            </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </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">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">nums</span><span class="o">[</span><span class="n">r</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="k">return</span><span class="w"> </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">    </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="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">randomPiv</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </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"> </span><span class="o">-</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </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">        </span><span class="kt">int</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="n">nums</span><span class="o">[</span><span class="n">l</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="n">nums</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="k">return</span><span class="w"> </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">    </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">  </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> <span class="nf">sortInsert</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">[]</span><span class="kt">int</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 有序区间 [0, i],无序区间[i+1, +00]</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">i</span><span class="p">;</span> <span class="nx">j</span> <span class="p">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p"><</span> <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> <span class="nx">j</span><span class="o">--</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 小数前移</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> <span class="nx">j</span><span class="p">,</span> <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="k">return</span> <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> <span class="nf">sortShell</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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">for</span> <span class="nx">step</span> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">step</span> <span class="p">></span> <span class="mi">0</span><span class="p">;</span> <span class="nx">step</span> <span class="o">/=</span> <span class="mi">2</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="nx">step</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">i</span><span class="p">;</span> <span class="nx">j</span> <span class="o">>=</span> <span class="nx">step</span> <span class="o">&&</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p"><</span> <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> <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="c1">// 同组内小数前移</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> <span class="nx">j</span><span class="p">,</span> <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> <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> <span class="nf">sortSelect</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">m</span> <span class="o">:=</span> <span class="nx">i</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 无序区间内选择最小值下标 m</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">i</span><span class="p">;</span> <span class="nx">j</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span> <span class="nx">j</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p"><</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">m</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">m</span> <span class="p">=</span> <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> <span class="nx">m</span> <span class="o">!=</span> <span class="nx">i</span> <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> <span class="nx">i</span><span class="p">,</span> <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> <span class="nf">sortHeap</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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">h</span> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <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> <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="p">></span> <span class="mi">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <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> <span class="nx">MinHeap</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">heap</span> <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">// 上浮操作:节点与大于节点值的父节点交换</span>
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">up</span><span class="p">(</span><span class="nx">k</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">k</span> <span class="o">==</span> <span class="mi">0</span> <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="c1">// 节点 k 比 父节点 pk 小时,交换两节点,实现节点上浮</span>
</span></span><span class="line"><span class="cl"> <span class="nx">pk</span> <span class="o">:=</span> <span class="p">(</span><span class="nx">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">k</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <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 class="p">></span> <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 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> <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 class="p">=</span> <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 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> <span class="p">=</span> <span class="nx">pk</span>
</span></span><span class="line"><span class="cl"> <span class="nx">pk</span> <span class="p">=</span> <span class="p">(</span><span class="nx">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <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">// 下沉操作:节点与子节点中较小值交换</span>
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">down</span><span class="p">(</span><span class="nx">k</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</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">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> <span class="o">:=</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="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">k</span> <span class="o"><=</span> <span class="nx">lastNonLeaf</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 默认左侧节点为子节点中值最小节点</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="o">:=</span> <span class="mi">2</span><span class="o">*</span><span class="nx">k</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"> <span class="nx">childV</span> <span class="o">:=</span> <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="c1">// 检查右侧节点,若比默认节点小,替换之</span>
</span></span><span class="line"><span class="cl"> <span class="nx">right</span> <span class="o">:=</span> <span class="nx">child</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">right</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="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 class="p"><</span> <span class="nx">childV</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="p">=</span> <span class="nx">right</span>
</span></span><span class="line"><span class="cl"> <span class="nx">childV</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="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="c1">// 若节点比子节点大,下沉</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <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 class="p">></span> <span class="nx">childV</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="nx">k</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="nx">child</span><span class="p">]</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="nx">child</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="nx">k</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">k</span> <span class="p">=</span> <span class="nx">child</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <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">// 添加操作:加至末尾节点,后上浮尾节点</span>
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">add</span><span class="p">(</span><span class="nx">v</span> <span class="kt">int</span><span class="p">)</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="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> <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> <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></span><span class="line"><span class="cl"><span class="c1">// 弹出操作:头节点弹出,尾节点放置头节点,后下沉头节点</span>
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">pop</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> <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">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nb">panic</span><span class="p">(</span><span class="s">"empty heap"</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> <span class="o">:=</span> <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">// swap last and 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> <span class="p">=</span> <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">// remove last</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">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> <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="p">></span> <span class="mi">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 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> <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">// 构建树:从最后一个非叶子节点开始,执行下沉操作</span>
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">build</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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="nx">arr</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</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">2</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">i</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">--</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">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> <span class="nf">sortMerge</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</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> <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> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <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> <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> <span class="nf">merge</span><span class="p">(</span><span class="nx">left</span><span class="p">,</span> <span class="nx">right</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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">res</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <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">    <span class="c1">// 每次处理一个元素</span>
</span></span><span class="line"><span class="cl"> <span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">left</span><span class="p">)</span> <span class="o">&&</span> <span class="nx">j</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">right</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">left</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p"><</span> <span class="nx">right</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <span class="nx">i</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">left</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <span class="nx">j</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">right</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <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> <span class="nc">Solution</span><span class="w"> </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="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="nf">sortArray</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">nums</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </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">        </span><span class="k">return</span><span class="w"> </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">    </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="c1">// [left, right)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">right</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">right</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">left</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">left</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">right</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">left</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </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">        </span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </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">        </span><span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">,</span><span class="w"> </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">        </span><span class="n">merge</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">,</span><span class="w"> </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">    </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="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">merge</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">right</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">arr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="o">[</span><span class="n">right</span><span class="w"> </span><span class="o">-</span><span class="w"> </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">        </span><span class="kt">int</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">right</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </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"> </span><span class="o"><</span><span class="w"> </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 class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">mid</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">++]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">right</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">arr</span><span class="o">[</span><span class="n">p</span><span class="o">++]</span><span class="w"> </span><span class="o">=</span><span class="w"> </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">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </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"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="n">left</span><span class="p">,</span><span class="w"> </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">    </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> <span class="nf">sortCount</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">[]</span><span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// 建立排序桶 [min, max]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">minV</span><span class="p">,</span> <span class="nx">maxV</span> <span class="o">:=</span> <span class="nx">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <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> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">arr</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">v</span> <span class="p"><</span> <span class="nx">minV</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">minV</span> <span class="p">=</span> <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> <span class="nx">v</span> <span class="p">></span> <span class="nx">maxV</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">maxV</span> <span class="p">=</span> <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> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <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> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">arr</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 需要 min 偏移</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">// 桶中提取数据</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <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> <span class="nx">i</span><span class="p">,</span> <span class="nx">count</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">buckets</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">;</span> <span class="nx">count</span> <span class="p">></span> <span class="mi">0</span><span class="p">;</span> <span class="nx">count</span><span class="o">--</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// 加回偏移量 minV</span>
</span></span><span class="line"><span class="cl"> <span class="nx">res</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <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> <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> <span class="nf">sortRadix</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">[]</span><span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 默认 10 进制,故桶为 [0, 9] </span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 最大值位数默认</span>
</span></span><span class="line"><span class="cl"> <span class="nx">maxV</span> <span class="o">:=</span> <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> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">arr</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">v</span> <span class="p">></span> <span class="nx">maxV</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">maxV</span> <span class="p">=</span> <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> <span class="o">:=</span> <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">    <span class="c1">// 按低位至高位排序</span>
</span></span><span class="line"><span class="cl"> <span class="nx">step</span> <span class="o">:=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="nx">maxLen</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">buckets</span> <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">// 插入排序桶</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">arr</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">bitV</span> <span class="o">:=</span> <span class="nx">v</span> <span class="o">/</span> <span class="nx">step</span> <span class="o">%</span> <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> <span class="p">=</span> <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> <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">// 更新数组</span>
</span></span><span class="line"><span class="cl"> <span class="nx">idx</span> <span class="o">:=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">bucket</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">buckets</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">bucket</span> <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> <span class="p">=</span> <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> <span class="o">*=</span> <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> <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 6090
</span></span><span class="line"><span class="cl">protected-mode 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 6091
</span></span><span class="line"><span class="cl">protected-mode no
</span></span><span class="line"><span class="cl">slaveof 127.0.0.1 6090 </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 6092
</span></span><span class="line"><span class="cl">protected-mode no
</span></span><span class="line"><span class="cl">slaveof 127.0.0.1 6090 </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 ${PORT}
</span></span><span class="line"><span class="cl">sentinel monitor mymaster 127.0.0.1 6090 2
</span></span><span class="line"><span class="cl">sentinel down-after-milliseconds mymaster 5000
</span></span><span class="line"><span class="cl">sentinel failover-timeout mymaster 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> port in <span class="sb">`</span>seq <span class="m">5000</span> 5002<span class="sb">`</span><span class="p">;</span> <span class="k">do</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  mkdir -p ./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">  <span class="nv">PORT</span><span class="o">=</span><span class="si">${</span><span class="nv">port</span><span class="si">}</span> envsubst < ./redis-sentinel-cluster.tmpl > ./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">  chmod <span class="m">777</span> ./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">  mkdir -p ./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"> </span><span class="s2">"3"</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">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis6090</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-6090/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis6091</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-6091/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis6092</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <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">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">sentinel5000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/sentinel.conf --sentinel"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <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">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">sentinel5001</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/sentinel.conf --sentinel"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <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">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">sentinel5002</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/sentinel.conf --sentinel"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <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 ${PORT}
</span></span><span class="line"><span class="cl">protected-mode no
</span></span><span class="line"><span class="cl">cluster-enabled yes
</span></span><span class="line"><span class="cl">cluster-config-file nodes.conf
</span></span><span class="line"><span class="cl">cluster-node-timeout 5000
</span></span><span class="line"><span class="cl">appendonly 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> port in <span class="sb">`</span>seq <span class="m">7000</span> 7005<span class="sb">`</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  mkdir -p ./redis-cluster/<span class="si">${</span><span class="nv">port</span><span class="si">}</span>/conf
</span></span><span class="line"><span class="cl">  <span class="nv">PORT</span><span class="o">=</span><span class="si">${</span><span class="nv">port</span><span class="si">}</span> envsubst < ./redis-cluster.tmpl > ./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">  chmod <span class="m">666</span> ./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">  mkdir -p ./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"> </span><span class="s2">"3"</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">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-cluster/7000/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7001</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-cluster/7001/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7002</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-cluster/7002/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7003</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-cluster/7003/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7004</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <span class="l">./redis-cluster/7004/data:/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </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">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">redis7005</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="s2">"redis-server /usr/local/etc/redis/redis.conf"</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l">host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </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">      </span>- <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">      </span>- <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 --cluster create 127.0.0.1:7000 127.0.0.1:7001 <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>                           127.0.0.1:7002 127.0.0.1:7003 <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>                           127.0.0.1:7004 127.0.0.1:7005 <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>                           --cluster-replicas <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 -c -p 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> cluster nodes
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">output> 2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c 127.0.0.1:7002@17002 master - <span class="m">0</span> <span class="m">1629082981000</span> <span class="m">3</span> connected 10923-16383
</span></span><span class="line"><span class="cl">fc92c1709a88bdca8e86b9b5a27d035609e46059 127.0.0.1:7001@17001 master - <span class="m">0</span> <span class="m">1629082982000</span> <span class="m">2</span> connected 5461-10922
</span></span><span class="line"><span class="cl">3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4 127.0.0.1:7000@17000 myself,master - <span class="m">0</span> <span class="m">1629082981000</span> <span class="m">1</span> connected 0-5460
</span></span><span class="line"><span class="cl">cf361fc2b72ca2bfd070b282754ad19da7640485 127.0.0.1:7003@17003 slave 3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4 <span class="m">0</span> <span class="m">1629082982590</span> <span class="m">1</span> connected
</span></span><span class="line"><span class="cl">fddc21542112cdcd8857bbfc77481b673e3a543e 127.0.0.1:7004@17004 slave fc92c1709a88bdca8e86b9b5a27d035609e46059 <span class="m">0</span> <span class="m">1629082981586</span> <span class="m">2</span> connected
</span></span><span class="line"><span class="cl">2a5e09014c852fd15c2e54d500c532ec6ee2490e 127.0.0.1:7005@17005 slave 2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c <span class="m">0</span> <span class="m">1629082982088</span> <span class="m">3</span> 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 -p <span class="m">7000</span> DEBUG sleep <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> cluster nodes
</span></span><span class="line"><span class="cl">2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c 127.0.0.1:7002@17002 master - <span class="m">0</span> <span class="m">1629083362653</span> <span class="m">3</span> connected 10923-16383
</span></span><span class="line"><span class="cl">fc92c1709a88bdca8e86b9b5a27d035609e46059 127.0.0.1:7001@17001 master - <span class="m">0</span> <span class="m">1629083361000</span> <span class="m">2</span> connected 5461-10922
</span></span><span class="line"><span class="cl">3bd1b8cbe2e0e30a77dfa2b92dd70ed834bfcba4 127.0.0.1:7000@17000 myself,slave cf361fc2b72ca2bfd070b282754ad19da7640485 <span class="m">0</span> <span class="m">1629083362000</span> <span class="m">7</span> connected
</span></span><span class="line"><span class="cl">cf361fc2b72ca2bfd070b282754ad19da7640485 127.0.0.1:7003@17003 master - <span class="m">0</span> <span class="m">1629083362000</span> <span class="m">7</span> connected 0-5460
</span></span><span class="line"><span class="cl">fddc21542112cdcd8857bbfc77481b673e3a543e 127.0.0.1:7004@17004 slave fc92c1709a88bdca8e86b9b5a27d035609e46059 <span class="m">0</span> <span class="m">1629083362553</span> <span class="m">2</span> connected
</span></span><span class="line"><span class="cl">2a5e09014c852fd15c2e54d500c532ec6ee2490e 127.0.0.1:7005@17005 slave 2fc17db8bb8818ec8ac50f40f07bfbdf1ee8d56c <span class="m">0</span> <span class="m">1629083361647</span> <span class="m">3</span> 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> <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> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"context"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/go-redis/redis/v8"</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> <span class="nx">ctx</span> <span class="p">=</span> <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> <span class="nf">redisAddrList</span><span class="p">()</span> <span class="p">[]</span><span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ip</span> <span class="o">:=</span> <span class="s">"localhost"</span>
</span></span><span class="line"><span class="cl"> <span class="nx">addrList</span> <span class="o">:=</span> <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> <span class="nx">port</span> <span class="o">:=</span> <span class="mi">7000</span><span class="p">;</span> <span class="nx">port</span> <span class="p"><</span> <span class="mi">7006</span><span class="p">;</span> <span class="nx">port</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">addrList</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">addrList</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">"%s:%d"</span><span class="p">,</span> <span class="nx">ip</span><span class="p">,</span> <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> <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> <span class="nf">NewRedisClient</span><span class="p">()</span> <span class="o">*</span><span class="nx">redis</span><span class="p">.</span><span class="nx">ClusterClient</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">redis</span><span class="p">.</span><span class="nf">NewClusterClient</span><span class="p">(</span><span class="o">&</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> <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> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rdb</span> <span class="o">:=</span> <span class="nf">NewRedisClient</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="o">:=</span> <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> <span class="s">"foo"</span><span class="p">,</span> <span class="s">"bar"</span><span class="p">,</span> <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> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <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> <span class="nx">err</span> <span class="o">:=</span> <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> <span class="s">"foo"</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> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <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 » redis-cli -p <span class="m">7000</span> cluster nodes     
</span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000@17000 myself,slave 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 <span class="m">0</span> <span class="m">1736083233000</span> <span class="m">7</span> connected
</span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003@17003 master - <span class="m">0</span> <span class="m">1736083234560</span> <span class="m">7</span> connected 0-5460
</span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004@17004 slave bd393aeacf7de92c8a3816cbfb1c497a310a418b <span class="m">0</span> <span class="m">1736083235665</span> <span class="m">2</span> connected
</span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001@17001 master - <span class="m">0</span> <span class="m">1736083235000</span> <span class="m">2</span> connected 5461-10922
</span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002@17002 slave 57011e62426c833268c7f01b248b0e8f44af443a <span class="m">0</span> <span class="m">1736083234660</span> <span class="m">8</span> connected
</span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005@17005 master - <span class="m">0</span> <span class="m">1736083235563</span> <span class="m">8</span> connected 10923-16383</span></span></code></pre><p>在工作目录下复制一个redis配置 <code>cp -r 7005 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 run -d <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --name redis7006 <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --network host <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    -v ./redis-cluster/7006/conf:/usr/local/etc/redis <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    -v ./redis-cluster/7006/data:/data <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    redis:6.2 redis-server /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 » redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000                                                                                               ing@ing-pc
</span></span><span class="line"><span class="cl">>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000
</span></span><span class="line"><span class="cl">>>> Performing Cluster Check <span class="o">(</span>using node 127.0.0.1:7000<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 0a50949e09aa0ebce0dbad1c8b0f301adbd62780
</span></span><span class="line"><span class="cl">M: 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>0-5460<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates bd393aeacf7de92c8a3816cbfb1c497a310a418b
</span></span><span class="line"><span class="cl">M: bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>5461-10922<span class="o">]</span> <span class="o">(</span><span class="m">5462</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 57011e62426c833268c7f01b248b0e8f44af443a
</span></span><span class="line"><span class="cl">M: 57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>10923-16383<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional 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> All nodes agree about slots configuration.
</span></span><span class="line"><span class="cl">>>> Check <span class="k">for</span> open slots...
</span></span><span class="line"><span class="cl">>>> Check slots coverage...
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> All <span class="m">16384</span> slots covered.
</span></span><span class="line"><span class="cl">>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> New node added 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 » redis-cli -p <span class="m">7000</span> cluster nodes                                                                                                                          ing@ing-pc
</span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000@17000 myself,slave 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 <span class="m">0</span> <span class="m">1736083995000</span> <span class="m">7</span> connected
</span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003@17003 master - <span class="m">0</span> <span class="m">1736083997000</span> <span class="m">7</span> connected 0-5460
</span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004@17004 slave bd393aeacf7de92c8a3816cbfb1c497a310a418b <span class="m">0</span> <span class="m">1736083995380</span> <span class="m">2</span> connected
</span></span><span class="line"><span class="cl"> 127.0.0.1:7006@17006 master - <span class="m">0</span> <span class="m">1736083996384</span> <span class="m">0</span> connected
</span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001@17001 master - <span class="m">0</span> <span class="m">1736083997390</span> <span class="m">2</span> connected 5461-10922
</span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002@17002 slave 57011e62426c833268c7f01b248b0e8f44af443a <span class="m">0</span> <span class="m">1736083996585</span> <span class="m">8</span> connected
</span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005@17005 master - <span class="m">0</span> <span class="m">1736083996000</span> <span class="m">8</span> connected 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">$ redis-cli -p <span class="m">7000</span> --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id d1c7e05fefad29888e1e4eb3a19574b94a280932</span></span></code></pre><p>其中 –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 » redis-cli  -p <span class="m">7000</span> -c cluster slots                                                                                                                  <span class="m">1</span> ↵ ing@ing-pc
</span></span><span class="line"><span class="cl">1<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">5460</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7003</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"0a50949e09aa0ebce0dbad1c8b0f301adbd62780"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7000</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"9a353c214cb677b1e996573b4550875fb0754b65"</span>
</span></span><span class="line"><span class="cl">2<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">5461</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">10922</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7001</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"bd393aeacf7de92c8a3816cbfb1c497a310a418b"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7004</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3b8b46eac23b396e1d0b1adcfb70d086ee539da5"</span>
</span></span><span class="line"><span class="cl">3<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">10923</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">16383</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7005</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"57011e62426c833268c7f01b248b0e8f44af443a"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7002</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3c21e101ea340698769de95812a98275693d3b2d"</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 » redis-cli -p <span class="m">7000</span> --cluster reshard 127.0.0.1:7000                                                                                                       ing@ing-pc
</span></span><span class="line"><span class="cl">>>> Performing Cluster Check <span class="o">(</span>using node 127.0.0.1:7000<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 0a50949e09aa0ebce0dbad1c8b0f301adbd62780
</span></span><span class="line"><span class="cl">M: 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>0-5460<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates bd393aeacf7de92c8a3816cbfb1c497a310a418b
</span></span><span class="line"><span class="cl">M: d1c7e05fefad29888e1e4eb3a19574b94a280932 127.0.0.1:7006
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">M: bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>5461-10922<span class="o">]</span> <span class="o">(</span><span class="m">5462</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 57011e62426c833268c7f01b248b0e8f44af443a
</span></span><span class="line"><span class="cl">M: 57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>10923-16383<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional 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> All nodes agree about slots configuration.
</span></span><span class="line"><span class="cl">>>> Check <span class="k">for</span> open slots...
</span></span><span class="line"><span class="cl">>>> Check slots coverage...
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> All <span class="m">16384</span> slots covered.
</span></span><span class="line"><span class="cl">How many slots <span class="k">do</span> you want to move <span class="o">(</span>from <span class="m">1</span> to 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> All <span class="m">16384</span> slots covered.
</span></span><span class="line"><span class="cl">How many slots <span class="k">do</span> you want to move <span class="o">(</span>from <span class="m">1</span> to 16384<span class="o">)</span>? <span class="m">4096</span>
</span></span><span class="line"><span class="cl">What is the receiving node ID? d1c7e05fefad29888e1e4eb3a19574b94a280932
</span></span><span class="line"><span class="cl">Please enter all the <span class="nb">source</span> node IDs.
</span></span><span class="line"><span class="cl">  Type <span class="s1">'all'</span> to use all the nodes as <span class="nb">source</span> nodes <span class="k">for</span> the <span class="nb">hash</span> slots.
</span></span><span class="line"><span class="cl">  Type <span class="s1">'done'</span> once you entered all the <span class="nb">source</span> nodes IDs.
</span></span><span class="line"><span class="cl">Source node <span class="c1">#1: all</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Ready to move <span class="m">4096</span> slots.
</span></span><span class="line"><span class="cl">  Source nodes:
</span></span><span class="line"><span class="cl">    M: 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003
</span></span><span class="line"><span class="cl">       slots:<span class="o">[</span>0-5460<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">       <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">    M: bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001
</span></span><span class="line"><span class="cl">       slots:<span class="o">[</span>5461-10922<span class="o">]</span> <span class="o">(</span><span class="m">5462</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">       <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">    M: 57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005
</span></span><span class="line"><span class="cl">       slots:<span class="o">[</span>10923-16383<span class="o">]</span> <span class="o">(</span><span class="m">5461</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">       <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">  Destination node:
</span></span><span class="line"><span class="cl">    M: d1c7e05fefad29888e1e4eb3a19574b94a280932 127.0.0.1:7006
</span></span><span class="line"><span class="cl">       slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">  Resharding plan:
</span></span><span class="line"><span class="cl">    Moving slot <span class="m">5461</span> from bd393aeacf7de92c8a3816cbfb1c497a310a418b
</span></span><span class="line"><span class="cl">    Moving slot <span class="m">5462</span> from bd393aeacf7de92c8a3816cbfb1c497a310a418b
</span></span><span class="line"><span class="cl">    ....</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 » redis-cli -p <span class="m">7000</span> -c cluster slots                                                                                                                       ing@ing-pc
</span></span><span class="line"><span class="cl">1<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">1364</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7006</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"d1c7e05fefad29888e1e4eb3a19574b94a280932"</span>
</span></span><span class="line"><span class="cl">2<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">1365</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">5460</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7003</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"0a50949e09aa0ebce0dbad1c8b0f301adbd62780"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7000</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"9a353c214cb677b1e996573b4550875fb0754b65"</span>
</span></span><span class="line"><span class="cl">3<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">5461</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">6826</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7006</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"d1c7e05fefad29888e1e4eb3a19574b94a280932"</span>
</span></span><span class="line"><span class="cl">4<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">6827</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">10922</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7001</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"bd393aeacf7de92c8a3816cbfb1c497a310a418b"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7004</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3b8b46eac23b396e1d0b1adcfb70d086ee539da5"</span>
</span></span><span class="line"><span class="cl">5<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">10923</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">12287</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7006</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"d1c7e05fefad29888e1e4eb3a19574b94a280932"</span>
</span></span><span class="line"><span class="cl">6<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">12288</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">16383</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7005</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"57011e62426c833268c7f01b248b0e8f44af443a"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7002</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3c21e101ea340698769de95812a98275693d3b2d"</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 stop 7006</code>,使用<code>CLUSTER 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 » redis-cli -p <span class="m">7000</span> -c CLUSTER FORGET d1c7e05fefad29888e1e4eb3a19574b94a280932                                                                             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 » redis-cli -p <span class="m">7000</span> -c CLUSTER NODES                                                                                                                       ing@ing-pc
</span></span><span class="line"><span class="cl">9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000@17000 myself,slave 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 <span class="m">0</span> <span class="m">1736085038000</span> <span class="m">7</span> connected
</span></span><span class="line"><span class="cl">0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003@17003 master - <span class="m">0</span> <span class="m">1736085039571</span> <span class="m">7</span> connected 1365-5460
</span></span><span class="line"><span class="cl">3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004@17004 slave bd393aeacf7de92c8a3816cbfb1c497a310a418b <span class="m">0</span> <span class="m">1736085039673</span> <span class="m">2</span> connected
</span></span><span class="line"><span class="cl">bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001@17001 master - <span class="m">0</span> <span class="m">1736085038667</span> <span class="m">2</span> connected 6827-10922
</span></span><span class="line"><span class="cl">3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002@17002 slave 57011e62426c833268c7f01b248b0e8f44af443a <span class="m">0</span> <span class="m">1736085039068</span> <span class="m">8</span> connected
</span></span><span class="line"><span class="cl">57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005@17005 master - <span class="m">0</span> <span class="m">1736085039000</span> <span class="m">8</span> connected 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 » redis-cli -p <span class="m">7000</span> -c CLUSTER SLOTS                                                                                                                       ing@ing-pc
</span></span><span class="line"><span class="cl">1<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">1365</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">5460</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7003</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"0a50949e09aa0ebce0dbad1c8b0f301adbd62780"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7000</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"9a353c214cb677b1e996573b4550875fb0754b65"</span>
</span></span><span class="line"><span class="cl">2<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">6827</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">10922</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7001</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"bd393aeacf7de92c8a3816cbfb1c497a310a418b"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7004</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3b8b46eac23b396e1d0b1adcfb70d086ee539da5"</span>
</span></span><span class="line"><span class="cl">3<span class="o">)</span> 1<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">12288</span>
</span></span><span class="line"><span class="cl">   2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">16383</span>
</span></span><span class="line"><span class="cl">   3<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7005</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"57011e62426c833268c7f01b248b0e8f44af443a"</span>
</span></span><span class="line"><span class="cl">   4<span class="o">)</span> 1<span class="o">)</span> <span class="s2">"127.0.0.1"</span>
</span></span><span class="line"><span class="cl">      2<span class="o">)</span> <span class="o">(</span>integer<span class="o">)</span> <span class="m">7002</span>
</span></span><span class="line"><span class="cl">      3<span class="o">)</span> <span class="s2">"3c21e101ea340698769de95812a98275693d3b2d"</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 » redis-cli -p <span class="m">7000</span> -c CLUSTER INFO                                                                                                                        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 » redis-cli --cluster fix 127.0.0.1:7000                                                                                                               <span class="m">1</span> ↵ ing@ing-pc
</span></span><span class="line"><span class="cl">127.0.0.1:7003 <span class="o">(</span>0a50949e...<span class="o">)</span> -> <span class="m">0</span> keys <span class="p">|</span> <span class="m">4096</span> slots <span class="p">|</span> <span class="m">1</span> slaves.
</span></span><span class="line"><span class="cl">127.0.0.1:7001 <span class="o">(</span>bd393aea...<span class="o">)</span> -> <span class="m">0</span> keys <span class="p">|</span> <span class="m">4096</span> slots <span class="p">|</span> <span class="m">1</span> slaves.
</span></span><span class="line"><span class="cl">127.0.0.1:7005 <span class="o">(</span>57011e62...<span class="o">)</span> -> <span class="m">1</span> keys <span class="p">|</span> <span class="m">4096</span> slots <span class="p">|</span> <span class="m">1</span> slaves.
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> <span class="m">1</span> keys in <span class="m">3</span> masters.
</span></span><span class="line"><span class="cl">0.00 keys per slot on average.
</span></span><span class="line"><span class="cl">>>> Performing Cluster Check <span class="o">(</span>using node 127.0.0.1:7000<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 9a353c214cb677b1e996573b4550875fb0754b65 127.0.0.1:7000
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 0a50949e09aa0ebce0dbad1c8b0f301adbd62780
</span></span><span class="line"><span class="cl">M: 0a50949e09aa0ebce0dbad1c8b0f301adbd62780 127.0.0.1:7003
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>1365-5460<span class="o">]</span> <span class="o">(</span><span class="m">4096</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3b8b46eac23b396e1d0b1adcfb70d086ee539da5 127.0.0.1:7004
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates bd393aeacf7de92c8a3816cbfb1c497a310a418b
</span></span><span class="line"><span class="cl">M: bd393aeacf7de92c8a3816cbfb1c497a310a418b 127.0.0.1:7001
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>6827-10922<span class="o">]</span> <span class="o">(</span><span class="m">4096</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional replica<span class="o">(</span>s<span class="o">)</span>
</span></span><span class="line"><span class="cl">S: 3c21e101ea340698769de95812a98275693d3b2d 127.0.0.1:7002
</span></span><span class="line"><span class="cl">   slots: <span class="o">(</span><span class="m">0</span> slots<span class="o">)</span> slave
</span></span><span class="line"><span class="cl">   replicates 57011e62426c833268c7f01b248b0e8f44af443a
</span></span><span class="line"><span class="cl">M: 57011e62426c833268c7f01b248b0e8f44af443a 127.0.0.1:7005
</span></span><span class="line"><span class="cl">   slots:<span class="o">[</span>12288-16383<span class="o">]</span> <span class="o">(</span><span class="m">4096</span> slots<span class="o">)</span> master
</span></span><span class="line"><span class="cl">   <span class="m">1</span> additional 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> All nodes agree about slots configuration.
</span></span><span class="line"><span class="cl">>>> Check <span class="k">for</span> open slots...
</span></span><span class="line"><span class="cl">>>> Check slots coverage...
</span></span><span class="line"><span class="cl"><span class="o">[</span>ERR<span class="o">]</span> Not all <span class="m">16384</span> slots are covered by nodes.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">>>> Fixing slots coverage...
</span></span><span class="line"><span class="cl">The following uncovered slots have no keys across the 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 these slots by covering with a random node? <span class="o">(</span><span class="nb">type</span> <span class="s1">'yes'</span> to accept<span class="o">)</span>: yes
</span></span><span class="line"><span class="cl">>>> Covering slot <span class="m">5470</span> with 127.0.0.1:7005
</span></span><span class="line"><span class="cl">>>> Covering slot <span class="m">11756</span> with 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 » redis-cli --cluster check 127.0.0.1:7000  
</span></span><span class="line"><span class="cl"> ...
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> All nodes agree about slots configuration.
</span></span><span class="line"><span class="cl">>>> Check <span class="k">for</span> open slots...
</span></span><span class="line"><span class="cl">>>> Check slots coverage...
</span></span><span class="line"><span class="cl"><span class="o">[</span>OK<span class="o">]</span> All <span class="m">16384</span> slots 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 » redis-cli -c -p <span class="m">7000</span> CLUSTER INFO                                                                                                                    <span class="m">1</span> ↵ 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 - 1) / 2</code></li>
<li>左子节点下标为 <code>2 * k + 1</code>,右子节点下标为 <code>2 * k + 2</code></li>
<li>最后一个非叶子节点的下标为 <code>(size - 2) / 2</code> (即最后一个节点 <code>size - 1</code>的父节点 <code>((size - 1) - 1) / 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> <span class="nx">MinHeap</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">heap</span> <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> <span class="nf">NewMinHeap</span><span class="p">()</span> <span class="o">*</span><span class="nx">MinHeap</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">&</span><span class="nx">MinHeap</span><span class="p">{</span><span class="nx">heap</span><span class="p">:</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> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">up</span><span class="p">(</span><span class="nx">k</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">k</span> <span class="o">==</span> <span class="mi">0</span> <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> <span class="nx">pk</span> <span class="o">:=</span> <span class="p">(</span><span class="nx">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">k</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <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 class="p">></span> <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 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> <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 class="p">=</span> <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 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> <span class="p">=</span> <span class="nx">pk</span>
</span></span><span class="line"><span class="cl"> <span class="nx">pk</span> <span class="p">=</span> <span class="p">(</span><span class="nx">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <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> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">down</span><span class="p">(</span><span class="nx">k</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</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">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> <span class="o">:=</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">2</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">k</span> <span class="o"><=</span> <span class="nx">last</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="o">:=</span> <span class="mi">2</span><span class="o">*</span><span class="nx">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="c1">// left child</span>
</span></span><span class="line"><span class="cl"> <span class="nx">childV</span> <span class="o">:=</span> <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> <span class="o">:=</span> <span class="nx">child</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">right</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="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 class="p"><</span> <span class="nx">childV</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">child</span> <span class="p">=</span> <span class="nx">right</span>
</span></span><span class="line"><span class="cl"> <span class="nx">childV</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="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> <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 class="p">></span> <span class="nx">childV</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="nx">k</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="nx">child</span><span class="p">]</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="nx">child</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="nx">k</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">k</span> <span class="p">=</span> <span class="nx">child</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <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> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">add</span><span class="p">(</span><span class="nx">v</span> <span class="kt">int</span><span class="p">)</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="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> <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> <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></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">pop</span><span class="p">()</span> <span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">bool</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</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">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <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> <span class="o">:=</span> <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> <span class="p">=</span> <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> <span class="p">=</span> <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> <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="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="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> <span class="nx">res</span><span class="p">,</span> <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> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">MinHeap</span><span class="p">)</span> <span class="nf">heapify</span><span class="p">(</span><span class="nx">arr</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</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="nx">arr</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</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">2</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">i</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">--</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">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>