<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://zhizheng.github.io/atom.xml" rel="self" type="application/atom+xml" /><link href="https://zhizheng.github.io/" rel="alternate" type="text/html" /><updated>2025-09-07T05:01:06+00:00</updated><id>https://zhizheng.github.io/atom.xml</id><title type="html">爱知笔记</title><subtitle>Whatever u do, Remember why you started.</subtitle><author><name>Zhizheng Zhang</name></author><entry><title type="html">使用 maven-assembly-plugin 打包</title><link href="https://zhizheng.github.io/post/maven-assembly-plugin/" rel="alternate" type="text/html" title="使用 maven-assembly-plugin 打包" /><published>2018-08-17T05:29:01+00:00</published><updated>2018-08-17T05:29:01+00:00</updated><id>https://zhizheng.github.io/post/maven-assembly-plugin</id><content type="html" xml:base="https://zhizheng.github.io/post/maven-assembly-plugin/"><![CDATA[<p>现在有这样一个需求，在一个 java 项目的源码根目录下增加一个 Dockerfile 文件，先把项目打包成一个完整的压缩包 your-app-bin.zip（包含 bin、config、lib 等目录），再把压缩包 your-app-bin.zip 和 Dockerfile 文件一起打包成另一个压缩包 your-app-docker.zip（your-app-bin.zip 和 Dockerfile 文件平级）。</p>

<p>因项目使用 maven 管理，并使用 maven-assembly-plugin 打包。可以在项目 pom.xml 中 maven-assembly-plugin 的配置下增加第二个打包配置文件。</p>

<!-- more -->

<h2 id="pomxml-中-maven-assembly-plugin-插件配置">pom.xml 中 maven-assembly-plugin 插件配置</h2>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- The configuration of maven-assembly-plugin --&gt;</span>
<span class="nt">&lt;plugin&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>maven-assembly-plugin<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>2.4.1<span class="nt">&lt;/version&gt;</span>
    <span class="c">&lt;!-- The configuration of the plugin --&gt;</span>
    <span class="nt">&lt;configuration&gt;</span>
        <span class="nt">&lt;finalName&gt;</span>your-app<span class="nt">&lt;/finalName&gt;</span>
        <span class="c">&lt;!-- append assembly id in release file name --&gt;</span>
        <span class="nt">&lt;appendAssemblyId&gt;</span>true<span class="nt">&lt;/appendAssemblyId&gt;</span>
        <span class="c">&lt;!-- Specifies the configuration file of the assembly plugin --&gt;</span>
        <span class="nt">&lt;descriptors&gt;</span>
            <span class="nt">&lt;descriptor&gt;</span>src/main/assembly/bin.xml<span class="nt">&lt;/descriptor&gt;</span>
            <span class="nt">&lt;descriptor&gt;</span>src/main/assembly/docker.xml<span class="nt">&lt;/descriptor&gt;</span>
        <span class="nt">&lt;/descriptors&gt;</span>
    <span class="nt">&lt;/configuration&gt;</span>
    <span class="nt">&lt;executions&gt;</span>
        <span class="nt">&lt;execution&gt;</span>
            <span class="nt">&lt;id&gt;</span>make-assembly<span class="nt">&lt;/id&gt;</span>
            <span class="nt">&lt;phase&gt;</span>package<span class="nt">&lt;/phase&gt;</span>
            <span class="nt">&lt;goals&gt;</span>
                <span class="nt">&lt;goal&gt;</span>single<span class="nt">&lt;/goal&gt;</span>
            <span class="nt">&lt;/goals&gt;</span>
        <span class="nt">&lt;/execution&gt;</span>
    <span class="nt">&lt;/executions&gt;</span>
<span class="nt">&lt;/plugin&gt;</span>
</code></pre></div></div>

<h2 id="binxml-内容">bin.xml 内容</h2>

<p>常规编写即可，没什么特殊要求。</p>

<h2 id="dockerxml-示例">docker.xml 示例</h2>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;assembly&gt;</span>
	<span class="nt">&lt;id&gt;</span>docker<span class="nt">&lt;/id&gt;</span>
	<span class="nt">&lt;formats&gt;</span>
		<span class="nt">&lt;format&gt;</span>zip<span class="nt">&lt;/format&gt;</span>
	<span class="nt">&lt;/formats&gt;</span>
	<span class="nt">&lt;dependencySets&gt;</span>
	<span class="nt">&lt;/dependencySets&gt;</span>
	<span class="nt">&lt;fileSets&gt;</span>
		<span class="nt">&lt;fileSet&gt;</span>
			<span class="nt">&lt;directory&gt;</span>${project.basedir}/target<span class="nt">&lt;/directory&gt;</span>
			<span class="nt">&lt;outputDirectory&gt;</span>.<span class="nt">&lt;/outputDirectory&gt;</span>
			<span class="nt">&lt;includes&gt;</span>
				<span class="nt">&lt;include&gt;</span>*.zip<span class="nt">&lt;/include&gt;</span>
			<span class="nt">&lt;/includes&gt;</span>
		<span class="nt">&lt;/fileSet&gt;</span>

		<span class="nt">&lt;fileSet&gt;</span>
			<span class="nt">&lt;directory&gt;</span>${project.basedir}<span class="nt">&lt;/directory&gt;</span>
			<span class="nt">&lt;outputDirectory&gt;</span>.<span class="nt">&lt;/outputDirectory&gt;</span>
			<span class="nt">&lt;includes&gt;</span>
				<span class="nt">&lt;include&gt;</span>Dockerfile<span class="nt">&lt;/include&gt;</span>
			<span class="nt">&lt;/includes&gt;</span>
		<span class="nt">&lt;/fileSet&gt;</span>
	<span class="nt">&lt;/fileSets&gt;</span>
<span class="nt">&lt;/assembly&gt;</span>
</code></pre></div></div>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li>
    <p><a href="http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html" target="_blank" rel="nofollow noopener noreferrer">Apache Maven Assembly Plugin</a></p>
  </li>
  <li>
    <p><a href="https://blog.csdn.net/u013174217/article/details/53300818" target="_blank" rel="nofollow noopener noreferrer">使用maven-assembly-plugin打包，assembly的语法介绍(同时打多个包、排除依赖包、文件更改别名、自定义路径)</a></p>
  </li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Maven" /><category term="assembly" /><category term="plugin" /><summary type="html"><![CDATA[现在有这样一个需求，在一个 java 项目的源码根目录下增加一个 Dockerfile 文件，先把项目打包成一个完整的压缩包 your-app-bin.zip（包含 bin、config、lib 等目录），再把压缩包 your-app-bin.zip 和 Dockerfile 文件一起打包成另一个压缩包 your-app-docker.zip（your-app-bin.zip 和 Dockerfile 文件平级）。 因项目使用 maven 管理，并使用 maven-assembly-plugin 打包。可以在项目 pom.xml 中 maven-assembly-plugin 的配置下增加第二个打包配置文件。]]></summary></entry><entry><title type="html">Linux 丢失或误删除 libc.so.6 的处理方法</title><link href="https://zhizheng.github.io/post/linux-missing-libc.so.6/" rel="alternate" type="text/html" title="Linux 丢失或误删除 libc.so.6 的处理方法" /><published>2018-05-08T09:33:01+00:00</published><updated>2018-05-08T09:33:01+00:00</updated><id>https://zhizheng.github.io/post/linux-missing-libc.so.6</id><content type="html" xml:base="https://zhizheng.github.io/post/linux-missing-libc.so.6/"><![CDATA[<p>因为要编写 markdown 并生成 html，选择安装 Atom。先是下载了最新版 1.26.1，安装后运行提示主机上 gblic 过时。又下载了一个较旧的版本 1.12.7，安装后运行还是提示主机上 gblic 过时，需要 glibc-2.14。因此决定升级主机 glibc 版本。</p>

