1 前言
etcd
是一个开源的 分布式键值存储系统,常被用于在分布式系统中保存配置数据、服务发现信息和协调数据。它由 CoreOS 开发,现在是 CNCF(云原生计算基金会) 的毕业项目,和 Kubernetes 等项目一起发展。
一句话概括
etcd 是一个强一致性、高可用性、分布式的键值数据库,广泛用于服务发现、配置管理、协调任务等场景,特别是在 Kubernetes 中充当核心的数据存储中心。
1.1 核心特性
特性 |
说明 |
强一致性(CP) |
基于 Raft 共识算法,保证数据一致性 |
高可用性 |
支持集群部署,节点故障时可继续服务 |
分布式架构 |
可水平扩展,集群内数据自动同步 |
Watch机制 |
支持客户端监听键的变动,适合事件驱动系统 |
支持事务操作 |
提供原子操作(如比较并交换) |
TLS 安全通信 |
提供客户端和服务端双向认证、数据加密 |
1.2 etcd与其他组件对比
比较项 |
etcd |
Consul |
Zookeeper |
协议 |
Raft |
Raft |
Zab |
数据模型 |
KV(层级) |
KV(扁平) |
树结构(类似文件系统) |
Watch机制 |
原生支持(事件推送) |
支持(长轮询) |
支持(监听) |
常见用途 |
K8s存储、配置中心 |
服务发现 |
分布式协调、锁 |
场景举例
场景 |
示例 |
服务临时注册 |
把服务注册为 service/host=127.0.0.1:8080 , 过期即下乡 |
临时权限令牌 |
/token/abc123 30秒后自动失效 |
分布式锁 |
借助租约实现锁的自动释放(防止死锁) |
2 安装
2.1 单机安装
2.1.1 下载与配置
mkdir /usr/local/soft/etcd
cd /usr/local/soft/etcd
mkdir /usr/local/soft/etcd/data
mkdir /usr/local/soft/etcd/logs
wget https://github.com/etcd-io/etcd/releases/download/v3.6.4/etcd-v3.6.4-linux-amd64.tar.gz
tar -zxvf etcd-v3.6.4-linux-amd64.tar.gz
cp /usr/local/soft/etcd/etcd-v3.6.4-linux-amd64/etcd* /usr/local/bin/
启动
./etcd --data-dir=/usr/local/soft/etcd/data/etcd &> /usr/local/soft/etcd/logs/etcd.log &
默认监听 2379(客户端)、2380(集群内部)
检查是否启动成功
方式一:查看进程是否存在
ps aux | grep etcd
方式二:确认端口监听状态
ss -tunlp | grep etcd
可以通过 curl
请求 etcd 的健康检查接口,如果是空返回、报错或连接失败,说明 etcd 没有正常启动。
curl http://127.0.0.1:2379/health
2.1.2 Docker快速部署
docker run -d \
-p 2379:2379 -p 2380:2380 \
--name etcd \
quay.io/coreos/etcd \
/usr/local/bin/etcd \
--name s1 \
--initial-advertise-peer-urls http://localhost:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://localhost:2379 \
--initial-cluster s1=http://localhost:2380
3 基础操作案例
3.1 写入键值对
etcdctl put foo "bar"
3.2 读取键值
etcdctl get foo
# 输出:
# foo
# bar
3.3 删除键值
etcdctl del foo
4 目录式存储&前缀查询
etcd本身是KV模型,但支持“类目录结构”的key
etcdctl put /config/db/host 127.0.0.1
etcdctl put /config/db/port 3306
etcdctl put /config/api/token abcdef
查询某个前缀下所有键
etcdctl get /config --prefix

5 Watch 键变化(监听)
用于观察键是否被改动
etcdctl watch name
另开一个终端执行
etcdctl put name 有勇气的牛排

6 Lease(租约)与 TTL
用于设置自动过期的键(如临时服务注册、锁等)
6.1 创建租约(60秒)
etcdctl lease grant 60
# 输出:lease 694d9853f094a70f granted with TTL(60s)
lease ID:694d9853f094a70f
6.2 使用租约写入键值
etcdctl put "name:有勇气的牛排" "正在编程" --lease=$LEASE_ID
etcdctl put "name:有勇气的牛排" "正在编程" --lease=694d9853f094a713
6.3 查看键值是否存在
etcdctl get "name:有勇气的牛排"
# 输出:
# name:有勇气的牛排
# 正在编程

6.4 查看租约剩余时间
etcdctl lease timetolive $LEASE_ID
etcdctl lease timetolive 694d9853f094a718
6.5 等待30秒后再次查询
etcdctl get "name:有勇气的牛排"

