分布式一致性工具课题
CAP定理
在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
- 一致性(Consistency):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
- 可用性(Availability):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
- 分区容忍性(Partition tolerance):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
根据定理,分佈式系统只能满足三项中的两项而不可能满足全部三项[4]。理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。
参考:https://zh.wikipedia.org/wiki/CAP%E5%AE%9A%E7%90%86
一致性算法
一致性算法主要有Paxos、Raft、ZAB三种:
其中Paxos深入理解起来有难度,在实际应用中也难以实现。Raft相当于简化版的Multi Paxos,ZAB和Raft原理一致,部分标签命名方式不一样,实际应用中比较多的应该是Raft算法。
参考:https://www.jianshu.com/p/9a9290fb0727
学习参考视频:https://www.bilibili.com/video/av21667358/?spm_id_from=333.788.videocard.0
工具选型
-
名称 优点 缺点 接口 一致性 zookeeper 1.功能强大,不仅仅只是服务发现
2.提供watcher机制能实时获取服务提供者的状态
3.dubbo等框架支持1.没有健康检查
2.需在服务中集成sdk,复杂度高
3.不支持多数据中心sdk Paxos consul 1.简单易用,不需要集成sdk
2.自带健康检查
3.支持多数据中心
4.提供web管理界面1.不能实时获取服务信息的变化通知 http/dns Raft etcd 1.简单易用,不需要集成sdk
2.可配置性强1.没有健康检查
2.需配合第三方工具一起完成服务发现
3.不支持多数据中心http Raft
综合考虑并参考公司本身用的是Etcd,本次课题选择使用Etcd集群搭建进行静态发现和DNS动态发现实验测试。
Etcd集群搭建
1、简介
Etcd 是 CoreOS 推出的高可用的键值存储系统,主要用于k8s集群的服务发现等,而本身 Etcd 也支持集群模式部署,从而实现自身高可用。Etcd构建自身高可用集群主要有三种形式:
- 静态发现: 预先已知 Etcd 集群中有哪些节点,在启动时直接指定好 Etcd 的各个 node 节点地址
- Etcd 动态发现: 通过已有的 Etcd 集群作为数据交互点,然后在扩展新的集群时实现通过已有集群进行服务发现的机制
- DNS 动态发现: 通过 DNS 查询方式获取其他节点地址信息
本次课题主要学习静态发现和DNS动态发现
2、静态发现
2.1、环境准备
本次课题没有限制环境搭建方式,CenoOS官方提供了Etcd的rpm,可以通过yum直接安装。
yum install etcd -y
分别安装到3台虚拟机上,节点配置如下:
节点 | 地址 |
---|---|
etcd1 | 192.168.100.101 |
etcd2 | 192.168.100.102 |
etcd3 | 192.168.100.103 |
2.2、修改Etcd配置
#编辑配置文件
[root@etcd1 ~]# vim /etc/etcd/etcd.conf
#配置如下
# 节点名称
ETCD_NAME=etcd1
# 数据存放位置
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
# 监听其他 Etcd 实例的地址
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
# 监听客户端地址
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
# 通知其他 Etcd 实例地址
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.100.101:2380"
# 初始化集群内节点地址
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.100.101:2380,etcd2=http://192.168.100.102:2380,etcd3=http://192.168.100.103:2380"
# 初始化集群状态,new 表示新建
ETCD_INITIAL_CLUSTER_STATE="new"
# 初始化集群 token
ETCD_INITIAL_CLUSTER_TOKEN="mritd-etcd-cluster"
# 通知 客户端地址
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.100.101:2379,http://192.168.100.101:4001"
etcd的单机使用参考:https://www.hi-linux.com/posts/40915.html
2.3、测试集群
集群搭建好后,分别在各个节点上启动etcd。在任意节点执行etcdctl mamber list
即可列出所有集群节点信息,同时可以使用 etcdctl cluster-health
检查集群健康状态。
#启动etcd
[root@etcd1 ~]# systemctl start etcd
#查看节点信息
[root@etcd1 ~]# etcdctl member list
1dd433ececcf25d7: name=etcd3 peerURLs=http://192.168.100.103:2380 clientURLs=http://192.168.100.103:2379,http://192.168.100.103:4001 isLeader=false
378e354d4ff62108: name=etcd2 peerURLs=http://192.168.100.102:2380 clientURLs=http://192.168.100.102:2379,http://192.168.100.102:4001 isLeader=true
50c741cfee76183e: name=etcd1 peerURLs=http://192.168.100.101:2380 clientURLs=http://192.168.100.101:2379,http://192.168.100.101:4001 isLeader=false
#查看节点健康状态
[root@etcd1 ~]# etcdctl cluster-health
member 1dd433ececcf25d7 is healthy: got healthy result from http://192.168.100.103:2379
member 378e354d4ff62108 is healthy: got healthy result from http://192.168.100.102:2379
member 50c741cfee76183e is healthy: got healthy result from http://192.168.100.101:2379
cluster is healthy
3、dnsmasq搭建
-
Etcd 在基于DNS做服务发现时,实际上是利用 DNS的SRV记录不断轮训查询实现的,所以首先要加入 DNS SRV记录,故采用dnsmasq作为dns服务器。
-
配置一台虚拟机的ip地址为192.168.100.104搭建dnsmasq。
3.1、安装dnsmasq
#安装dnsmasq
[root@dnsmasq ~]# yum install -y dnsmasq
3.2、主要配置
#编辑配置文件
[root@dnsmasq ~]# vim /etc/dnsmasq.conf
#主要配置如下
# 上游 DNS 定义
resolv-file=/etc/resolv.dnsmasq.conf
# 取消从本地 hosts 读取
no-hosts
# 监听地址
listen-address=127.0.0.1,192.168.100.104
# 指定本地 dns host 配置
addn-hosts=/etc/dnsmasq.hosts
# 设置 dns 缓存大小
cache-size=150
3.3、DNS解析配置
# 增加本地回环
[root@dnsmasq ~]# echo 'nameserver 127.0.0.1' >> /etc/resolv.conf
# 增加本地 hosts
[root@dnsmasq ~]# cp /etc/hosts /etc/dnsmasq.hosts
# 添加上游 DNS 服务器
[root@dnsmasq ~]# echo 'nameserver 8.8.8.8' >> /etc/resolv.dnsmasq.conf
[root@dnsmasq ~]# echo 'nameserver 192.168.100.100' >> /etc/resolv.dnsmasq.conf
3.4、测试
#安装bind-utils工具包
[root@dnsmasq ~]# yum -y install bind-utils
#使用dig命令测试
[root@dnsmasq ~]# dig @192.168.100.104 www.baidu.com
; <<>> DiG 9.9.4-RedHat-9.9.4-74.el7_6.1 <<>> @192.168.100.104 www.baidu.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23167
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.baidu.com. IN A
;; ANSWER SECTION:
www.baidu.com. 1082 IN CNAME www.a.shifen.com.
www.a.shifen.com. 183 IN A 180.97.33.107
www.a.shifen.com. 183 IN A 180.97.33.108
;; Query time: 0 msec
;; SERVER: 192.168.100.104#53(192.168.100.104)
;; WHEN: 五 7月 05 05:49:04 CST 2019
;; MSG SIZE rcvd: 104
4、DNS动态发现
4.1、创建DNS记录
# 增加 SRV 记录
[root@dnsmasq ~]# vim /etc/dnsmasq.conf
# 增加内容如下
srv-host=_etcd-server._tcp.mritd.me,etcd1.mritd.me,2380,0,100
srv-host=_etcd-server._tcp.mritd.me,etcd2.mritd.me,2380,0,100
srv-host=_etcd-server._tcp.mritd.me,etcd3.mritd.me,2380,0,100
# 然后增加对应的域名解析
[root@dnsmasq ~]# vim /etc/dnsmasq.hosts
# 增加内容如下
192.168.100.101 etcd1.mritd.me
192.168.100.102 etcd2.mritd.me
192.168.100.103 etcd3.mritd.me
4.2、重启dnsmasq测试是否成功
#重启服务
[root@dnsmasq ~]# systemctl restart dnsmasq
#查询SRV
[root@dnsmasq ~]# dig @192.168.100.104 +noall +answer SRV _etcd-server._tcp.mritd.me
_etcd-server._tcp.mritd.me. 0 IN SRV 0 100 2380 etcd2.mritd.me.
_etcd-server._tcp.mritd.me. 0 IN SRV 0 100 2380 etcd1.mritd.me.
_etcd-server._tcp.mritd.me. 0 IN SRV 0 100 2380 etcd3.mritd.me.
#查询域名解析
[root@dnsmasq ~]# dig @192.168.100.104 +noall +answer etcd1.mritd.me etcd2.mritd.me etcd3.mritd.me
etcd1.mritd.me. 0 IN A 192.168.100.101
etcd2.mritd.me. 0 IN A 192.168.100.102
etcd3.mritd.me. 0 IN A 192.168.100.103
4.3、修改Etcd
Linux 系统默认从 /etc/resolv.conf
配置文件读取 DNS 服务器,为了让 Etcd 能够从 dnsmasq 服务器获取自定义域名解析,要修改3台 Etcd 服务器的 /etc/resolv.conf
文件
#编辑resolv.conf文件
[root@etcd1 ~]# vim /etc/resolv.conf
# 保证我们自定义的 dnsmasq 服务器在第一位
# Generated by NetworkManager
search lan lan.
nameserver 192.168.100.104
nameserver 192.168.100.2
nameserver 127.0.0.1
4.4、配置Etcd
修改 Etcd 配置文件,开启 DNS 服务发现,主要是删除掉 ETCD_INITIAL_CLUSTER
字段(用于静态服务发现),并指定 DNS SRV 域名(ETCD_DISCOVERY_SRV
)
# 编辑 etcd 配置文件
[root@etcd1 ~]# vim /etc/etcd/etcd.conf
# 节点名称
ETCD_NAME=etcd1
# 数据存放位置
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
# 监听其他 Etcd 实例的地址
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
# 监听客户端地址
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
# 通知其他 Etcd 实例地址
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.100.101:2380"
# 初始化集群内节点地址(用于静态发现)
# ETCD_INITIAL_CLUSTER="etcd1=http://192.168.100.101:2380,etcd2=http://192.168.100.102:2380,etcd3=http://192.168.100.103:2380"
# 初始化集群状态,new 表示新建
ETCD_INITIAL_CLUSTER_STATE="new"
# 初始化集群 token
ETCD_INITIAL_CLUSTER_TOKEN="mritd-etcd-cluster"
# 通知 客户端地址
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.100.101:2379,http://192.168.100.101:4001"
#指定DNS SRV域名
#ETCD_DISCOVERY_SRV="mritd.me"
4.5、测试动态发现
# 由于端口并未绑定到 0.0.0.0,所以需要指定 etcd 服务器
# 静态服务发现是绑定了 0.0.0.0
# 出于安全考虑最好只监听局域网
[root@etcd1 ~]# etcdctl --endpoints "http://etcd1.mritd.me:2379,http://etcd1.mritd.me:4001" member list
1dd433ececcf25d7: name=etcd3 peerURLs=http://192.168.100.103:2380 clientURLs=http://192.168.100.103:2379,http://192.168.100.103:4001 isLeader=false
378e354d4ff62108: name=etcd2 peerURLs=http://192.168.100.102:2380 clientURLs=http://192.168.100.102:2379,http://192.168.100.102:4001 isLeader=true
50c741cfee76183e: name=etcd1 peerURLs=http://192.168.100.101:2380 clientURLs=http://192.168.100.101:2379,http://192.168.100.101:4001 isLeader=false