<!-- more -->

<h2 id="环境说明">环境说明</h2>

<ul>
  <li>操作系统：Debian 7 (wheezy)</li>
  <li>glibc: glibc-2.13</li>
  <li>Atom: 1.26.1 &amp; 1.12.7</li>
</ul>

<h2 id="升级-glibc-到新版本">升级 glibc 到新版本</h2>

<ol>
  <li>下载 <a href="http://ftp.gnu.org/gnu/glibc/glibc-2.14.1.tar.gz" target="_blank" rel="nofollow noopener noreferrer">http://ftp.gnu.org/gnu/glibc/glibc-2.14.1.tar.gz</a></li>
  <li>
    <p>编译</p>

    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">cd</span> /builds
 <span class="nb">tar </span>zxf /path/to/glibc-2.14.1.tar.gz
 <span class="nb">cd</span> /builds/glibc-2.14.1
 <span class="nb">mkdir </span>build
 <span class="nb">cd </span>build
 ../configure <span class="nt">--prefix</span><span class="o">=</span>/opt/glibc/2.14.1
 <span class="nb">sudo </span>apt-get <span class="nb">install </span>gawk <span class="c"># 解决 make 报错</span>
 make <span class="nt">-j4</span>
 <span class="nb">sudo </span>make <span class="nb">install</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>修改系统链接指向新动态库</p>

    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">cd</span> /lib/x86_64-linux-gnu
 <span class="nb">unlink </span>libc.so.6
 <span class="nb">ln</span> <span class="nt">-s</span> /opt/glibc/2.14.1/lib/libc-2.14.1.so libc.so.6 <span class="c"># 命令报错，提示找不到 libc.so.6，其它好多系统内置命令也无法运行</span>
</code></pre></div>    </div>
  </li>
</ol>

<h2 id="找不到-libcso6-问题解决">找不到 libc.so.6 问题解决</h2>

<ol>
  <li>使用光盘修复系统</li>
  <li>
    <p>执行以下命令</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> LD_PRELOAD=/lib/x86_64-linux-gnu/libc-2.13.so ln -s /opt/glibc/2.14.1/lib/libc-2.14.1.so libc.so.6
</code></pre></div>    </div>

    <p>或</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> LD_PRELOAD=/opt/glibc/2.14.1/lib/libc-2.14.1.so ln -s /opt/glibc/2.14.1/lib/libc-2.14.1.so libc.so.6
</code></pre></div>    </div>
  </li>
</ol>

<p>推荐使用第 2 种方法。</p>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="http://www.cnblogs.com/qingchen1984/p/5731419.html" target="_blank" rel="nofollow noopener noreferrer">误删除libc.so.6的解决方法</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Linux" /><category term="missing" /><category term="libc.so.6" /><summary type="html"><![CDATA[因为要编写 markdown 并生成 html，选择安装 Atom。先是下载了最新版 1.26.1，安装后运行提示主机上 gblic 过时。又下载了一个较旧的版本 1.12.7，安装后运行还是提示主机上 gblic 过时，需要 glibc-2.14。因此决定升级主机 glibc 版本。]]></summary></entry><entry><title type="html">Excel 自动填充数据</title><link href="https://zhizheng.github.io/post/autofill-in-excel/" rel="alternate" type="text/html" title="Excel 自动填充数据" /><published>2018-04-16T17:01:07+00:00</published><updated>2018-04-16T17:01:07+00:00</updated><id>https://zhizheng.github.io/post/autofill-in-excel</id><content type="html" xml:base="https://zhizheng.github.io/post/autofill-in-excel/"><![CDATA[<p>现在有一个需求，在 excel 表格某一列中要填入 80000 个连续的手机号码，从 18900000001 到 18900080000。</p>

<h2 id="手工录入">手工录入</h2>

<ul>
  <li>一个号码一个号码地录入，十分耗时，只录入少数数据时适用。本方法对于填充 80000 个单元格的数据不适用</li>
  <li>先录入第一个号码，再通过托动单元格右下角的填充柄填充数据。本方法对于填充 80000 个单元格的数据也不太适用</li>
</ul>

<h2 id="序列填充">序列填充</h2>

<p>在单元格内填入第一个手机号码 18900000001</p>

<!-- more -->

<p><img src="/uploads/2018/04/excel-autofill_1.png" alt="excel-autofill_1.png" /></p>

<p>在菜单中选择“编辑”-&gt;“填充”-&gt;“序列”</p>

<p><img src="/uploads/2018/04/excel-autofill_2.png" alt="excel-autofill_2.png" /></p>

<p>在弹出的窗口中，序列产生在选择“列”，类型选择“等差数列”，步长值填写“1”，终止值填写“18900080000“，点击确定按钮</p>

<p><img src="/uploads/2018/04/excel-autofill_3.png" alt="excel-autofill_3.png" /></p>

<p>序列填充完成后，可以看到，第一个值为 18900000001，最后一个值为 18900080000</p>

<p><img src="/uploads/2018/04/excel-autofill_4.png" alt="excel-autofill_4.png" />
<img src="/uploads/2018/04/excel-autofill_5.png" alt="excel-autofill_5.png" /></p>

<h2 id="注意事项">注意事项</h2>

<ul>
  <li>Excel 2003（.xls）最大行数为 65536，Excel 2007（.xlsx）最大行数为 1048576</li>
  <li>Excel 2003（.xls）最大列数为 256，Excel 2007（.xlsx）最大列数为 16384</li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Excel" /><category term="autofill" /><summary type="html"><![CDATA[现在有一个需求，在 excel 表格某一列中要填入 80000 个连续的手机号码，从 18900000001 到 18900080000。 手工录入 一个号码一个号码地录入，十分耗时，只录入少数数据时适用。本方法对于填充 80000 个单元格的数据不适用 先录入第一个号码，再通过托动单元格右下角的填充柄填充数据。本方法对于填充 80000 个单元格的数据也不太适用 序列填充 在单元格内填入第一个手机号码 18900000001]]></summary></entry><entry><title type="html">Linux 端口转发（映射）</title><link href="https://zhizheng.github.io/post/linux-port-forwarding/" rel="alternate" type="text/html" title="Linux 端口转发（映射）" /><published>2018-04-14T09:24:01+00:00</published><updated>2018-04-14T09:24:01+00:00</updated><id>https://zhizheng.github.io/post/linux-port-forwarding</id><content type="html" xml:base="https://zhizheng.github.io/post/linux-port-forwarding/"><![CDATA[<p>当内网集群只开放一台主机（一般称为跳板机或中转机）可以被外界访问时，我们在跳板机或中转机上可以通过 ssh 连接到其它内网主机。</p>

<p>但是，当我们要通过本地浏览器访问某台内网主机上的 web 程序（或通过数据库客户端访问某台内网主机上的数据库）时，要如何做呢？</p>

<p>一种可靠的方法是通过端口转发（映射），架构示意图如下：</p>

<!-- more -->

<p><img src="/uploads/2018/04/port-forwarding_arch.png" alt="port-forwarding_arch.png" /></p>

<p>具体可以通过 SecureCrt 或 Xshell 实现，具体方法如下：</p>

<h2 id="securecrt">SecureCrt</h2>

