介绍
etcd 是 CoreOS 团队发起的一个开源项目,实现了分布式键值存储和服务发现,etcd 和 ZooKeeper/Consul 非常相似,都提供了类似的功能,以及 REST API 的访问操作,具有以下特点:
- 简单:安装和使用简单,提供了 REST API 进行操作交互
- 安全:支持 HTTPS SSL 证书
- 快速:支持并发 10 k/s 的读写操作
- 可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性
在k8s中的使用
Etcd 是 Kubernetes 集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息。
和Redis的比较
- etcd 的红火来源于 k8s 用 etcd 做服务发现,而 redis 的兴起则来源于 memcache 缓存本身的局限性。
- etcd 的重点是利用 raft 算法做分布式一致性,强调各个节点之间的通信、同步,确保各节点数据和事务的一致性,使得服务发现工作更稳定;
- redis 也可以做主从同步和读写分离,但节点一致性强调的是数据,不是事务。redis 的注册和发现只能通过 pub 和 sub 实现,安全性不能保证(断线重连之后不会将历史信息推送给客户端,需要自己做一个定时轮询),延时也比 etcd v3 高。
- etcd v3 的底层采用 boltdb 做存储,value 直接持久化;redis 是一个内存数据库,它的持久化方案有 aof 和 rdb,在宕机时都或多或少会丢失数据。
- etcd v3 只能通过 gRPC 访问,而 redis 可以通过 http 访问,因此 etcd 的客户端开发工作量高很多。
- redis 的性能比 etcd 强。
- redis 的 value 支持多种数据类型。
- etcd 是用 go 开发的,和 k8s 在同一个生态下
使用docker安装
version: '2'
networks:
app-tier:
driver: bridge
services:
Etcd:
image: 'bitnami/etcd:3.5.1'
environment:
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379
ports:
- 2379:2379
- 2380:2380
networks:
- app-tier
创建 docker-compose.yml 文件,镜像版本为3.5.1,默认不支持http访问
docker-compose up -d
启动容器
通过http请求访问
注意开启防火墙对端口2379的访问
http://ip:2379/version
查询版本,3.5.1
http://ip:2379/v2/keys
默认不支持http访问,返回404 page not found
开启http访问
version: '2'
networks:
app-tier:
driver: bridge
services:
Etcd:
image: 'bitnami/etcd:3.5.1'
environment:
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379
- ETCD_ENABLE_V2=true
ports:
- 2379:2379
- 2380:2380
networks:
- app-tier
增加ETCD_ENABLE_V2=true
的环境变量,重新启动
docker-compose down
docker-compose up -d
添加删除及查询
设置键值
删除键值
查询键值
客户端访问
.\etcdctl.exe --endpoints=http://ip:2379 get age
获取值
.\etcdctl.exe --endpoints=http://ip:2379 put name lisi2
设置键值
注意,v2和v3的数据是相互隔离的
java客户端访问
<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>0.5.11</version>
</dependency>
import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.KV;
import io.etcd.jetcd.KeyValue;
import io.etcd.jetcd.kv.GetResponse;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
public class TestEtcdClient {
public static void main(String[] args) throws Exception {
testGetValue();
// testPutKey();
}
private static void testPutKey() {
KV kvClient = createClient().getKVClient();
ByteSequence key = ByteSequence.from("date".getBytes());
ByteSequence value = ByteSequence.from(new Date().toString().getBytes());
kvClient.put(key, value);
}
private static void testGetValue() throws Exception {
KV kvClient = createClient().getKVClient();
ByteSequence key = ByteSequence.from("name".getBytes());
CompletableFuture<GetResponse> getFuture = kvClient.get(key);
GetResponse response = getFuture.get();
for (KeyValue keyValue : response.getKvs()) {
System.out.println(keyValue.getKey().toString() + ":" + keyValue.getValue().toString());//name:lisi2
}
}
private static Client createClient() {
return Client.builder().endpoints("http://ip:2379").build();
}
}
v2版本和v3版本的区别
v2
- 专注于key-value存储,而不是一个完整的数据库;
- 通过HTTP + JSON的方式暴露给外部API;
- watch机制提供持续监听某个key变化的功能,以及基于TTL的key的自动过期机制。
v3
- 二进制取代字符串:通过gRPC进行通信,代替了v2版本的HTTP+JSON格式;
- 减少TCP连接:使用HTTP/2协议,同一个连接可以同时处理多个请求,摒弃多个请求需要建立多个连接的方式。
- 实时监听key的更新:解决v2中途key的数据更新,客服端不会感知的问题;
- 多路复用:这个可以想到select和epool模型,就是一个客户之前需要建立多个TCP连接,现在只需要建立一个即可。
- 保存历史数据:摈弃v2的“滑动窗口”式设计,通过MVCC机制,保存了所有的历史数据;
- 数据落磁盘:因为要保存历史数据,数据量态度,不适合全内存存储,使用BoltDB存储;
- 查询优化:摒弃v2的目录式层级化设计,使用线段树优化查询。
参考
docker 安装 ETCD 及 etcd 使用
Etcd 解析
etcd和redis比较
ETCD系列教程3 - 深入ETCD