没有输出,键已过期被 etcd 自动删除
6.6 可选:续约(keepAlive)
启动续约机制
etcdctl lease keep-alive $LEASE_ID
<h2><a id="1__0"></a>1 前言</h2>
<p><code>etcd</code> 是一个开源的 <strong>分布式键值存储系统</strong>,常被用于在分布式系统中保存配置数据、服务发现信息和协调数据。它由 CoreOS 开发,现在是 <strong>CNCF(云原生计算基金会)</strong> 的毕业项目,和 Kubernetes 等项目一起发展。</p>
<p>一句话概括</p>
<p>etcd 是一个<strong>强一致性、高可用性、分布式的键值数据库</strong>,广泛用于<strong>服务发现、配置管理、协调任务等场景</strong>,特别是在 Kubernetes 中充当核心的<strong>数据存储中心</strong>。</p>
<h3><a id="11__8"></a>1.1 核心特性</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>强一致性(CP)</strong></td>
<td>基于 Raft 共识算法,保证数据一致性</td>
</tr>
<tr>
<td><strong>高可用性</strong></td>
<td>支持集群部署,节点故障时可继续服务</td>
</tr>
<tr>
<td><strong>分布式架构</strong></td>
<td>可水平扩展,集群内数据自动同步</td>
</tr>
<tr>
<td><strong>Watch机制</strong></td>
<td>支持客户端监听键的变动,适合事件驱动系统</td>
</tr>
<tr>
<td><strong>支持事务操作</strong></td>
<td>提供原子操作(如比较并交换)</td>
</tr>
<tr>
<td><strong>TLS 安全通信</strong></td>
<td>提供客户端和服务端双向认证、数据加密</td>
</tr>
</tbody>
</table>
<h3><a id="12_etcd_19"></a>1.2 etcd与其他组件对比</h3>
<table>
<thead>
<tr>
<th>比较项</th>
<th>etcd</th>
<th>Consul</th>
<th>Zookeeper</th>
</tr>
</thead>
<tbody>
<tr>
<td>协议</td>
<td>Raft</td>
<td>Raft</td>
<td>Zab</td>
</tr>
<tr>
<td>数据模型</td>
<td>KV(层级)</td>
<td>KV(扁平)</td>
<td>树结构(类似文件系统)</td>
</tr>
<tr>
<td>Watch机制</td>
<td>原生支持(事件推送)</td>
<td>支持(长轮询)</td>
<td>支持(监听)</td>
</tr>
<tr>
<td>常见用途</td>
<td>K8s存储、配置中心</td>
<td>服务发现</td>
<td>分布式协调、锁</td>
</tr>
</tbody>
</table>
<h3><a id="_28"></a>场景举例</h3>
<table>
<thead>
<tr>
<th>场景</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>服务临时注册</td>
<td>把服务注册为 <code>service/host=127.0.0.1:8080</code>, 过期即下乡</td>
</tr>
<tr>
<td>临时权限令牌</td>
<td><code>/token/abc123</code> 30秒后自动失效</td>
</tr>
<tr>
<td>分布式锁</td>
<td>借助租约实现锁的自动释放(防止死锁)</td>
</tr>
</tbody>
</table>
<h2><a id="2__36"></a>2 安装</h2>
<h3><a id="21__38"></a>2.1 单机安装</h3>
<h4><a id="211__40"></a>2.1.1 下载与配置</h4>
<pre><div class="hljs"><code class="lang-shell">mkdir /usr/local/soft/etcd
cd /usr/local/soft/etcd
mkdir /usr/local/soft/etcd/data
mkdir /usr/local/soft/etcd/logs
</code></div></pre>
<pre><div class="hljs"><code class="lang-shell">wget https://github.com/etcd-io/etcd/releases/download/v3.6.4/etcd-v3.6.4-linux-amd64.tar.gz
tar -zxvf etcd-v3.6.4-linux-amd64.tar.gz
cp /usr/local/soft/etcd/etcd-v3.6.4-linux-amd64/etcd* /usr/local/bin/
</code></div></pre>
<p>启动</p>
<pre><div class="hljs"><code class="lang-shell">./etcd --data-dir=/usr/local/soft/etcd/data/etcd &> /usr/local/soft/etcd/logs/etcd.log &
</code></div></pre>
<p>默认监听 2379(客户端)、2380(集群内部)</p>
<h4><a id="_66"></a>检查是否启动成功</h4>
<p>方式一:查看进程是否存在</p>
<pre><div class="hljs"><code class="lang-shell">ps aux | grep etcd
</code></div></pre>
<p>方式二:确认端口监听状态</p>
<pre><div class="hljs"><code class="lang-shell">ss -tunlp | grep etcd
</code></div></pre>
<p>可以通过 <code>curl</code> 请求 etcd 的健康检查接口,如果是空返回、报错或连接失败,说明 etcd 没有正常启动。</p>
<pre><div class="hljs"><code class="lang-shell">curl http://127.0.0.1:2379/health
</code></div></pre>
<h3><a id="212_Docker_86"></a>2.1.2 Docker快速部署</h3>
<pre><div class="hljs"><code class="lang-shell">docker run -d \
-p 2379:2379 -p 2380:2380 \
--name etcd \
quay.io/coreos/etcd \
/usr/local/bin/etcd \
--name s1 \
--initial-advertise-peer-urls http://localhost:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://localhost:2379 \
--initial-cluster s1=http://localhost:2380
</code></div></pre>
<h2><a id="3__102"></a>3 基础操作案例</h2>
<h3><a id="31__104"></a>3.1 写入键值对</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl put foo "bar"
</code></div></pre>
<h3><a id="32__110"></a>3.2 读取键值</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl get foo
<span class="hljs-meta"># </span><span class="language-bash">输出:</span>
<span class="hljs-meta"># </span><span class="language-bash">foo</span>
<span class="hljs-meta"># </span><span class="language-bash">bar</span>
</code></div></pre>
<h3><a id="33__119"></a>3.3 删除键值</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl del foo
</code></div></pre>
<h2><a id="4__125"></a>4 目录式存储&前缀查询</h2>
<p>etcd本身是KV模型,但支持“类目录结构”的key</p>
<pre><div class="hljs"><code class="lang-shell">etcdctl put /config/db/host 127.0.0.1
etcdctl put /config/db/port 3306
etcdctl put /config/api/token abcdef
</code></div></pre>
<p>查询某个前缀下所有键</p>
<pre><div class="hljs"><code class="lang-shell">etcdctl get /config --prefix
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/c62a45bfbae1e6889038b49bace08071.png" alt="image.png" /></p>
<h2><a id="5_Watch__143"></a>5 Watch 键变化(监听)</h2>
<p>用于观察键是否被改动</p>
<pre><div class="hljs"><code class="lang-shell">etcdctl watch name
</code></div></pre>
<p>另开一个终端执行</p>
<pre><div class="hljs"><code class="lang-shell">etcdctl put name 有勇气的牛排
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/8fb2f2f798ca034688a31f1a39594cf2.png" alt="image.png" /></p>
<h2><a id="6_Lease_TTL_159"></a>6 Lease(租约)与 TTL</h2>
<p>用于设置自动过期的键(如临时服务注册、锁等)</p>
<h3><a id="61_60_163"></a>6.1 创建租约(60秒)</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl lease grant 60
<span class="hljs-meta"># </span><span class="language-bash">输出:lease 694d9853f094a70f granted with TTL(60s)</span>
</code></div></pre>
<p>lease ID:694d9853f094a70f</p>
<h3><a id="62__172"></a>6.2 使用租约写入键值</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl put "name:有勇气的牛排" "正在编程" --lease=$LEASE_ID
</code></div></pre>
<pre><div class="hljs"><code class="lang-shell">etcdctl put "name:有勇气的牛排" "正在编程" --lease=694d9853f094a713
</code></div></pre>
<h3><a id="63__182"></a>6.3 查看键值是否存在</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl get "name:有勇气的牛排"
<span class="hljs-meta">
# </span><span class="language-bash">输出:</span>
<span class="hljs-meta"># </span><span class="language-bash">name:有勇气的牛排</span>
<span class="hljs-meta"># </span><span class="language-bash">正在编程</span>
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/77945a9d672a57f6ca70e05465703369.png" alt="image.png" /></p>
<h3><a id="64__194"></a>6.4 查看租约剩余时间</h3>
<p><code>etcdctl lease timetolive $LEASE_ID</code></p>
<pre><div class="hljs"><code class="lang-shell">etcdctl lease timetolive 694d9853f094a718
</code></div></pre>
<h3><a id="65_30_202"></a>6.5 等待30秒后再次查询</h3>
<pre><div class="hljs"><code class="lang-shell">etcdctl get "name:有勇气的牛排"
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/65e1dc900e8920c66c8670811718a742.png" alt="image.png" /></p>
<p>没有输出,键已过期被 etcd 自动删除</p>
<h3><a id="66_keepAlive_212"></a>6.6 可选:续约(keepAlive)</h3>
<p>启动续约机制</p>
<pre><div class="hljs"><code class="lang-shell">etcdctl lease keep-alive $LEASE_ID
</code></div></pre>
评论区