<p>确定连接跳板机或中转机的端口（当使用安全网关程序登录时，端口是随机的），可以看出 port 是 3551</p>

<p><img src="/uploads/2018/04/port-forwarding_1.png" alt="port-forwarding_1.png" />
<img src="/uploads/2018/04/port-forwarding_2.png" alt="port-forwarding_2.png" /></p>

<p>新建一个会话，ip 127.0.0.1，端口 3551，并将所有的端口转发（映射）都配置上</p>

<p><img src="/uploads/2018/04/port-forwarding_3.png" alt="port-forwarding_3.png" />
<img src="/uploads/2018/04/port-forwarding_4.png" alt="port-forwarding_4.png" />
<img src="/uploads/2018/04/port-forwarding_5.png" alt="port-forwarding_5.png" />
<img src="/uploads/2018/04/port-forwarding_6.png" alt="port-forwarding_6.png" /></p>

<p>连接刚建立的会话，连接成功后，就可以通过本机访问 web 程序或数据库了</p>

<blockquote>
  <p>http://127.0.0.106:8080/</p>
</blockquote>

<blockquote>
  <p>jdbc:mysql://127.0.0.15:3306?test</p>
</blockquote>

<h2 id="xshell">Xshell</h2>

<p>Xshell 操作和 SecureCrt 类似，不再赘述。</p>

<h2 id="重要说明">重要说明</h2>

<p>跳板机或中转机连接关闭后，端口转发（映射）全部失效。</p>]]></content><author><name>Zhizheng Zhang</name></author><category term="Linux" /><category term="Port" /><category term="Forwarding" /><category term="SecureCrt" /><category term="Xshell" /><summary type="html"><![CDATA[当内网集群只开放一台主机（一般称为跳板机或中转机）可以被外界访问时，我们在跳板机或中转机上可以通过 ssh 连接到其它内网主机。 但是，当我们要通过本地浏览器访问某台内网主机上的 web 程序（或通过数据库客户端访问某台内网主机上的数据库）时，要如何做呢？ 一种可靠的方法是通过端口转发（映射），架构示意图如下：]]></summary></entry><entry><title type="html">Linux 用户密码过期</title><link href="https://zhizheng.github.io/post/linux-password-expire/" rel="alternate" type="text/html" title="Linux 用户密码过期" /><published>2018-04-02T13:21:01+00:00</published><updated>2018-04-02T13:21:01+00:00</updated><id>https://zhizheng.github.io/post/linux-password-expire</id><content type="html" xml:base="https://zhizheng.github.io/post/linux-password-expire/"><![CDATA[<p>今天，在工作中遇到了 linux 用户密码过期的问题，使用 chage 命令可以设置用户账号和密码的有效期。</p>

<p>chage 命令用法如下</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>user@server:~<span class="nv">$ </span>chage <span class="nt">-h</span>
Usage: chage <span class="o">[</span>options] LOGIN

Options:
  <span class="nt">-d</span>, <span class="nt">--lastday</span> LAST_DAY        <span class="nb">set date </span>of last password change to LAST_DAY
  <span class="nt">-E</span>, <span class="nt">--expiredate</span> EXPIRE_DATE  <span class="nb">set </span>account expiration <span class="nb">date </span>to EXPIRE_DATE
  <span class="nt">-h</span>, <span class="nt">--help</span>                    display this <span class="nb">help </span>message and <span class="nb">exit</span>
  <span class="nt">-I</span>, <span class="nt">--inactive</span> INACTIVE       <span class="nb">set </span>password inactive after expiration
                                to INACTIVE
  <span class="nt">-l</span>, <span class="nt">--list</span>                    show account aging information
  <span class="nt">-m</span>, <span class="nt">--mindays</span> MIN_DAYS        <span class="nb">set </span>minimum number of days before password
                                change to MIN_DAYS
  <span class="nt">-M</span>, <span class="nt">--maxdays</span> MAX_DAYS        <span class="nb">set </span>maximim number of days before password
                                change to MAX_DAYS
  <span class="nt">-R</span>, <span class="nt">--root</span> CHROOT_DIR         directory to <span class="nb">chroot </span>into
  <span class="nt">-W</span>, <span class="nt">--warndays</span> WARN_DAYS      <span class="nb">set </span>expiration warning days to WARN_DAYS
</code></pre></div></div>

<p>其中，-E 设置账号过期时间，-M 设置密码过期时间，-I 设置密码失效时间。</p>

<!-- more -->

<p>用户 user 查看自己账号和密码的有效期</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>user@server:~<span class="nv">$ </span>chage <span class="nt">-l</span> user
Last password change					: Nov 28, 2016
Password expires					: never
Password inactive					: never
Account expires						: never
Minimum number of days between password change		: <span class="nt">-1</span>
Maximum number of days between password change		: 99999
Number of days of warning before password expires	: 7
</code></pre></div></div>

<p>设置账号 user 的过期时间为 2018 年 12 月 31 日</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@server:~# chage <span class="nt">-E</span> <span class="s2">"2018-12-31"</span> user
</code></pre></div></div>

<p>设置账号 user 永不过期</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@server:~# chage <span class="nt">-E</span> <span class="nt">-1</span> user
</code></pre></div></div>

<p>设置账号 user 立即过期</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@server:~# chage <span class="nt">-E</span> 0 user
</code></pre></div></div>

<p>设置账号 user 的密码在 MAX_DAYS=30 天后过期，此时必须先修改密码才能登录系统</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@server:~# chage <span class="nt">-M</span> 30 user
</code></pre></div></div>

<p>设置账号 user 的密码在 MAX_DAYS+3 天后失效，此时不能登录系统，只能求助于管理员</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@server:~# chage <span class="nt">-I</span> 3 user
</code></pre></div></div>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="http://m.blog.itpub.net/15498/viewspace-2070548/" target="_blank" rel="nofollow noopener noreferrer">如何设置Linux普通用户密码永不过期</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Linux" /><category term="password" /><category term="expire" /><category term="command" /><summary type="html"><![CDATA[今天，在工作中遇到了 linux 用户密码过期的问题，使用 chage 命令可以设置用户账号和密码的有效期。 chage 命令用法如下 user@server:~$ chage -h Usage: chage [options] LOGIN Options: -d, --lastday LAST_DAY set date of last password change to LAST_DAY -E, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE -h, --help display this help message and exit -I, --inactive INACTIVE set password inactive after expiration to INACTIVE -l, --list show account aging information -m, --mindays MIN_DAYS set minimum number of days before password change to MIN_DAYS -M, --maxdays MAX_DAYS set maximim number of days before password change to MAX_DAYS -R, --root CHROOT_DIR directory to chroot into -W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS 其中，-E 设置账号过期时间，-M 设置密码过期时间，-I 设置密码失效时间。]]></summary></entry><entry><title type="html">Redis 集群搭建</title><link href="https://zhizheng.github.io/post/redis-cluster/" rel="alternate" type="text/html" title="Redis 集群搭建" /><published>2018-04-02T10:05:01+00:00</published><updated>2018-04-02T10:05:01+00:00</updated><id>https://zhizheng.github.io/post/redis-cluster</id><content type="html" xml:base="https://zhizheng.github.io/post/redis-cluster/"><![CDATA[<h2 id="源码下载">源码下载</h2>

<p><a href="http://download.redis.io/releases/redis-3.2.11.tar.gz" target="_blank" rel="nofollow noopener noreferrer">http://download.redis.io/releases/redis-3.2.11.tar.gz</a></p>

<h2 id="源码编译">源码编译</h2>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">tar </span>zxvf redis-3.2.11.tar.gz
<span class="nb">cd</span> ~/redis-3.2.11
make
</code></pre></div></div>

<h2 id="集群规划及配置">集群规划及配置</h2>

<p>创建集群目录，将编译好的命令文件复制到 bin 目录</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> /usr/local/redis-cluster/bin
<span class="nb">cd</span> ~/redis-3.2.11/src
<span class="nb">cp </span>mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server redis-trib.rb /usr/local/redis-cluster/bin
</code></pre></div></div>

<!-- more -->

<p>创建 6 个 redis 实例目录，并将 redis 配置文件复制到各实例目录</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /usr/local/redis-cluster

<span class="nb">mkdir</span> <span class="nt">-p</span> 9001/data
<span class="nb">mkdir</span> <span class="nt">-p</span> 9002/data
<span class="nb">mkdir</span> <span class="nt">-p</span> 9003/data
<span class="nb">mkdir</span> <span class="nt">-p</span> 9004/data
<span class="nb">mkdir</span> <span class="nt">-p</span> 9005/data
<span class="nb">mkdir</span> <span class="nt">-p</span> 9006/data

<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9001
<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9002
<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9003
<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9004
<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9005
<span class="nb">cp</span> ~/redis-3.2.11/redis.conf 9006
</code></pre></div></div>

<p>修改各 redis 实例的配置文件，以 9001 实例为例，bind 为本机 ip</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>daemonize yes
pidfile /usr/local/redis-cluster/9001/redis.pid
bind 192.168.1.6
port 9001
dir /usr/local/redis-cluster/9001/data
appendonly yes
cluster-enabled yes
cluster-config-file nodes-9001.conf
cluster-node-timeout 15000
</code></pre></div></div>

<p>9002-9006 实例配置同上，只是将其中的 9001 替换为相应的端口号。</p>

<h2 id="实例启动及测试">实例启动及测试</h2>

<p>启动实例</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9001/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9002/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9003/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9004/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9005/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/9006/redis.conf
</code></pre></div></div>

<p>连接实例，确认各实例正常启动</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9001
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9002
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9003
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9004
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9005
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9006
</code></pre></div></div>

<h2 id="集群构建及测试">集群构建及测试</h2>

<p>安装 ruby 及 redis 依赖</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt-get <span class="nb">install </span>ruby
gem <span class="nb">install </span>redis
</code></pre></div></div>

<p>将单独的 redis 实例构建成集群（三主三从）</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/redis-cluster/bin/redis-trib.rb create <span class="nt">--replicas</span> 1 192.168.1.6:9001 192.168.1.6:9002 192.168.1.6:9003 192.168.1.6:9004 192.168.1.6:9005 192.168.1.6:9006
</code></pre></div></div>

<p>连接集群节点，注意比连接单实例时多了一个 -c 参数</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9001 <span class="nt">-c</span>
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9002 <span class="nt">-c</span>
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9003 <span class="nt">-c</span>
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9004 <span class="nt">-c</span>
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9005 <span class="nt">-c</span>
/usr/local/redis-cluster/bin/redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9006 <span class="nt">-c</span>
</code></pre></div></div>

<p>查看集群信息</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9001 <span class="nt">-c</span>
192.168.1.6:9001&gt; cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_sent:55
cluster_stats_messages_received:50
192.168.1.6:9001&gt; cluster nodes
e74db54eb4fa9dde324988e44bb3919129f944c8 192.168.1.6:9006 slave de0928f00ac377bf5b7806d088808f31804923eb 0 1522674425815 6 connected
186a18ae13203946253b537cfdab549b3be5282d 192.168.1.6:9005 slave 761269f61d3f95d3937b5b3451ea73f979aa40e6 0 1522674423811 5 connected
3e58b504f1419cf770313daf11f480bf48dd34a0 192.168.1.6:9001 myself,master - 0 0 1 connected 0-5460
6a1327d2385b0e270a9d1fa63bae3c14c879625e 192.168.1.6:9004 slave 3e58b504f1419cf770313daf11f480bf48dd34a0 0 1522674424813 4 connected
761269f61d3f95d3937b5b3451ea73f979aa40e6 192.168.1.6:9002 master - 0 1522674422809 2 connected 5461-10922
de0928f00ac377bf5b7806d088808f31804923eb 192.168.1.6:9003 master - 0 1522674426818 3 connected 10923-16383
</code></pre></div></div>

<h2 id="客户端连接读写">客户端连接读写</h2>

<p>客户端以 redis-cli 为例，数据读写测试脚本</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./redis-cli <span class="nt">-h</span> 192.168.1.6 <span class="nt">-p</span> 9001 <span class="nt">-c</span>
192.168.1.6:9001&gt; <span class="nb">set </span>key1 value1
-&gt; Redirected to slot <span class="o">[</span>9189] located at 192.168.1.6:9002
OK
192.168.1.6:9002&gt; get key1
<span class="s2">"value1"</span>
</code></pre></div></div>

<p>客户端以 jedis 为例，当前版本</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>redis.clients<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>jedis<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>2.9.0<span class="nt">&lt;/version&gt;</span>
    <span class="nt">&lt;type&gt;</span>jar<span class="nt">&lt;/type&gt;</span>
    <span class="nt">&lt;scope&gt;</span>compile<span class="nt">&lt;/scope&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</code></pre></div></div>

<p>jedis 数据读写测试代码</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Set</span><span class="o">&lt;</span><span class="nc">HostAndPort</span><span class="o">&gt;</span> <span class="n">jedisClusterNodes</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">HostAndPort</span><span class="o">&gt;();</span>
<span class="c1">// Jedis Cluster will attempt to discover cluster nodes automatically</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9001</span><span class="o">));</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9002</span><span class="o">));</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9003</span><span class="o">));</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9004</span><span class="o">));</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9005</span><span class="o">));</span>
<span class="n">jedisClusterNodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">HostAndPort</span><span class="o">(</span><span class="s">"192.168.1.6"</span><span class="o">,</span> <span class="mi">9006</span><span class="o">));</span>
<span class="nc">JedisCluster</span> <span class="n">jc</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JedisCluster</span><span class="o">(</span><span class="n">jedisClusterNodes</span><span class="o">);</span>
<span class="n">jc</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="s">"key"</span><span class="o">,</span> <span class="s">"value"</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">value</span> <span class="o">=</span> <span class="n">jc</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"key"</span><span class="o">);</span>
<span class="c1">// jc.close();</span>
</code></pre></div></div>

<h2 id="槽分配及位置确定">槽分配及位置确定</h2>

<p>从上面集群信息中可以看出，主从实例 9001 9004 分配的槽范围为 0-5460，主从实例 9002 9005 分配的槽范围为 5461-10922，主从实例 9003 9006 分配的槽范围为 10923-16383。</p>

<p>当用户通过客户端(redis-cli 或 jedis)向集群存入键值对时，数据存储的槽编号通过 key 计算出来，算法 CRC16(key) % 16384。</p>

<p>算法 CRC16(key) % 16384 的 java 代码实现</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * 计算键 key 要放入哪个槽
 * 
 * @param key 键名
 * @return slot 槽编号
 */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">int</span> <span class="nf">slot</span><span class="o">(</span><span class="nc">String</span> <span class="n">key</span><span class="o">){</span>
    <span class="kt">int</span> <span class="n">slot</span>  <span class="o">=</span> <span class="n">crc16</span><span class="o">(</span><span class="n">key</span><span class="o">)</span> <span class="o">%</span> <span class="mi">16384</span><span class="o">;</span>
    <span class="k">return</span> <span class="n">slot</span><span class="o">;</span>
<span class="o">}</span>

<span class="cm">/**
 * 计算键 key 的 crc16 值
 * 
 * @param key 键名
 * @return crc16 值
 * @see ~/redis-3.2.11/src/cluster.c and ~/redis-3.2.11/src/crc16.c
 */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">int</span> <span class="nf">crc16</span><span class="o">(</span><span class="nc">String</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span><span class="o">[]</span> <span class="n">table</span> <span class="o">=</span> <span class="o">{</span>
        <span class="mh">0x0000</span><span class="o">,</span><span class="mh">0x1021</span><span class="o">,</span><span class="mh">0x2042</span><span class="o">,</span><span class="mh">0x3063</span><span class="o">,</span><span class="mh">0x4084</span><span class="o">,</span><span class="mh">0x50a5</span><span class="o">,</span><span class="mh">0x60c6</span><span class="o">,</span><span class="mh">0x70e7</span><span class="o">,</span>
        <span class="mh">0x8108</span><span class="o">,</span><span class="mh">0x9129</span><span class="o">,</span><span class="mh">0xa14a</span><span class="o">,</span><span class="mh">0xb16b</span><span class="o">,</span><span class="mh">0xc18c</span><span class="o">,</span><span class="mh">0xd1ad</span><span class="o">,</span><span class="mh">0xe1ce</span><span class="o">,</span><span class="mh">0xf1ef</span><span class="o">,</span>
        <span class="mh">0x1231</span><span class="o">,</span><span class="mh">0x0210</span><span class="o">,</span><span class="mh">0x3273</span><span class="o">,</span><span class="mh">0x2252</span><span class="o">,</span><span class="mh">0x52b5</span><span class="o">,</span><span class="mh">0x4294</span><span class="o">,</span><span class="mh">0x72f7</span><span class="o">,</span><span class="mh">0x62d6</span><span class="o">,</span>
        <span class="mh">0x9339</span><span class="o">,</span><span class="mh">0x8318</span><span class="o">,</span><span class="mh">0xb37b</span><span class="o">,</span><span class="mh">0xa35a</span><span class="o">,</span><span class="mh">0xd3bd</span><span class="o">,</span><span class="mh">0xc39c</span><span class="o">,</span><span class="mh">0xf3ff</span><span class="o">,</span><span class="mh">0xe3de</span><span class="o">,</span>
        <span class="mh">0x2462</span><span class="o">,</span><span class="mh">0x3443</span><span class="o">,</span><span class="mh">0x0420</span><span class="o">,</span><span class="mh">0x1401</span><span class="o">,</span><span class="mh">0x64e6</span><span class="o">,</span><span class="mh">0x74c7</span><span class="o">,</span><span class="mh">0x44a4</span><span class="o">,</span><span class="mh">0x5485</span><span class="o">,</span>
        <span class="mh">0xa56a</span><span class="o">,</span><span class="mh">0xb54b</span><span class="o">,</span><span class="mh">0x8528</span><span class="o">,</span><span class="mh">0x9509</span><span class="o">,</span><span class="mh">0xe5ee</span><span class="o">,</span><span class="mh">0xf5cf</span><span class="o">,</span><span class="mh">0xc5ac</span><span class="o">,</span><span class="mh">0xd58d</span><span class="o">,</span>
        <span class="mh">0x3653</span><span class="o">,</span><span class="mh">0x2672</span><span class="o">,</span><span class="mh">0x1611</span><span class="o">,</span><span class="mh">0x0630</span><span class="o">,</span><span class="mh">0x76d7</span><span class="o">,</span><span class="mh">0x66f6</span><span class="o">,</span><span class="mh">0x5695</span><span class="o">,</span><span class="mh">0x46b4</span><span class="o">,</span>
        <span class="mh">0xb75b</span><span class="o">,</span><span class="mh">0xa77a</span><span class="o">,</span><span class="mh">0x9719</span><span class="o">,</span><span class="mh">0x8738</span><span class="o">,</span><span class="mh">0xf7df</span><span class="o">,</span><span class="mh">0xe7fe</span><span class="o">,</span><span class="mh">0xd79d</span><span class="o">,</span><span class="mh">0xc7bc</span><span class="o">,</span>
        <span class="mh">0x48c4</span><span class="o">,</span><span class="mh">0x58e5</span><span class="o">,</span><span class="mh">0x6886</span><span class="o">,</span><span class="mh">0x78a7</span><span class="o">,</span><span class="mh">0x0840</span><span class="o">,</span><span class="mh">0x1861</span><span class="o">,</span><span class="mh">0x2802</span><span class="o">,</span><span class="mh">0x3823</span><span class="o">,</span>
        <span class="mh">0xc9cc</span><span class="o">,</span><span class="mh">0xd9ed</span><span class="o">,</span><span class="mh">0xe98e</span><span class="o">,</span><span class="mh">0xf9af</span><span class="o">,</span><span class="mh">0x8948</span><span class="o">,</span><span class="mh">0x9969</span><span class="o">,</span><span class="mh">0xa90a</span><span class="o">,</span><span class="mh">0xb92b</span><span class="o">,</span>
        <span class="mh">0x5af5</span><span class="o">,</span><span class="mh">0x4ad4</span><span class="o">,</span><span class="mh">0x7ab7</span><span class="o">,</span><span class="mh">0x6a96</span><span class="o">,</span><span class="mh">0x1a71</span><span class="o">,</span><span class="mh">0x0a50</span><span class="o">,</span><span class="mh">0x3a33</span><span class="o">,</span><span class="mh">0x2a12</span><span class="o">,</span>
        <span class="mh">0xdbfd</span><span class="o">,</span><span class="mh">0xcbdc</span><span class="o">,</span><span class="mh">0xfbbf</span><span class="o">,</span><span class="mh">0xeb9e</span><span class="o">,</span><span class="mh">0x9b79</span><span class="o">,</span><span class="mh">0x8b58</span><span class="o">,</span><span class="mh">0xbb3b</span><span class="o">,</span><span class="mh">0xab1a</span><span class="o">,</span>
        <span class="mh">0x6ca6</span><span class="o">,</span><span class="mh">0x7c87</span><span class="o">,</span><span class="mh">0x4ce4</span><span class="o">,</span><span class="mh">0x5cc5</span><span class="o">,</span><span class="mh">0x2c22</span><span class="o">,</span><span class="mh">0x3c03</span><span class="o">,</span><span class="mh">0x0c60</span><span class="o">,</span><span class="mh">0x1c41</span><span class="o">,</span>
        <span class="mh">0xedae</span><span class="o">,</span><span class="mh">0xfd8f</span><span class="o">,</span><span class="mh">0xcdec</span><span class="o">,</span><span class="mh">0xddcd</span><span class="o">,</span><span class="mh">0xad2a</span><span class="o">,</span><span class="mh">0xbd0b</span><span class="o">,</span><span class="mh">0x8d68</span><span class="o">,</span><span class="mh">0x9d49</span><span class="o">,</span>
        <span class="mh">0x7e97</span><span class="o">,</span><span class="mh">0x6eb6</span><span class="o">,</span><span class="mh">0x5ed5</span><span class="o">,</span><span class="mh">0x4ef4</span><span class="o">,</span><span class="mh">0x3e13</span><span class="o">,</span><span class="mh">0x2e32</span><span class="o">,</span><span class="mh">0x1e51</span><span class="o">,</span><span class="mh">0x0e70</span><span class="o">,</span>
        <span class="mh">0xff9f</span><span class="o">,</span><span class="mh">0xefbe</span><span class="o">,</span><span class="mh">0xdfdd</span><span class="o">,</span><span class="mh">0xcffc</span><span class="o">,</span><span class="mh">0xbf1b</span><span class="o">,</span><span class="mh">0xaf3a</span><span class="o">,</span><span class="mh">0x9f59</span><span class="o">,</span><span class="mh">0x8f78</span><span class="o">,</span>
        <span class="mh">0x9188</span><span class="o">,</span><span class="mh">0x81a9</span><span class="o">,</span><span class="mh">0xb1ca</span><span class="o">,</span><span class="mh">0xa1eb</span><span class="o">,</span><span class="mh">0xd10c</span><span class="o">,</span><span class="mh">0xc12d</span><span class="o">,</span><span class="mh">0xf14e</span><span class="o">,</span><span class="mh">0xe16f</span><span class="o">,</span>
        <span class="mh">0x1080</span><span class="o">,</span><span class="mh">0x00a1</span><span class="o">,</span><span class="mh">0x30c2</span><span class="o">,</span><span class="mh">0x20e3</span><span class="o">,</span><span class="mh">0x5004</span><span class="o">,</span><span class="mh">0x4025</span><span class="o">,</span><span class="mh">0x7046</span><span class="o">,</span><span class="mh">0x6067</span><span class="o">,</span>
        <span class="mh">0x83b9</span><span class="o">,</span><span class="mh">0x9398</span><span class="o">,</span><span class="mh">0xa3fb</span><span class="o">,</span><span class="mh">0xb3da</span><span class="o">,</span><span class="mh">0xc33d</span><span class="o">,</span><span class="mh">0xd31c</span><span class="o">,</span><span class="mh">0xe37f</span><span class="o">,</span><span class="mh">0xf35e</span><span class="o">,</span>
        <span class="mh">0x02b1</span><span class="o">,</span><span class="mh">0x1290</span><span class="o">,</span><span class="mh">0x22f3</span><span class="o">,</span><span class="mh">0x32d2</span><span class="o">,</span><span class="mh">0x4235</span><span class="o">,</span><span class="mh">0x5214</span><span class="o">,</span><span class="mh">0x6277</span><span class="o">,</span><span class="mh">0x7256</span><span class="o">,</span>
        <span class="mh">0xb5ea</span><span class="o">,</span><span class="mh">0xa5cb</span><span class="o">,</span><span class="mh">0x95a8</span><span class="o">,</span><span class="mh">0x8589</span><span class="o">,</span><span class="mh">0xf56e</span><span class="o">,</span><span class="mh">0xe54f</span><span class="o">,</span><span class="mh">0xd52c</span><span class="o">,</span><span class="mh">0xc50d</span><span class="o">,</span>
        <span class="mh">0x34e2</span><span class="o">,</span><span class="mh">0x24c3</span><span class="o">,</span><span class="mh">0x14a0</span><span class="o">,</span><span class="mh">0x0481</span><span class="o">,</span><span class="mh">0x7466</span><span class="o">,</span><span class="mh">0x6447</span><span class="o">,</span><span class="mh">0x5424</span><span class="o">,</span><span class="mh">0x4405</span><span class="o">,</span>
        <span class="mh">0xa7db</span><span class="o">,</span><span class="mh">0xb7fa</span><span class="o">,</span><span class="mh">0x8799</span><span class="o">,</span><span class="mh">0x97b8</span><span class="o">,</span><span class="mh">0xe75f</span><span class="o">,</span><span class="mh">0xf77e</span><span class="o">,</span><span class="mh">0xc71d</span><span class="o">,</span><span class="mh">0xd73c</span><span class="o">,</span>
        <span class="mh">0x26d3</span><span class="o">,</span><span class="mh">0x36f2</span><span class="o">,</span><span class="mh">0x0691</span><span class="o">,</span><span class="mh">0x16b0</span><span class="o">,</span><span class="mh">0x6657</span><span class="o">,</span><span class="mh">0x7676</span><span class="o">,</span><span class="mh">0x4615</span><span class="o">,</span><span class="mh">0x5634</span><span class="o">,</span>
        <span class="mh">0xd94c</span><span class="o">,</span><span class="mh">0xc96d</span><span class="o">,</span><span class="mh">0xf90e</span><span class="o">,</span><span class="mh">0xe92f</span><span class="o">,</span><span class="mh">0x99c8</span><span class="o">,</span><span class="mh">0x89e9</span><span class="o">,</span><span class="mh">0xb98a</span><span class="o">,</span><span class="mh">0xa9ab</span><span class="o">,</span>
        <span class="mh">0x5844</span><span class="o">,</span><span class="mh">0x4865</span><span class="o">,</span><span class="mh">0x7806</span><span class="o">,</span><span class="mh">0x6827</span><span class="o">,</span><span class="mh">0x18c0</span><span class="o">,</span><span class="mh">0x08e1</span><span class="o">,</span><span class="mh">0x3882</span><span class="o">,</span><span class="mh">0x28a3</span><span class="o">,</span>
        <span class="mh">0xcb7d</span><span class="o">,</span><span class="mh">0xdb5c</span><span class="o">,</span><span class="mh">0xeb3f</span><span class="o">,</span><span class="mh">0xfb1e</span><span class="o">,</span><span class="mh">0x8bf9</span><span class="o">,</span><span class="mh">0x9bd8</span><span class="o">,</span><span class="mh">0xabbb</span><span class="o">,</span><span class="mh">0xbb9a</span><span class="o">,</span>
        <span class="mh">0x4a75</span><span class="o">,</span><span class="mh">0x5a54</span><span class="o">,</span><span class="mh">0x6a37</span><span class="o">,</span><span class="mh">0x7a16</span><span class="o">,</span><span class="mh">0x0af1</span><span class="o">,</span><span class="mh">0x1ad0</span><span class="o">,</span><span class="mh">0x2ab3</span><span class="o">,</span><span class="mh">0x3a92</span><span class="o">,</span>
        <span class="mh">0xfd2e</span><span class="o">,</span><span class="mh">0xed0f</span><span class="o">,</span><span class="mh">0xdd6c</span><span class="o">,</span><span class="mh">0xcd4d</span><span class="o">,</span><span class="mh">0xbdaa</span><span class="o">,</span><span class="mh">0xad8b</span><span class="o">,</span><span class="mh">0x9de8</span><span class="o">,</span><span class="mh">0x8dc9</span><span class="o">,</span>
        <span class="mh">0x7c26</span><span class="o">,</span><span class="mh">0x6c07</span><span class="o">,</span><span class="mh">0x5c64</span><span class="o">,</span><span class="mh">0x4c45</span><span class="o">,</span><span class="mh">0x3ca2</span><span class="o">,</span><span class="mh">0x2c83</span><span class="o">,</span><span class="mh">0x1ce0</span><span class="o">,</span><span class="mh">0x0cc1</span><span class="o">,</span>
        <span class="mh">0xef1f</span><span class="o">,</span><span class="mh">0xff3e</span><span class="o">,</span><span class="mh">0xcf5d</span><span class="o">,</span><span class="mh">0xdf7c</span><span class="o">,</span><span class="mh">0xaf9b</span><span class="o">,</span><span class="mh">0xbfba</span><span class="o">,</span><span class="mh">0x8fd9</span><span class="o">,</span><span class="mh">0x9ff8</span><span class="o">,</span>
        <span class="mh">0x6e17</span><span class="o">,</span><span class="mh">0x7e36</span><span class="o">,</span><span class="mh">0x4e55</span><span class="o">,</span><span class="mh">0x5e74</span><span class="o">,</span><span class="mh">0x2e93</span><span class="o">,</span><span class="mh">0x3eb2</span><span class="o">,</span><span class="mh">0x0ed1</span><span class="o">,</span><span class="mh">0x1ef0</span>
    <span class="o">};</span>

    <span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="na">getBytes</span><span class="o">();</span>
    <span class="kt">int</span> <span class="n">crc</span> <span class="o">=</span> <span class="mh">0x0000</span><span class="o">;</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">byte</span> <span class="n">b</span> <span class="o">:</span> <span class="n">bytes</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">crc</span> <span class="o">=</span> <span class="o">(</span><span class="n">crc</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span><span class="o">)</span> <span class="o">^</span> <span class="n">table</span><span class="o">[((</span><span class="n">crc</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="o">)</span> <span class="o">^</span> <span class="n">b</span><span class="o">)</span> <span class="o">&amp;</span> <span class="mh">0x00FF</span><span class="o">];</span>
    <span class="o">}</span> 
    <span class="n">crc</span> <span class="o">=</span> <span class="n">crc</span> <span class="o">&amp;</span> <span class="mh">0x3FFF</span><span class="o">;</span>

    <span class="k">return</span> <span class="n">crc</span><span class="o">;</span>
<span class="o">}</span>

<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">key</span> <span class="o">=</span> <span class="s">"key1"</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">slot</span> <span class="o">=</span> <span class="n">slot</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="s">"slot="</span> <span class="o">+</span> <span class="n">slot</span><span class="o">);</span> <span class="c1">// 输出 slot=9189</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="http://www.cnblogs.com/mafly/p/redis_cluster.html" target="_blank" rel="nofollow noopener noreferrer">Redis 集群搭建详细指南</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Redis" /><category term="cluster" /><category term="java" /><category term="client" /><category term="crc16" /><summary type="html"><![CDATA[源码下载 http://download.redis.io/releases/redis-3.2.11.tar.gz 源码编译 tar zxvf redis-3.2.11.tar.gz cd ~/redis-3.2.11 make 集群规划及配置 创建集群目录，将编译好的命令文件复制到 bin 目录 mkdir -p /usr/local/redis-cluster/bin cd ~/redis-3.2.11/src cp mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server redis-trib.rb /usr/local/redis-cluster/bin]]></summary></entry><entry><title type="html">Linux su 命令</title><link href="https://zhizheng.github.io/post/linux-command-su/" rel="alternate" type="text/html" title="Linux su 命令" /><published>2018-02-02T09:54:01+00:00</published><updated>2018-02-02T09:54:01+00:00</updated><id>https://zhizheng.github.io/post/linux-command-su</id><content type="html" xml:base="https://zhizheng.github.io/post/linux-command-su/"><![CDATA[<p>今天一个同事问了我一个 linux 相关的问题，在服务器上用 root 用户执行如下命令</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /elasticsearch/elasticsearch-2.3.2/bin &amp;&amp; su elasticsearch &amp;&amp; ./elasticsearch -d
</code></pre></div></div>

<blockquote>
  <p>好像执行./elasticsearch -d时，还是在root用户</p>
</blockquote>

<p>根据他说的情况，我想到 su 是有命令参数的，根据他的命令，我修改了一下</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - elasticsearch  -c "cd /elasticsearch/elasticsearch-2.3.2/bin &amp;&amp; ./elasticsearch -d"
</code></pre></div></div>

<p>发给他后，他在自己的环境执行后，结果确实成功了。</p>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="http://blog.csdn.net/linucle/article/details/43967237" target="_blank" rel="nofollow noopener noreferrer">shell不能执行su 后的脚本</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Linux" /><category term="command" /><category term="su" /><summary type="html"><![CDATA[今天一个同事问了我一个 linux 相关的问题，在服务器上用 root 用户执行如下命令 cd /elasticsearch/elasticsearch-2.3.2/bin &amp;&amp; su elasticsearch &amp;&amp; ./elasticsearch -d 好像执行./elasticsearch -d时，还是在root用户 根据他说的情况，我想到 su 是有命令参数的，根据他的命令，我修改了一下 su - elasticsearch -c "cd /elasticsearch/elasticsearch-2.3.2/bin &amp;&amp; ./elasticsearch -d" 发给他后，他在自己的环境执行后，结果确实成功了。 参考资料 shell不能执行su 后的脚本]]></summary></entry><entry><title type="html">本地调试 jekyll 主题时报 Could not open library ‘libcurl.dll’</title><link href="https://zhizheng.github.io/post/jekyll-theme-next-libcurl/" rel="alternate" type="text/html" title="本地调试 jekyll 主题时报 Could not open library ‘libcurl.dll’" /><published>2018-01-18T04:23:01+00:00</published><updated>2018-01-18T04:23:01+00:00</updated><id>https://zhizheng.github.io/post/jekyll-theme-next-libcurl</id><content type="html" xml:base="https://zhizheng.github.io/post/jekyll-theme-next-libcurl/"><![CDATA[<p>Windows 本地调试 jekyll-theme-next 主题时</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle exec jekyll server
</code></pre></div></div>

<p>报以下错误</p>

<blockquote>
  <p>Dependency Error: Yikes! It looks like you don’t have jekyll-remote-theme or one of its dependencies installed. In order to use Jekyll as currently configured, you’ll need to install this gem. The full error message from Ruby is: ‘Could not open library ‘libcurl’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.dll’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.so.4’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.so.4.dll’: �Ҳ���ָ����ģ�顣 ‘ If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/!</p>
</blockquote>

<p>经网上查询并亲自试验，发现有两种方法解决这个问题。</p>

<!-- more -->

<h2 id="解决方法">解决方法</h2>

<h3 id="方法一修改主题配置文件">方法一：修改主题配置文件</h3>

<h4 id="修改-gemfile">修改 Gemfile</h4>

<p>修改前内容</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins
#gem 'jekyll-admin', group: :jekyll_plugins
</code></pre></div></div>

<p>修改后内容</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>source 'https://rubygems.org'
gem 'github-pages'
#gem 'jekyll-admin', group: :jekyll_plugins
</code></pre></div></div>

<h4 id="修改-_configyml">修改 _config.yml</h4>

<p>在 plugins 下添加 jekyll-paginate，修改前内容</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>plugins:
# jemoji conficts with toc in some no-ascii post
# - jemoji
 - jekyll-sitemap
 - jekyll-feed
</code></pre></div></div>

<p>修改后内容</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>plugins:
# jemoji conficts with toc in some no-ascii post
# - jemoji
 - jekyll-sitemap
 - jekyll-feed
 - jekyll-paginate
</code></pre></div></div>

<h3 id="方法二在操作系统中安装-libcurldll">方法二：在操作系统中安装 libcurl.dll</h3>

<p>可以直接从网上下载 libcurl.dll 放到系统 path 下，或者下载 curl 源码自己编译。</p>

<h4 id="下载-libcurldll-二进制包">下载 libcurl.dll 二进制包</h4>

<p>打开网页 https://curl.haxx.se/gknw.net/7.40.0/dist-w64/，并选择一个包下载，如 <a href="https://curl.haxx.se/gknw.net/7.40.0/dist-w64/curl-7.40.0-ssh2-ssl-sspi-zlib-static-bin-w64.zip" target="_blank" rel="nofollow noopener noreferrer">curl-7.40.0-ssh2-ssl-sspi-zlib-static-bin-w64.zip</a>，解压后将目录中的 libcurl.dll 放到系统 path 下，如 Ruby 安装目录 bin 中。</p>

<h4 id="下载-curl-源码编译">下载 curl 源码编译</h4>

<p>打开网页 https://curl.haxx.se/download.html，并选择一个源码包下载，如 <a href="https://curl.haxx.se/download/curl-7.57.0.zip" target="_blank" rel="nofollow noopener noreferrer">curl-7.57.0.zip</a>，解压包到 C:\curl-7.57.0，在终端（CMD 或 Powershell）下，切换到本机 DevKit 目录，运行 msys.bat，此时会弹出一个 mingw 环境窗口，在 mingw 环境窗口中输入命令 <code class="language-plaintext highlighter-rouge">cd /c/curl-7.57.0/lib</code> 进入到 C:\curl-7.57.0\lib 目录，然后执行 <code class="language-plaintext highlighter-rouge">make -f Makefile.m32</code> 编译源码，编译完成后会在 lib 目录下会生成 libcurl.dll，将 libcurl.dll 放到系统 path 下，如 Ruby 安装目录 bin 中。</p>

<h2 id="方法优劣比较">方法优劣比较</h2>

<h3 id="方法一">方法一</h3>

<h4 id="优点">优点</h4>

<p>可以比较快速地进入本地调试步骤，而不用修改操作系统。</p>

<h4 id="缺点">缺点</h4>

<p>如果远方仓库（如 github）中 Gemfile 和 _config.yml plugins 部分保持主题默认的话，本地调试完成后提交时有可能误将这两部分误提交。</p>

<h3 id="方法二">方法二</h3>

<h4 id="优点-1">优点</h4>

<p>操作系统安装 libcurl.dll 后，本地 Gemfile 和 _config.yml plugins 部分可以与远方仓库（如 github）保持一致，不用做任何修改。</p>

<h4 id="缺点-1">缺点</h4>

<p>要修改操作系统，比较麻烦，还有可能给系统带来安全性的问题。</p>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="https://stackoverflow.com/questions/47720302/jekyll-serve-dependency-error-could-not-open-lib-curl" target="_blank" rel="nofollow noopener noreferrer">jekyll serve dependency error - Could not open ‘lib curl’</a></li>
  <li><a href="https://ruby-china.org/topics/1084" target="_blank" rel="nofollow noopener noreferrer">Ruby 在 windows xp 成功编译 gem typhoeus 的步骤</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="Jekyll" /><category term="theme" /><category term="debug" /><summary type="html"><![CDATA[Windows 本地调试 jekyll-theme-next 主题时 bundle exec jekyll server 报以下错误 Dependency Error: Yikes! It looks like you don’t have jekyll-remote-theme or one of its dependencies installed. In order to use Jekyll as currently configured, you’ll need to install this gem. The full error message from Ruby is: ‘Could not open library ‘libcurl’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.dll’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.so.4’: �Ҳ���ָ����ģ�顣 . Could not open library ‘libcurl.so.4.dll’: �Ҳ���ָ����ģ�顣 ‘ If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/! 经网上查询并亲自试验，发现有两种方法解决这个问题。]]></summary></entry><entry><title type="html">HttpClient 并发报 Timeout waiting for connection from pool</title><link href="https://zhizheng.github.io/post/HttpClient-Concurrent-Timeout/" rel="alternate" type="text/html" title="HttpClient 并发报 Timeout waiting for connection from pool" /><published>2018-01-17T03:00:01+00:00</published><updated>2018-01-17T03:00:01+00:00</updated><id>https://zhizheng.github.io/post/HttpClient-Concurrent-Timeout</id><content type="html" xml:base="https://zhizheng.github.io/post/HttpClient-Concurrent-Timeout/"><![CDATA[<p>新建了一个 HttpClient 实例，使用 for 循环调用，结果报出以下错误</p>

<blockquote>
  <p>java
org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool</p>
</blockquote>

<p>解决方法，修改连接池配置，增大连接数</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">RequestConfig</span> <span class="n">config</span> <span class="o">=</span> <span class="nc">RequestConfig</span><span class="o">.</span><span class="na">custom</span><span class="o">()</span>  
    <span class="o">.</span><span class="na">setSocketTimeout</span><span class="o">(</span><span class="n">socketTimeout</span><span class="o">)</span>  
    <span class="o">.</span><span class="na">setConnectTimeout</span><span class="o">(</span><span class="n">connectTimeout</span><span class="o">)</span>  
    <span class="o">.</span><span class="na">setConnectionRequestTimeout</span><span class="o">(</span><span class="n">connectionRequestTimeout</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>  
<span class="n">httpClient</span> <span class="o">=</span> <span class="nc">HttpClients</span><span class="o">.</span><span class="na">custom</span><span class="o">().</span><span class="na">setDefaultRequestConfig</span><span class="o">(</span><span class="n">config</span><span class="o">)</span>  
     <span class="o">.</span><span class="na">setMaxConnTotal</span><span class="o">(</span><span class="n">maxConnTotal</span><span class="o">)</span>  
     <span class="o">.</span><span class="na">setMaxConnPerRoute</span><span class="o">(</span><span class="n">maxConnPerRoute</span><span class="o">).</span><span class="na">build</span><span class="o">();</span> 
</code></pre></div></div>

<h2 id="参考资料">参考资料</h2>

<ul>
  <li><a href="http://jinnianshilongnian.iteye.com/blog/2089792" target="_blank" rel="nofollow noopener noreferrer">使用httpclient必须知道的参数设置及代码写法、存在的风险</a></li>
  <li><a href="http://blog.csdn.net/falynn1220/article/details/50607789" target="_blank" rel="nofollow noopener noreferrer">HttpClient大并发下Timeout waiting for connection from pool优化方案</a></li>
</ul>]]></content><author><name>Zhizheng Zhang</name></author><category term="HttpClient" /><category term="pool" /><category term="timeout" /><summary type="html"><![CDATA[新建了一个 HttpClient 实例，使用 for 循环调用，结果报出以下错误 java org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool 解决方法，修改连接池配置，增大连接数 RequestConfig config = RequestConfig.custom() .setSocketTimeout(socketTimeout) .setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout).build(); httpClient = HttpClients.custom().setDefaultRequestConfig(config) .setMaxConnTotal(maxConnTotal) .setMaxConnPerRoute(maxConnPerRoute).build(); 参考资料 使用httpclient必须知道的参数设置及代码写法、存在的风险 HttpClient大并发下Timeout waiting for connection from pool优化方案]]></summary></entry><entry><title type="html">修改本站点主题为 NexT</title><link href="https://zhizheng.github.io/post/change-site-theme-next/" rel="alternate" type="text/html" title="修改本站点主题为 NexT" /><published>2018-01-16T10:00:01+00:00</published><updated>2018-01-16T10:00:01+00:00</updated><id>https://zhizheng.github.io/post/change-site-theme-next</id><content type="html" xml:base="https://zhizheng.github.io/post/change-site-theme-next/"><![CDATA[<p>修改本站点主题为 NexT。</p>]]></content><author><name>Zhizheng Zhang</name></author><category term="Site" /><category term="theme" /><category term="NexT" /><summary type="html"><![CDATA[修改本站点主题为 NexT。]]></summary></entry></feed>